playing around with new maximize()

roippi

Developer
So now with the new maximize() signature you can do stuff like price analyses:

what are the most meat-effective things for maximizing moxie?

Code:
> maxtest moxie

Maximizing...
5976 combinations checked, best score 2,388.00
serum of sarcasm: 2.141809290953545
Connery's Elixir of Audacity: 1.1347150259067358
dark potion: 1.095
tomato juice of powerful power: 1.0354609929078014
spooky wad: 0.9668508287292817
potion of temporary gr8tness: 0.7891891891891892
shot of flower schnapps: 0.4375
Crimbo candied pecan: 0.43
Crimbo fudge: 0.43
Crimbo peppermint bark: 0.43
breath mint: 0.43
hot wad: 0.4069767441860465
Tasty Fun Good rice candy: 0.39814814814814814
Trivial Avocations Card: Where?: 0.3107142857142857
queen cookie: 0.30469565217391303
CSA bravery badge: 0.3
sleaze wad: 0.29772727272727273
Trivial Avocations Card: What?: 0.29
pirate pamphlet: 0.29
Black Body™ spray: 0.29
Trivial Avocations Card: Who?: 0.29
Trivial Avocations Card: When?: 0.2806451612903226
twinkly wad: 0.24857142857142858
seal-brain elixir: 0.24333333333333335
stench wad: 0.19333333333333333
cold-filtered water: 0.16528301886792454
Angry Farmer candy: 0.15693430656934307
Taco Dan's Taco Stand Chimichangarita: 0.15087719298245614
Black No. 2: 0.15
handsomeness potion: 0.14982578397212543
roasted marshmallow: 0.14333333333333334
knight cookie: 0.13482108503270487
tube of hair oil: 0.13384615384615384
canteen of wine: 0.13292867981790593
pressurized potion of pulchritude: 0.13140657032851644
yellow polka-dot oyster egg: 0.13082706766917293
mafia aria: 0.12352941176470589
elven <i>limbos</i> gingerbread: 0.1095
haggis-wrapped haggis-stuffed haggis: 0.1
cold wad: 0.09886363636363636
jellyfish gel: 0.0911304347826087
llama lama gong: 0.0880672268907563
weremoose spit: 0.08739495798319327
unstable DNA: 0.087
maple syrup: 0.07543859649122807
gremlin mutagen: 0.073
sensitive poetry journal: 0.07087889833940866
blob-shaped Crimbo cookie: 0.060833333333333336
extra-potent gremlin mutagen: 0.05407407407407407
Lobos Mints: 0.054018732302330646
vial of porquoise juice: 0.0503448275862069
Crimbo fudge: 0.05
lime-and-chile-flavored chewing gum: 0.05
roofie: 0.05
dubious peppermint: 0.04833333333333333
prismatic wad: 0.047636363636363636
sham champagne: 0.04517792676637442
flask of porquoise juice: 0.042731707317073174
jug of porquoise juice: 0.03305660377358491
lime supersucker: 0.03125
yellow candy heart: 0.03
orange candy heart: 0.03
lavender candy heart: 0.03
green candy heart: 0.03
pink candy heart: 0.03
white candy heart: 0.03
llama lama gong: 0.029243697478991595
eyedrops of newt: 0.027932960893854747
shaving cream: 0.02702702702702703
super-spiky hair gel: 0.026785714285714284
gummi canary: 0.02
Climate Colada: 0.01638524077548468
banana smoothie: 0.014035087719298246
Knob Goblin love potion: 0.011764705882352941
mariachi toothpaste: 0.010186046511627907
rocky road ice cream: 0.008443373493975904
glimmering great tit feather: 0.007818181818181818
bottle of pirate juice: 0.00761556621734826
pawn cookie: 0.0064516129032258064
Muschat: 0.00625
Ultrasoldier Serum: 0.0058791946308724835
sugar-coated pine cone: 0.005375
Aye Aye: 0.005050505050505051
cool cat elixir: 0.003614893360645861
lump of Saccharine Maple sap: 0.003504
bat-shaped Crimboween cookie: 0.00348
square CRIMBCOOKIE: 0.00348
Aye Aye, Captain: 0.003125
Aye Aye, Tooth Tooth: 0.0029411764705882353
orc paste: 0.002564102564102564
hair of the fish: 0.0017857142857142857
love song of naughty innuendo: 0.0017241379310344827
love song of icy revenge: 0.0011173184357541898
floaty sand: 0.0008460236886632825
toothbrush: 0.000588235294117647
powdered toad horn: 0.0001318181818181818
wreath-shaped Crimbo cookie: 0.00009688195991091314
none: 0.0
none: 0.0
none: 0.0
goofballs: 0.0
none: 0.0
box of sunshine: 0.0
none: 0.0
none: 0.0

