FightOptimizer.ash

Update - FightOptimizer 1.0.8 with preliminary support for NS13 changes has been posted. See below for details.


Here's something I've been working on for a little while now.

FightOptimizer.ash is a KoLmafia battle consult script which tries to beat whatever monster you're fighting with the fewest resources expended. It does this by looking at all the skills you have and your equipment and effects, then considering the tree of all possible strategies that you could use. Attack? Attack + Stream of Sauce? Attack + Stream of Sauce + Minor Ray of Something? Entangling Noodles + Attack? Lunging-Thrust Smack + Thrust-Smack? etc etc etc. Once it has explored the entire tree of strategies it picks the best one and uses it.  ;D

How does it work? FO loops through all the possible strategies you can pursue. When considering a strategy, it actually simulates the whole battle round-by-round, estimating damage for monster attacks and player actions. By doing this it can find out whether a given strategy is a winning one, and it computes the cost in meat if it is. (Battles really have HP/MP costs, but those translate into meat easily enough.) It is pessimistic and assumes the worst in most cases, because you never know what the RNG is going to roll for you.

Isn't that slow? Not really. FO uses some clever techniques to trim the search space until it's manageable. It's fast enough that on my 2GHz laptop I barely even notice that it's running. Your mileage may vary depending on your CPU speed and Java VM.

Does it work? Oh yes. I've been using it for several ascensions on two different characters now, hardcore and softcore, and it can consistently beat all the monsters I've run into. And it either uses exactly the same strategy I would have used -- or a better one. In fact, I've been surprised a couple of times by FO's choice of strategy.


  • [li]Example #1: Adventuring in the Goatlet, I would often use the spellslinging strategy of Entangling Noodles, Stream of Sauce, Stream of Sauce (9MP) if I were doing things manually. FightOptimizer saw that in certain cases that could be replaced by Entangling Noodles, attack, Stream of Sauce (6MP) and did so. Cool!
    [/li]
    [li]Example #2: Adventuring in the Castle in the Clouds in the Sky as a muscle class, I would often use LTS or Noodles + high-level spells when I was doing things manually. But as soon as I acquired Cannelloni Cocoon, FO decided that in some cases it would be cheaper to simply attack giants in the Castle in the Clouds in the Sky and take damage from them (getting beaten to within an inch of my life) and then cast CC to restore my HP after the battle was done. Whoa. But it was absolutely right.
    [/li]
    [li]Example #3: Once, with a softcore character fighting in the hedge maze, I noticed that FO was choosing some seriously high-level expensive skills to defeat the Topiary Golems. (Weapon of the Pastalord, Fearful Fettucini, etc.) I stopped the script and investigated. Whoops, it turns out that I'd accidentally gone there totally naked, wearing nothing at all... no spell bonuses, no melee bonuses, no damage reduction, not even a weapon. FO had noticed this and was still managing to trounce the golems anyway, although at a much higher cost in MP of course.
    [/li]
    [li]Example #4: FO will even adjust its strategy in the middle of a fight if your attacks do more damage than its pessimistic prediction. In the Orc Chasm, you often see things like this:
    Request 22 of 314 (Mountain: Valley Beyond Orc Chasm) in progress...
    Encounter: Flaming Troll
    Internally representing encounter as Flaming Troll...
    Strategy: custom combat script
    Round 0: Harry Crimboween wins initiative!
    FightOptimizer strategy: Entangling Noodles, dictionary, Stream of Sauce (36 meat)
    Round 1: Harry Crimboween casts ENTANGLING NOODLES!
    Round 2: Harry Crimboween uses the dictionary!
    You did 50 damage with your dictionary. (p=30)
    FightOptimizer adjusted strategy: dictionary (18 meat)
    Round 3: Harry Crimboween uses the dictionary!
    You did 41 damage with your dictionary. (p=30)
    You win the fight!
    During the fight the dictionary actually performed better than the script's pessimistic prediction and did 50 damage instead of 30. As soon as this happened, the script knew that the monster's HP was at most 26, low enough that it could use the dictionary instead of Stream of Sauce to deliver the final blow. So it adjusted its strategy and saved an additional 3MP @ 6 meat/MP = 18 meat.
    [/li]

What about ML adjustments, ML variance, and scaling monsters? It handles ML adjustments beautifully. It is pessimistic about monster level variance -- it basically assumes the worst so that it never gets surprised. Scaling monsters (Feast of Boris, Baron von Ratsworth, Mob Penguins, etc) are special-cased in the script with the current best-guess formulae from the KoLwiki, so they work too.

Headbutt/Kneebutt/Shieldbutt? Head + Knee + Shield combos? Disco Bandit deleveling? Disco Combos? Yes, it's got at least preliminary support for all of those. The TT skills work well, but the DB skills and combos might need a bit more testing.

In-combat healing with Saucy Salve / Lasagna Bandages? I tried this out, but in practice it just expanded the search space exponentially and was really never worth it. If you look in the script you can try re-enabling them if you really want to.

