accessing item/effect modifiers in ash script

landstander

New member
I'm returning to kol after nearly a decade away, crazy this game is still kicking. I see some of your names and get flashbacks and nostalgia from high school. Its kind of weird.

Anyway, I need to farm a bunch of meat to make up for giving all my sweet loot away and I am trying to make my farming script smart enough to check mall prices of +meat% and +familiar weight items and buy them if their cost is cheaper than what I expect to get from the bonus. Something like

Code:
boolean is_meat_item_economical(item i, int meat_per_adv, float meat_buff_percent, int turns){
  int purchase_price = mall_price(i);
  return ((meat_per_adv * meat_buff_percent) * turns) > purchase_price;
}

Ideally I would be able to loop over items looking for ones that contains meat/item/familiar buffs so I wouldnt need to keep hard coded lists around I'd need to update to take advantage of new items. The problem is I cant find any way of determining what the meat (/item/familiar weight/foo) buff and number of turns an effect lasts at runtime. I can get the item, the effect and the "effect modifier" but never enough information to do what I need.

Code:
void main(){
  print($item[love song of icy revenge]);
  print(effect_modifier($item[love song of icy revenge], "effect"));
  print(numeric_modifier(effect_modifier($item[love song of icy revenge], "effect"), "familiar weight"));
}

Prints:
love song of icy revenge
Cold Hearted
1.0

I found the source file kolmafia uses internally (from what I can tell): https://sourceforge.net/p/kolmafia/code/HEAD/tree/src/data/modifiers.txt which is probably perfect but I dont think I can make use of it and I see other scripts seemingly making their own databases that end up in the data/ in the installation directiony.

Am I missing something obvious? Is there a simpler way? At this point I'll just hard code my own lists when I have time, I havent figured out how to do file IO yet, need to dig into a more complicated script like Universal Recovery to see what they do. Any tips are appreciated, thanks.
 

landstander

New member
Yes, I reference that from time to time. Veracity doesnt do something exactly like this, though I think there are a couple hard coded effect's they check for and maintain, skills they have that dont require purchasing iirc.

I do use things like SmartStasis, an auto dinseylandfill quest script and some others to speed things up, but I didnt like the existing meat farming scripts I saw and wanted to stitch together my own. This is also for my own fun and interest as well.
 

heeheehee

Developer
Staff member
You probably want to use whatif (aka speculate). I usually get lazy and just linearize meat drop from familiars, since it's "close enough" in the regime I care about, though.

Code:
> ash numeric_modifier("Generated:_spec", "Meat Drop")

Returned: 76.49719092257398

> speculate up empathy; up leash of linguini

Familiar Weight  18.00 (+10.00)
Meat Drop  116.65 (+40.16)

> ash numeric_modifier("Generated:_spec", "Meat Drop")
 

Veracity

Developer
Staff member
The problem is I cant find any way of determining what the meat (/item/familiar weight/foo) buff and number of turns an effect lasts at runtime. I can get the item, the effect and the "effect modifier" but never enough information to do what I need.
You have access to everything in modifiers.txt.

Code:
[color=green]> ash string_modifier( $item[ love song of icy revenge ], "Modifiers" )[/color]

Returned: Effect: "Cold Hearted", Effect Duration: 5

[color=green]> ash numeric_modifier( $item[ love song of icy revenge ], "Effect Duration" )[/color]

Returned: 5.0
 

landstander

New member
You have access to everything in modifiers.txt.

Code:
[color=green]> ash string_modifier( $item[ love song of icy revenge ], "Modifiers" )[/color]

Returned: Effect: "Cold Hearted", Effect Duration: 5

[color=green]> ash numeric_modifier( $item[ love song of icy revenge ], "Effect Duration" )[/color]

Returned: 5.0

See, I thought I was missing something. The api reference is very helpful but rarely as thorough as I'd like. I havent gotten to the point of looking at kolmafia source code yet but suspect ill be there soon. I'm spoiled by strongly typed languages (which ash is from what I can tell, but isnt used to its fullest in some cases like there not being a modifier class/enum that you could use here) and debuggers and unit tests.

Do you have any tips on discovering what properties are available on an object, e.g. what are the options I can provide as the second parameter to *_modifier(). I tried a couple methods like to_string() but it just printed the name. Usually I resort to looking at how other scripts do similar tasks but I cant always find what I am looking for.