Units are Score Per Meat, I believe? Anyway, code attached for those who want a starting place to do something similar.
 

Attachments

  • maxtest.ash
    649 bytes · Views: 48

nworbetan

Member
If you'd like to do something similar, you may sometimes also need to also multiply the Score Per Meat by the Duration of the boost. You can consider this a feature request for a "duration" or "turns" (or something along those lines) field in the record, or would the other thread be a better place for an official request?
 

roippi

Developer
If you'd like to do something similar, you may sometimes also need to also multiply the Score Per Meat by the Duration of the boost. You can consider this a feature request for a "duration" or "turns" (or something along those lines) field in the record, or would the other thread be a better place for an official request?

While a good idea, I'm not sure that information currently exists anywhere in mafia.
 

nworbetan

Member
Huh. I thought it was hidden in $effect[].all or something like that, but I don't see it there or statuseffects.txt or modifiers.txt. You kind of have to have a duration to do a benefit/cost analysis that's accurate for > 1 turn though.
 

xKiv

Active member
As I noted in one of the other threads, it's numeric_modifier(item,"Effect Duration") for items (use XXX), and turns_per_cast(skill) for skills (cast XXX).
It's not on effects because there are various ways to get the effect, with different durations.
Also, if you are doing per-duration analysis, you also want to know for how long does the player want to be maximized. If I only need to be maximized for 1 turn, I will probably take a 5-turn source over a 100-turn source (unless 1 of the 100-turn source costs less than 1 of the 5-turn source).
 

roippi

Developer
Right. Always forget about numeric_modifier. Remember that "Effect Duration" only works for potions (right now) so wads, foods, drinks, etc will have a 0 effect duration. As will !potion effects, due to disambiguation issues.

Code:
Showing results sorted by SPM:
serum of sarcasm: 2.141809290953545
Connery's Elixir of Audacity: 1.1347150259067358
dark potion: 1.095
tomato juice of powerful power: 1.0354609929078014
spooky wad: 0.9668508287292817
potion of temporary gr8tness: 0.7891891891891892
shot of flower schnapps: 0.4375
Crimbo candied pecan: 0.43
Crimbo fudge: 0.43
Crimbo peppermint bark: 0.43

Code:
Showing results sorted by SDPM:
serum of sarcasm: 10.709046454767726
Connery's Elixir of Audacity: 5.6735751295336785
tomato juice of powerful power: 5.177304964539007
seal-brain elixir: 4.866666666666666
potion of temporary gr8tness: 3.945945945945946
pirate pamphlet: 2.9
Black Body™ spray: 2.9
Crimbo candied pecan: 2.15
Crimbo fudge: 2.15
Crimbo peppermint bark: 2.15

You can obviously consider npc price, etc, this doesn't.
 

nworbetan

Member
So the fact that the durations are already available in mafia looks like good news to me. Does that mean that you're more or less likely to add a duration field to the record? I still think adding that field to the record would be very worthwhile, because of the wide variety of sources of effects that are included in the output.
 