Combat items? Not yet. It'll automatically use certain quest items and anti-anti-antidotes, but it does not consume damage-inflicting combat items. This may change in the future.

Stasis? Nope. I was considering adding it, but it sounds like it won't be worth the effort if NS13 nerfs it. We'll see, though -- some forms of stasis might still survive, such as starfish MP restoration.

Installation: FO currently requires KoLmafia 4235 or later. Drop FightOptimizer.ash into your "scripts" folder, and (optionally, but strongly recommended) drop the spading_hp_min.dat and spading_hp_max.dat files into your "data" folder.

Then go into the "Custom Combat" tab, hit Edit, and replace whatever's in there with this:
[pre][ default ]
1: consult FightOptimizer.ash
[/pre]

Many thanks to the people behind the KoLwiki, which was where most of the formulas and data tables used in this script were gathered from. And big thanks to the creators of KoLmafia and ASH. You know who you are. :)




Update - 1.0.2 - June 26 2007: I've added very early support for the NS13 changes. However, NS13 changed more than anybody expected, so ALL THE FORMULAS IN THE SCRIPT ARE PROBABLY WRONG NOW. But I've added at least early support for spell damage caps, chefstaff multipliers, and adjusted the TS/LTS hit percentages. Anything that's not explicitly stated in-game is just my own personal wild-ass guess. It also makes a very pessimistic assumption if it encounters a new, unspaded monster that KoLmafia doesn't yet know about. (It guesses that it's ML 200, so don't be surprised if it breaks out the big guns...) In short, it's highly experimental, and will sometimes just fail, but at least it's better than the old version at dealing with the post-NS13 world. I'll continue updating every few days as Mafia is updated and things are spaded out.
Update - 1.0.3 - June 27 2007: Got chefstaff stacking/dual-wielding working, added a number of monster element overrides.
Update - 1.0.4 - June 30 2007: Deal with spell backlash damage, which I think applies only to non-Myst classes. Also included handful of monster HP overrides for new monsters.
Update - 1.0.5 - July 2 2007: Added auto-spading of new monsters. To auto-spade, you'll need to download the *.dat files and put them in your scripts directory, then turn on the AUTOSPADE_MONSTERS configuration variable (and optionally AUTOSPADE_AGGRESSIVELY). Also tweaked the code to adjust the strategy during combat so that it should be a bit smarter.
Update - 1.0.6 - July 12 2007: Updated for changes to TS/LTS/Immaculate Seasoning. Added plinking when autospading. Added support for flyering, molybdenum magnet, and anti-anti-antidote during combat. Quite a few NS13 item updates.
Update - 1.0.7 - July 14 2007: Added support for outfit effects. Better handling of new/unspaded monsters - it used to sometimes get stuck on attacking when your hit stat is just too low, and now it tries to avoid that. Several changes to improve results on the Island Battlefield.
Update - 1.0.8 - July 15 2007: Fixed strategy updating, which had been broken by the anti-anti-antidote code. Myst is no longer your hit stat when using a staff with Rigatoni/SSG. Added Worm Wood monsters.
 

Attachments

  • spading_hp_min.dat
    2.2 KB · Views: 572
  • spading_hp_max.dat
    2.2 KB · Views: 559
  • FightOptimizer.ash
    122.7 KB · Views: 837

jabberw0ck

New member
First off, great job on the script. With my SC's limited skills, I don't know that it will help me much now, but after a few ascensions I imagine it will come in handy.

I'm using build 3921 and adventuring in the Valley Beyond Orc Chasm and occasionally I get this error:

Cannot store element in adjusted of type int (FightOptimizer.ash, line 788) Consult script 'FightOptimizer.ash' not found.

It seems to only happen right after I lose HP while fighting, although that's just my immediate observation. (It also happens after Round 0 if I lose initiative) Happily though, nothing crashes and I can simply complete the combat manually and then continue using the script.

Thanks again!
 
Oh, shoot ... heh, this was a bug in KoLmafia that I filed a couple days ago but isn't yet fixed. I fixed it in my local KoLmafia sources and then forgot about it.

FightOptimizer uses KoLmafia's monster_hp() and related functions. These were recently removed and re-added in a different form, and because of a copy-paste error they're returning an ELEMENT_TYPE instead of an INT_TYPE. Obviously the monster's HP is not $element[cold], it's going to be a number. :) I guess you might need to wait for a new daily build of KoLmafia after all. If you can build from source, here's a diff which you can apply to KoLmafia to fix it -- just change a few ELEMENT_TYPE to INT_TYPE starting at around line 3743 of KoLmafiaASH.java:

Code:
% svn diff KoLmafiaASH.java 
Index: KoLmafiaASH.java
===================================================================
--- KoLmafiaASH.java    (revision 3923)
+++ KoLmafiaASH.java    (working copy)
@@ -3743,19 +3743,19 @@
                result.addElement( new ScriptExistingFunction( "monster_attack", INT_TYPE, params ) );
 
                params = new ScriptType[] { MONSTER_TYPE };