Edit: ash string_modifier( $item[ love song of icy revenge ], "Modifiers" ) will work for this case, but general discoverability tips are still appreciated.
 
Last edited:

ckb

Minion
Staff member
I wrote this a while ago, but I believe it does what you want. As a side note, don't expect to regularly find anything profitable in the mall worth using.

PHP:
void MeatBuff() {
	float [item] ilist;
	int base = 250;
	foreach it in $items[] {
		if (it.fullness==0 && it.inebriety==0 && it.spleen==0 && it.tradeable==true && it.usable==true) {
			effect eff = effect_modifier(it, "Effect");
			float toe = numeric_modifier(it, "Effect Duration");
			float mtd = numeric_modifier(eff, "Meat Drop");
			float gain = base*mtd*toe/100.0;
			if (gain>0.0) {
				int hpc = mall_price(it);
				//print(it+" : +"+mtd+" X "+toe+" = "+gain+" @ "+hpc,"blue");
				if (gain/to_float(hpc) > 1.10) {
					float cpt = (gain/hpc);
					ilist[it] = cpt;
					//ilist[it] = gain;
				}
			}
		}
	}
	
	//sort ilist by value;
	string rpt = "";
	rpt += "<table border=1 cellpadding=1 cellspacing=1>";
	rpt += "<tr><td><b>ITEM</b></td><td><b>CPT</b></td></tr>";
	foreach ii in ilist {
		string col = "red";
		if (have_effect(effect_modifier(ii, "Effect"))>0) { col="green"; }
		rpt += "<tr><td  style=color:"+col+">"+ii+"</td><td>"+to_string(ilist[ii],"%.5f")+"</td></tr>";
	}
	rpt += "</table>";
	print_html(rpt);
	
}
 

landstander

New member
Code:
modref
is a good way of seeing the modifiers you can check for.

Good one, thanks!

I wrote this a while ago, but I believe it does what you want. As a side note, don't expect to regularly find anything profitable in the mall worth using.

Thanks, Ill check it out tomorrow when I have time to play around with kol some more. And yes, I also expect this to rarely be beneficial. All but the most common items, like the manual that gives +300% meat in barfmountain (which I have plenty of anyway), should basically balance out to as much as you would earn using it, because economics. But if I can script it I might as well look.
 

landstander

New member
I attached the script I came up with in case anyone in the future is interested. It will calculate meat drop buffs and familiar weight buffs (assumes hobo monkey right now). For normal farming, it is pretty rare to find any economic meat or familiar weight buff items in the mall. However, if you are fighting copies of knob goblin embezzlers everyday it actually buys several buff items.

You can just run it to get a simulation, the first time each day will be a little slow as it has to load up a map of items to check against but its very quick after that. You'll need to explicitly turn off the simluation mode using the
Code:
farming_econ_simulate
property if you want to use it as a between battle script. See the source code for what else you can change.

Here is the code relevant to the immediate question I asked about how to look up item effects:

Code:
static effect[item] meat_buff_items;
static effect[item] meat_buff_ignore;
static effect[item] familiar_buff_items;
static effect[item] familiar_buff_ignore;

boolean potentially_useable(item i){
  return(i.fullness == 0 && i.inebriety == 0 && i.spleen == 0 && i.usable == true && i.tradeable==true);
}

static{
  meat_buff_ignore[$item[How to Avoid Scams]] = effect_modifier($item[How to Avoid Scams], "Effect");
  meat_buff_ignore[$item[Uncle Greenspan's Bathroom Finance Guide]] = effect_modifier($item[Uncle Greenspan's Bathroom Finance Guide], "Effect");

  foreach it in $items[] {
    if(potentially_useable(it)){
      effect e = effect_modifier(it, "Effect");
      float duration = numeric_modifier(it, "Effect Duration");
      float meat_drop = numeric_modifier(e, "Meat Drop");
      float familiar_weight = numeric_modifier(e, "Familiar Weight");
      if(meat_drop > 0.0 && !(meat_buff_ignore contains it)){
        meat_buff_items[it] = e;
      }
      if(familiar_weight > 0.0 && !(familiar_buff_ignore contains it)){
        familiar_buff_items[it] = e;
      }
    }
  }
}
 

Attachments

  • farming_econ_between_battle.ash
    5.8 KB · Views: 31
Top