xKiv

Active member
Duration of effects for consumables seems to be present at least in datafiles (spleenhit, fullness, inebriety) in last column (for example "10 A Little Bit Evil (+2 ML)" - requires some parsing). I don't know if that field is exposed to ash.
But those three also cost hard-limited resources (spleen, stomach, sirloin), so it doesn't make sense to compare them with things that "only" cost meat (in the immediate sense - everything costs adventures deep down, and most of those were gotten from organs).
 

roippi

Developer
So the fact that the durations are already available in mafia looks like good news to me. Does that mean that you're more or less likely to add a duration field to the record?

Less. If the information is available elsewhere (numeric_modifier) why duplicate it in the record? I could cram mall_price, npc_price, available_amount, etc into the record too, but won't because you can get access to all of those via ash.

Duration of effects for consumables seems to be present at least in datafiles (spleenhit, fullness, inebriety) in last column (for example "10 A Little Bit Evil (+2 ML)" - requires some parsing). I don't know if that field is exposed to ash.

It's not. The only use for that field AFAIK is the display on item manage panel.
 

nworbetan

Member
Less. If the information is available elsewhere (numeric_modifier) why duplicate it in the record?

I can think of a couple reasons for duplicating it in the record:

a) The new maximize() returns a list of X cli commands that will provide Y benefit, and Y feels like a vector to me, with both a magnitude (i.e. rec.score) and a direction (i.e. rec.duration), and both the magnitude and the direction are equally required to answer the question "what is actually going to happen when I use this rec.command X".

b) The durations are available "elsewhere_a" except when it's available "elsewhere_b", but in some other cases it's available "elsewhere_c", unless it's Monday in Arizona, in which case it's avalable "elsewhere_d" instead... all of which require parsing text from a list that looks like this, which seems like an awful lot of hoops to jump through to get such a basic piece of information.

c) The result of adding a duration field is that the new maximize() would be simultaneously more featureful and easier to use.

I do realize that I'm asking you to deal with an area of mafia that's kind of messy. I mean, neither one of us could even remember where the effect durations were hidden at the beginning of the thread. ;) But the fact that it's kind of messy is actually why I'm asking you to do this. Dealing with effects isn't as easy as it could be if some of the mess were cleaned up a little, and it would be awesome if you could make things easier.
 

roippi

Developer
You know that there's an $item field now, ya? There's no parsing involved anywhere, just plug the item into numeric_modifier.
 

nworbetan

Member
Except for the spells that aren't items, and the ballpit, and the tea party, and the mysterious island arena, and the summoning chamber, and the telescope, and the buffs that come from using free rests when you have an appropriate dwelling and...
 

roippi

Developer
And excepting spells, all of those things are definitely not known by any part of mafia, so...?

You have to understand what you're asking for before you ask it. "Give me access to x" is really two things: "make mafia aware of x for every possible y in the game" and then "give me access to x". Those are two separate feature requests with two vastly different scopes.
 

nworbetan

Member
It's looking like what I really want is a new proxy record added to $effects. Just because it's possible to return a duration from maximize() doesn't mean that's the correct place to ask for that information to be added.
 

xKiv

Active member
It would have to be added to *commands*. Not all commands are using items or casting skills.
From my POV as ash programmer, the sweet spot would probably be something like cli_estimate_duration("cli command here");, which would take the same string as a cli_execute and would try to return (shortest) duration of any effect gained by the command.
As java programmer, I would maybe ponder adding an estimate_duration() method to AbstractCommand, that would be called instead of run() and share much code with it (just without actually posting any requests or modifying mafia's internal state). Maaabe even generalized to a "what would the result of this be" speculation. For some cases, this might be trivial (ball pit: constant), for others a major PITA (I don't even want to look for them), and definitely a big heap of work.
I would probably not recommend to do it.

As a user, I expect most of those cases (= not simple item use or skill cast) to be limited use anyway.
 