-               result.addElement( new ScriptExistingFunction( "monster_attack", ELEMENT_TYPE, params ) );
+               result.addElement( new ScriptExistingFunction( "monster_attack", INT_TYPE, params ) );
 
                params = new ScriptType[] {};
                result.addElement( new ScriptExistingFunction( "monster_defense", INT_TYPE, params ) );
 
                params = new ScriptType[] { MONSTER_TYPE };
-               result.addElement( new ScriptExistingFunction( "monster_defense", ELEMENT_TYPE, params ) );
+               result.addElement( new ScriptExistingFunction( "monster_defense", INT_TYPE, params ) );
 
                params = new ScriptType[] {};
                result.addElement( new ScriptExistingFunction( "monster_hp", INT_TYPE, params ) );
 
                params = new ScriptType[] { MONSTER_TYPE };
-               result.addElement( new ScriptExistingFunction( "monster_hp", ELEMENT_TYPE, params ) );
+               result.addElement( new ScriptExistingFunction( "monster_hp", INT_TYPE, params ) );
 
                params = new ScriptType[] {};
                result.addElement( new ScriptExistingFunction( "will_usually_miss", BOOLEAN_TYPE, params ) );

(PS: the SourceForge artifact is 1734144.)
 

Veracity

Developer
Staff member
[quote author=Harry Crimboween link=topic=983.msg4905#msg4905 date=1182262456]
This was a bug in KoLmafia that I filed a couple days ago but isn't yet fixed. I fixed it in my local KoLmafia sources and then forgot about it.[/quote]

Where did you "file" this bug? This is the first time I recall hearing about it. I don't see it on sourceforge.

Fixed in revision 3925.

Edit: Oh, I see: it was in a comment added to a Feature Request.
 
[quote author=Veracity link=topic=983.msg4907#msg4907 date=1182273872]
Where did you "file" this bug? This is the first time I recall hearing about it. I don't see it on sourceforge.
[/quote]

As mentioned in the above message, it was filed on June 9th as kolmafia-Bugs-1734144 when monster_base_hp() etc disappeared from rev 3883. It got moved from Bugs to Feature Requests as kolmafia-Feature Requests-1734144.

Soon afterward, some functions similar (but different) from the original ones reappeared in 3892, which I assumed were a response to the feature request. I commented in the existing bug on June 10th that the new functions were broken. Since I was on the road last week I just fixed it locally and forgot about it. Sorry, I could've been more proactive about following it up when there wasn't a response for a few days...
 

mmmk

New member
// If this is the Naughty Sorceress, abort.
if (contains_text(OPPONENT, "naughty sorceress")) error("Sorry, no Sorceress yet.");

:p hehe the one i was interested in isn't there ... but good work :)
 
[quote author=mmmk link=topic=983.msg4913#msg4913 date=1182364115]
:p hehe the one i was interested in isn't there ... but good work :)
[/quote]

Yeah, she's kind of a special case, isn't she? ;D Scripting the NS fight is an interesting challenge. I might give it a shot eventually -- with certain equipment/skillsets she's not that hard, but solving it in the general case if you just go in poorly prepared is kind of a tough problem. But of course there's no point in writing anything for NS11 right now.
 
[quote author=angeredtsuzuki link=topic=983.msg4915#msg4915 date=1182394665]
hey, where do you get the daily build 3925?
i didn't see it on the daily build and change log section
[/quote]

A daily build hasn't been posted yet ... for now you have to build from SVN. Once a daily past 3925 has been posted the script will work with it.
 

macman104

Member
[quote author=angeredtsuzuki link=topic=983.msg4921#msg4921 date=1182476342]
ok thanks.
how do you install daily builds?[/quote]It's just like using a regular mafia download. The only difference is that these are built from untested source code. If you are unfamiliar with daily builds, please read the stickies in the section that contains the daily builds.
 
ok, i downloaded the daily build, and it says this:
Untitled-1-2.jpg
 

fewyn

Administrator
Staff member
[quote author=angeredtsuzuki link=topic=983.msg4923#msg4923 date=1182480719]
ok, i downloaded the daily build, and it says this:
** no need to quote images **
[/quote]

Download it somewhere *THEN* open it?
 
[quote author=angeredtsuzuki link=topic=983.msg4923#msg4923 date=1182480719]
ok, i downloaded the daily build, and it says this:
** no need to quote images **[/quote]

Re-download it. Sometimes an act of gremlins can cause a download to become corrupted while downloading. This is true with anything you download.

Pesky Gremlins!
 

kain

Member
This thing rocks. Seriously.

The only thing I'm running into is when I'm trying to open the library and I'm wielding the pool cue, it tries to thrust-smack and of course, if you have spirit of rigatoni perm'd ... that's a crapshoot!

Aside from that, wow, incredible.
 
Top