nworbetan

Member
Such a proxy record should be added to $item[] or $skill[], not $effect[].

I can't disagree with that at all.

But the impetus for my request was the desire to start with any arbitrary $effect and retrieve the duration without needing to parse text to decide how to retrieve the duration. So the duration added to $items[] and $skills[] would get half-way there, and adding .skill and .item proxy fields to $effects[] would go the rest of the distance.

Don't get me wrong, I like the $effect[].default and $effect[].all fields just fine the way they are, but parsing the source of the effect out of them before deciding which of the umpteen forms of xxx_modifier("something", "something_else") feels wonky, even when it does eventually give you the info you're looking for. I'd be much happier with something simpler, more straight-forward, and somewhat closer to universal like:
PHP:
float desired_turns = 111;
int i;

if ($effect[eff].skill.duration > 0) {
    i = ceil(desired_turns / $effect[eff].skill.duration);
    use_skill(i, $effect[eff].skill);
} else if ($effect[eff].item.duration > 0) {
    i = ceil(desired_turns / $effect[eff].item.duration);
    use(i, $effect[eff].item);
}

After that, if any of the outliers require parsing text to handle, so be it. A few special cases might be worth the effort in a few special situations. But it'd be really nice to have an easier way that covers $items[] and $skills[], since those are the meat and potatos when acquiring $effects[].
 

Theraze

Active member
The problem is that many effects have multiple sources, which may each have their own default duration...
 

roippi

Developer
Theraze is correct, mapping effects to items is not bijective (nor is it injective). Make sure what you're requesting is mathematically possible.

But it'd be really nice to have an easier way that covers $items[] and $skills[]

http://wiki.kolmafia.us/index.php?title=Turns_per_cast???

And I don't see how numeric_modifier is not "easy." Write a 1-line wrapper function if you really don't like interfacing with it, then just use mywrapper( item ).
 

nworbetan

Member
The problem is that many effects have multiple sources, which may each have their own default duration...

PHP:
foreach it in $effect[eff].items {
    if (it.duration > 0) {
        etc...
    }
 }

That problem is much easier to solve than parsing the source from $effect[eff].all.


Theraze is correct, mapping effects to items is not bijective (nor is it injective). Make sure what you're requesting is mathematically possible.



http://wiki.kolmafia.us/index.php?title=Turns_per_cast???

And I don't see how numeric_modifier is not "easy." Write a 1-line wrapper function if you really don't like interfacing with it, then just use mywrapper( item ).

I'm not saying that numeric_modifier() isn't easy, I'm saying that it's possible to create much simpler and more straight-forward way to provide information about $effects[]. I'm saying that an easier and more straight-forward way to obtain information about $effects[] is something that I would prefer.

Here's what I'm saying isn't easy: imagine that you want to maximize() familiar weight (or any other stat where familiar weight is beneficial), and $effect[chorale of companionship] is recommended. That's the starting point, $effect[chorale of companionship].

Now, please consider the code required to answer these basic questions about $effect[chorale of companionship]:

  • What do you need to do to turn that $effect[chorale of companionship] into $skill[chorale of companionship] so you can evaluate its mp cost?
  • What do you need to do to turn that $effect[chorale of companionship] into $item[recording of chorale of companionship] so you can evaluate its meat cost?
  • What do you need to do to $effect[chorale of companionship] to decide whether using the $skill[] or the $item[] source is preferrable?
  • What do you need to do to $effect[chorale of companionship] to detect whether using the $skill[] or the $item[] source is possible or not?


The wrappers that you need to write for those operations, and any other opearation starting with an $effect[] are not an easy 1 line wrappers. Not even close. I'm sure most of them are possible, with an assortment of ad-hoc methods that are not quite the right tool for the job I'm describing. An easy, straightforward, and practically universal method is possible though: $effect[].items and $effect[].skill.
 
Top