Winterbay's Helpful Automatic Monsterbasher (WHAM)

Right, so me poking around with a level 50+ DB won't help me with debugging much I guess :)
(well apart from deep enough in the basement I guess, but I may run into other problems before I start losing fights)
 
Who's issue is this, that it thinks it can jiggle the staff more than 5 times a day?

AoJ, Staff of the All-Steak equipped


Code:
[244] 8-Bit Realm
Encounter: Tektite
Strategy: /~/.kolmafia/ccs/WHAM.ccs [default]
Round 0: chef_rannos wins initiative!
WHAM: Running SmartStasis
Round 1: chef_rannos executes a macro!
Round 1: chef_rannos jiggles the Staff of the All-Steak
Round 2: You jiggle the staff, but there are no theatrics. Just a squirt of nasty congealed grease, which surprises and displays your opponent to the tune of 18 damage.
Round 2: tektite takes 18 damage.
WHAM: Starting evaluation and performing of attack
Round 2: chef_rannos executes a macro!
Round 2: chef_rannos casts CURDLE!
Round 3: tektite takes 66 damage.
Round 3: chef_rannos wins the fight!
You gain 5 hit points
You gain 4 Mana Points
You acquire an item: blue pixel
You acquire an item: white pixel
You acquire an item: black pixel
You gain 2 Strongness
You gain 9 Magicalness


Well, I see the jiggle does some damage...but it blew my 5 item drop charges on 8-bit monsters...and not even just bloopers... :(

However, if it doesn't stun, I'd prefer a one hit spell than doing about 20 damage on a jiggle. ;)
 
Last edited:
1 round stun, ~20 damage. I think the problem is here though:
Code:
				else if (equipped_item($slot[weapon]) == $item[Staff of the All-Steak])
					return has_goal(m) < 0.15;
It checks if the goal is <15% but it never checks if it's part of the goal at all... probably should be changed to something like:
Code:
				else if (equipped_item($slot[weapon]) == $item[Staff of the All-Steak])
					return (has_goal(m) < 0.15 && has_goal(m) > 0);
 
Some moxie debuffs:
hat: makeshift turban (blindness: -25%), silent beret -30%, wolf mask as part of furry suit (-75%)
offhand: brimstone bunker -20%
pants: furry pants as part of furry suit
accessories: teflon swims -5%, giant designer sunglasses -10%, night vision goggles -10%, vinyl boots (for males) -15%, brimstone brooch -20%
-> up to -120% (with makeshift scuba)

potions: steal this candy -10%,wet venom duct -10%, marzipan skull -10%, pet-buffing spray -10%, bottled inspiration -20%, mr. mediocrebar -30%, patchouli incense stick -30%
another -120% for fine-tuning
 
1 round stun, ~20 damage. I think the problem is here though:
Code:
                else if (equipped_item($slot[weapon]) == $item[Staff of the All-Steak])
                    return has_goal(m) < 0.15;
It checks if the goal is <15% but it never checks if it's part of the goal at all... probably should be changed to something like:
Code:
                else if (equipped_item($slot[weapon]) == $item[Staff of the All-Steak])
                    return (has_goal(m) < 0.15 && has_goal(m) > 0);

Ahh yes, forgot about that. Also, I don't think Mafia is tracking the 5 a day yet so no way to safeguard against that unfortunately. Also, if someone can give a better limit than 15% I'm all ears.
 
Hmm... I'd probably consider something like .1>jiggle>.5 or something like that. Basically, if you have less than a 50% chance of your goal item, but more than a 10% chance, use the staff. If you have less than 10% chance, you probably still won't get the item. If you have better than 50% chance without it, don't waste the jiggle. That also takes care of the "why does it jiggle on everything even if it doesn't have the item I wanted" issue. :)
 
Ok! I've been looking through your ok() function to see what I should auto-add into the upcoming blacklist functionality of BatBrain, and I have lots of things to discuss with you. I believe that once I update, well over half of your function will be unnecessary (and some of it already is). So I'm going to discuss your function piecemeal and explain why I think certain parts of it aren't needed. I suspect some of them are fixes for things which were previously broken in BatBrain but have since been fixed. I've also added certain things to BatBrain as a result of going through this function, which means when I update, you can feel free to remove the new redundancy. If I describe something as unnecessary but you have evidence (anecdotal or otherwise) to say otherwise, please let me know, because it probably means something in BatBrain needs addressing.

PHP:
//Function to return skills and items that are usable

This comment is unnecessary! What? Oh oKKKK I won't actually go line by line. :) Let's do chunk by chunk.

PHP:
	boolean no_cunctatitis() {
		return m != $monster[Procrastination Giant] || weapon_type(equipped_item($slot[weapon])) == $stat[Moxie];
	}
	
	boolean no_teleportitis() {
		return m != $monster[x-dimensional horror] && !contains_text(to_lower_case(to_string(m)), "quantum");
	}
	
	boolean no_bears() {
		return !(happened("skill 7131") || happened("skill 7132") || happened("skill 7133") || happened("skill 7134") || happened("skill 7135") || happened("skill 7136"));
	}

Yep, BatBrain isn't checking any of these, and it probably shouldn't since actions will still produce the results predicted (damage, etc). Good so far.

PHP:
	if(m == $monster[Naughty Sorority Nurse] && (dmg_dealt(a.dmg) + (m_hit_chance()*dmg_dealt(retal.dmg) + dmg_dealt(baseround().dmg))) < min(monster_stat("hp"), 90)) {
		return false;	//These monsters heal too much for this skill
	}

Unnecessary if you're checking action validity with kill_rounds(), which already includes NSN healing.

PHP:
	if(a.pdmg[$element[none]] > my_stat("hp")) {
		return false;	//Don't use something that would kill us
	}

Probably unnecessary if you're checking to_profit(), because that already includes the cost of getting beaten up if the action will kill you (and that includes the monster event). But also doesn't hurt to leave it in.

PHP:
	if(aid.find()) {
		switch(aid.group(1)) {
			case "use ":	//If the user doesn't want WHAM to use items, don't
				if(vars["WHAM_noitemsplease"] == "true")
					return false;
				if(historical_price(to_item(to_int(aid.group(2)))) > to_int(get_property("autoBuyPriceLimit")) && to_item(aid.group(2)).reusable == false)
					return false;
				break;

Suggestion here. After you import BatBrain but before you call act(), the data file is loaded into factors but your options are not yet built. Seems like checking WHAM_noitemsplease could be done at top level -- once -- soon after importing BatBrain, and if true simply remove factors["item"]. Would speed up your script a little too, since BatBrain wouldn't know items even exist and could completely skip build_items().

PHP:
			case "skill ":
				if (abs(a.mp) > my_stat("mp")) //We don't have enough MP for this skill
					return false;
				break;
			case "jiggle":
				if (happened("jiggle") || happened("chefstaff"))
					return false;
				break;
		}

Both of these are or will be unnecessary. Both build_skillz() and enqueue() already pass over skills you have insufficient MP to cast, and jiggle tracking will be fixed in the update.

PHP:
		for i from 0 to count(not_ok) - 1 {
			switch(aid.group(1)) {
				case "use ":	if(not_ok[i].id == aid.group(2) && ((item_amount(to_item(to_int(aid.group(2)))) - times_happened(not_ok[i].type + " " + not_ok[i].id) <= not_ok[i].amount || to_item(to_int(not_ok[i].id)).reusable == true) || not_ok[i].amount == -1))
									return false;
								break;
				case "skill ":	if(not_ok[i].id == aid.group(2))
									return false;
								break;
			}
		}

This functionality is being added to BatBrain, because I am a dirty idea thief. Won't be necessary then either. :)

PHP:
		switch(aid.group(1)+aid.group(2)) {
			case "use 2065":	//PADL-phone does not work against Bugbear chefs
			case "use 2354":	//Neither does the windchimes
				return (to_string(m) != "trendy bugbear chef");
			case "use 2453":	//Goodfella contracts
				return (my_effective_familiar() == $familiar[Penguin Goodfella]);
			case "use 2848":	//Gnomitronic thingamabob
				return (item_amount($item[gnomitronic hyperspatial demodulizer]) > 0 && !happened($item[gnomitronic hyperspatial demodulizer]));
			case "use 3391":	// Frosty's iceball. Don't use it!
				return false;

All unnecesssary so far. The PADL phone and windchimes are already being ignored unless you're on the Battlefield and the monster appears there normally in appearance_rates() (the trendy bugbear chef does not). I've added Goodfella contracts to build_items() so after the update they will be ignored unless you have a penguin familiar and enough meat to use it. The Gnomitropic thingy is already flagged as once-only. Frosty's iceball is flagged as custom in batfactors, which means it is deliberately ignored.

PHP:
			case "use 4698":	//Imp Air
			case "use 4699":	//Bus Pass, don't use unless we are already past the steel item quest
				return (get_property("questM10Azazel") == "finished");

This seems like an excellent candidate for something BatBrain should auto-blacklist, because simply ignoring goals is not a thorough enough solution to prevent accidentally using these. I'll be sure to blacklist these conditionally (only 5 of them, and only if the quest is unfinished, meaning if you have extras, they'll be available for use) before updating.

PHP:
			case "use 5676":	//Pool torpedos only work under water
				return (my_location().zone == "The Sea");

Unnecessary, I think. Torpedos are already listed in batfactors as doing 0 damage outside of the Sea. This ought to cause your script to ignore them unless you are in the Sea.

PHP:
			case "skill 66": //Flying Fire Fist, don't auto-use this if it will expend Salamanderenity.
				if(have_effect($effect[Salamanderenity]) > 0) return false;
				else return true;

This is useful if you are sure you always want to hoard Salamanderenity, but BatBrain's default handling is probably better. It already considers the actual meat cost of the amount of Salamanderenity you would lose as part of the value of the skill. In other words, if it would take 10 casts of Salamander Kata to restore your Salamanderenity to its current level, using Flying Fire Fist would cost an additional meatpermp*10*mp_cost(Salamander Kata), in addition to the regular cost of casting Fire Fist. I think BatBrain's default handling is superior, because it allows the skill to be available, although it will probably be quite unprofitable unless you have very few turns of Salamanderenity or you're in an extreme combat.

PHP:
			case "skill 1003": //Thrust-Smack
			case "skill 1004": //Lunge-Smack
			case "skill 1005": //Lunging Thrust-Smack
			case "skill 2003": //Headbutt
			case "skill 2015": //Kneebutt
			case "skill 2103": //Head + Knee Combo
				return (weapon_type(equipped_item($slot[weapon])) != $stat[Moxie] && no_cunctatitis() && no_teleportitis());
			case "skill 1023": //Harpoon!
				return equipped_item($slot[weapon]) != $item[none] && no_cunctatitis();

Most of this is necessary, but the weapon_type() check is not, as BatBrain checks that your attack stat is muscle before adding melee skills. I suspect that's there from before BatBrain was fixed. I've also stolen the unarmed check for Harpoon! for the next update, since KoL evidently allows you to cast skills you can't cast.

PHP:
			case "skill 2005": //Shieldbutt
			case "skill 2105": //Head + Shield Combo
			case "skill 2106": //Knee + Shield Combo
			case "skill 2107": //Head + Knee + Shield Combo
				return (item_type(equipped_item($slot[off-hand])) == "shield" && weapon_type(equipped_item($slot[weapon])) != $stat[Moxie] && no_cunctatitis() && no_teleportitis());

The weapon_type() check is again unnecessary. I was quite surprised to discover that checking for a shield may actually be necessary! It should not be, however -- BatBrain should not include shield attacks if you aren't wearing a shield. I've fixed that for the update as well.

PHP:
			case "skill 7021":	//Ask Richard for a Bandage
			case "skill 7022":	//Ask Richard for a Grenade
			case "skill 7023":	//Ask Richard to Rough the Hobo Up a Bit
				return false;	//Due to a KoL-bug these skills cannot be enqueued via skill number.

Since BatBrain using these skills will cause errors until KoL fixes the bug, it seems like this is another good candidate for BatBrain to auto-blacklist, at least until the bug is fixed. Added that as well.

PHP:
			case "skill 7061":	//Spring Raindrop Attack
			case "skill 7062":	//Summer Siesta
			case "skill 7063":	//Falling Leaf Whirlwind
			case "skill 7064":	//Winter's Bite Technique
				return ((equipped_amount($item[haiku katana]) - (times_happened("skill 7061") + times_happened("skill 7062") + times_happened("skill 7063") + times_happened("skill 7064"))) > 0);

Oooh! BatBrain's new blacklist should allow for a really nice fix here, since blacklisting a skill with a nonzero integer X means that no more than X of them will be allowed per combat. However, a perfect solution is a bit complicated as the blacklist would have to be reduced in set_happened() for all katana skills, and if they were only being queued, then reversing that would be difficult when the queue is cleared. As I've thought about it for more than 10 minutes without arriving at a perfect conclusion, I'm going to make a TODO: note and move on. Keep this.

PHP:
			case "skill 7074":	//Consume Burrowgrub is only ok three times per day
				return to_int(get_property("burrowgrubSummonsRemaining")) > 0;
			case "skill 7113":	//Squeeze stress ball can only be used 5 times per day
				if(to_int(get_property("_stressBallSqueezes")) >= 5)
					return false;
				break;

Now these skills can take advantage of the new blacklist to avoid enqueueing too many of them. You can remove this bit after BatBrain updates.

PHP:
			case "skill 7131":
			case "skill 7132":
			case "skill 7133":
			case "skill 7134":
			case "skill 7136":
				if(!no_bears())
					return false; //Don't try multiple bear skills in one combat
			case "skill 7135":	//Bear Hug should only be used against plural monsters if you are a zombie slayer
				if (my_path() == "Zombie Slayer" && howmanyfoes > 1 && no_bears()) return true;
				else if (my_path() != "Zombie Slayer" && no_bears()) return true;
				else return false;

I still haven't gotten bear skills integrated. I guess not particularly enjoying Zombiecore and not having a set of arms to boot are factors here. Keep this.

PHP:
			case "skill 11000": //Mighty Axing 
			case "skill 11001": //Cleave
				return (no_cunctatitis() && no_teleportitis() && have_equipped($item[Trusty]));
			case "skill 11006": //Throw Trusty
				return have_equipped($item[Trusty]);

BatBrain wasn't checking for Trusty for both Cleave and Throw Trusty. Added those checks, so now your check for Trusty equipped is unnecessary. I'm assuming here that none of those skills work unarmed.

PHP:
			case "skill 12010":	//Ravenous Pounce
			case "skill 12011":	//Distracting Minion
				return no_cunctatitis() && no_teleportitis();

All good. I'm beginning to like the idea of a flag for melee skills. Then you could just check that flag rather than each skill case.

PHP:
			case "jiggle":
				if (equipped_item($slot[weapon]) == $item[Staff of the Staff of Life])
					return to_float(my_hp()) / my_maxhp() < 0.4;
				else if (equipped_item($slot[weapon]) == $item[Staff of the All-Steak])
					return has_goal(m) < 0.15;
				else
					return true;

The bug there for All-Steak has already been mentioned, but otherwise this is all good. These new chefstaffs present a bit of difficulty, since all chefstaffs share the same action id "jiggle". We can't deliberately ignore that id, so it's going to need some custom handling. TODO.

PHP:
			case "attack":
				return (my_path() != "Avatar of Jarlsberg" && ((my_path() != "Avatar of Boris" && no_cunctatitis() && no_teleportitis()) ||
						(my_path() == "Avatar of Boris" && (!have_equipped($item[Trusty]) && no_cunctatitis() && no_teleportitis()) || (contains_text(to_string(m),"Naughty Sorceress") || m == $monster[Bonerdagon] || have_effect($effect[temporary amnesia]) > 0))));
        }

The new BatBrain auto-blacklists "attack" for AsoJ (I guess that would be the plural of AoJ). Otherwise, this is all good.

OK! I hope this was helpful -- it was intended as helpful, not critical. I really should have looked at this sooner to note some of BatBrain's failings. Some of them were really quite silly. Silly failings. Anyway, yay collaboration! Hopefully you will breathe a sigh of relief as you delete most of this function after the update. :)

Speaking of, I'm on track for an update this week. Or perhaps I should wait till 13.3.31? And I could call this version 1.31.31! It's only ten more days...
 
This is useful if you are sure you always want to hoard Salamanderenity, but BatBrain's default handling is probably better. It already considers the actual meat cost of the amount of Salamanderenity you would lose as part of the value of the skill. In other words, if it would take 10 casts of Salamander Kata to restore your Salamanderenity to its current level, using Flying Fire Fist would cost an additional meatpermp*10*mp_cost(Salamander Kata), in addition to the regular cost of casting Fire Fist. I think BatBrain's default handling is superior, because it allows the skill to be available, although it will probably be quite unprofitable unless you have very few turns of Salamanderenity or you're in an extreme combat.
What value does BatBrain place on not needing to track down a g-string for the tower? (Hoarding Salamanderenity is quite useful for killing tower monsters.)
 
Thanks for the comments. I'll look over them more in detail when I get the time, but I can say that some of the things in that list are still there from when I stole the function from Bale's DAM-script and has never been removed :)
 
In that case, lost, I suggest this for Flying Fire Fist:

PHP:
if (have_effect($effect[Salamanderenity]) == 0) return true;
foreach i in tower_items(true) {
   if (item_amount(i) == 0) return false;
}
return true;

Then you'll only hoard Salamanderenity if you don't already have all your tower items.

@Winterbay: Haha, yeah it seemed some of that code was a bit old.
 
I still haven't gotten bear skills integrated. I guess not particularly enjoying Zombiecore and not having a set of arms to boot are factors here.

These days you can purchase a box of bear arms for less than the cost of mayfly bait. Just saying.
 
Okay, I'm back to the see again and debugging on my lunch hour!

Code:
[989] An Octopus's Garden
Encounter: octopus gardener
Strategy: /home/user/.kolmafia/ccs/Destroy.ccs [default]
Round 0: Crowther loses initiative!
You lose 133 hit points
ATT: 435 (94% Ã 51.95, death in 15)
DEF: 372 (97.73% Ã 58.11, win in 11)
HP: 608, Value: 3,836.3 ., RES: 0
WHAM: Monster HP is 608.0.
WHAM: Running SmartStasis
Profit per round: ActionProfitDamageOtherbase (0.)0.--
1/5 monsters drop goals here.
Custom action: use 821 (stun first with use 5561)
Auto-funk: merging 'use 5561' and 'use 821'.
Custom action: use 822 (no stun)
Round 1: Crowther executes a macro!
Round 1: Crowther uses the Rain-Doh indigo cup and uses the bubbly potion!
You gain 171 hit points
Round 2: Crowther uses the smoky potion!
You lose 124 hit points
WHAM: Starting evaluation and performing of attack
WHAM: Reached WHAM_round_limit while looking for a way to kill the monster. Executing the current strategy and continuing from there.
WHAM: Enqueuing a stun to help with the battle
WHAM: Enqueueing attack with your weapon (macroid attack). Estimated damage: 56.78931940087406.
WHAM: Enqueueing attack with your weapon (macroid attack). Estimated damage: 56.78931940087406.
WHAM: Enqueueing attack with your weapon (macroid attack). Estimated damage: 56.78931940087406.
WHAM: Enqueueing Candyblast (macroid skill 3022). Estimated damage: 32.0.
WHAM: Enqueueing Candyblast (macroid skill 3022). Estimated damage: 32.0.
WHAM: Enqueueing Candyblast (macroid skill 3022). Estimated damage: 32.0.
WHAM: Enqueueing Candyblast (macroid skill 3022). Estimated damage: 32.0.
WHAM: Enqueueing Candyblast (macroid skill 3022). Estimated damage: 32.0.
WHAM: Enqueueing Candyblast (macroid skill 3022). Estimated damage: 32.0.
WHAM: We are going to 10-shot with Entangling Noodles, attack with your weapon, attack with your weapon, attack with your weapon, Candyblast, Candyblast, Candyblast, Candyblast, Candyblast and Candyblast.
Round 3: Crowther executes a macro!
Round 3: Crowther casts ENTANGLING NOODLES!
Round 4: Crowther attacks!
Round 5: octopus gardener takes 56 damage.
Round 5: Crowther attacks!
Round 6: octopus gardener takes 5 damage.
You lose 125 hit points
Round 6: Crowther attacks!
Round 7: octopus gardener takes 55 damage.
You lose 92 hit points
Round 7: Crowther casts CANDYBLAST!
Round 8: octopus gardener takes 36 damage.
You lose 105 hit points
Round 8: Crowther casts CANDYBLAST!
Round 9: octopus gardener takes 34 damage.
You lose 134 hit points
Round 9: Crowther casts CANDYBLAST!
Round 10: octopus gardener takes 34 damage.
Round 10: Crowther casts CANDYBLAST!
Round 11: octopus gardener takes 32 damage.
You lose 136 hit points
Round 11: Crowther casts CANDYBLAST!
Round 12: octopus gardener takes 36 damage.
You acquire an item: Wint-O-Fresh mint
You lose 106 hit points
Round 12: Crowther casts CANDYBLAST!
Round 13: octopus gardener takes 31 damage.
You lose 94 hit points
Look! You found 1 Wint-O-Fresh mint (50.)!

Conditions not satisfied after 1 adventure.
Autorecovery failed.
What I notice here is death was predicted in 15 rounds and I died earlier. Then I noticed that damage is predicted as 94% x 51.95, but I'm getting hit for 94-136 damage. That would be enough to cause things to fail. I know nothing about monster damage formulas. Time to look into that.

EDIT: Okay, seems this is the wrong thread, since that's all done in BatBrain.

Moxie: 396
dr = 7
da = 490
ml = 10
att = 435 (425+10)

BatBrain is using ((435-396)+.225*435-7)*(1-((sqrt(490/10)-1)/10)) = 51.95, which agrees with the formula in the wiki.

Right now I'm guessing there's some secret formula in the sea for monster damage.
 
Last edited:
Ok, let's do this...

PHP:
    boolean no_cunctatitis() {
        return m != $monster[Procrastination Giant] || weapon_type(equipped_item($slot[weapon])) == $stat[Moxie];
    }
    
    boolean no_teleportitis() {
        return m != $monster[x-dimensional horror] && !contains_text(to_lower_case(to_string(m)), "quantum");
    }
    
    boolean no_bears() {
        return !(happened("skill 7131") || happened("skill 7132") || happened("skill 7133") || happened("skill 7134") || happened("skill 7135") || happened("skill 7136"));
    }

Yep, BatBrain isn't checking any of these, and it probably shouldn't since actions will still produce the results predicted (damage, etc). Good so far.

We're off to a great start then :)

PHP:
    if(m == $monster[Naughty Sorority Nurse] && (dmg_dealt(a.dmg) + (m_hit_chance()*dmg_dealt(retal.dmg) + dmg_dealt(baseround().dmg))) < min(monster_stat("hp"), 90)) {
        return false;    //These monsters heal too much for this skill
    }

Unnecessary if you're checking action validity with kill_rounds(), which already includes NSN healing.

This was introduced back when I still calculated things myself I think, and could probably be removed now.
PHP:
    if(a.pdmg[$element[none]] > my_stat("hp")) {
        return false;    //Don't use something that would kill us
    }

Probably unnecessary if you're checking to_profit(), because that already includes the cost of getting beaten up if the action will kill you (and that includes the monster event). But also doesn't hurt to leave it in.

Now, this is there due to me trying to get WHAM to play nicely with Mine Crabs which it currently doesn't. The problem being that WHAM kept choosing items with cumulative damage meaning that after a while the total damage got above the limit and the mine exploded. I'm still not sure how to handle that and my sea-farming character handles the mine crab in a separate line in the CCS.

PHP:
    if(aid.find()) {
        switch(aid.group(1)) {
            case "use ":    //If the user doesn't want WHAM to use items, don't
                if(vars["WHAM_noitemsplease"] == "true")
                    return false;
                if(historical_price(to_item(to_int(aid.group(2)))) > to_int(get_property("autoBuyPriceLimit")) && to_item(aid.group(2)).reusable == false)
                    return false;
                break;

Suggestion here. After you import BatBrain but before you call act(), the data file is loaded into factors but your options are not yet built. Seems like checking WHAM_noitemsplease could be done at top level -- once -- soon after importing BatBrain, and if true simply remove factors["item"]. Would speed up your script a little too, since BatBrain wouldn't know items even exist and could completely skip build_items().

The main thinking behind having these here is to allow for the removal of items from automatic use, but to still get them printed out should the script fail to find a way to kill the monster so that you can make an informed decision to use a good item even though you don't want WHAM to do it for you.

PHP:
            case "skill ":
                if (abs(a.mp) > my_stat("mp")) //We don't have enough MP for this skill
                    return false;
                break;
            case "jiggle":
                if (happened("jiggle") || happened("chefstaff"))
                    return false;
                break;
        }

Both of these are or will be unnecessary. Both build_skillz() and enqueue() already pass over skills you have insufficient MP to cast, and jiggle tracking will be fixed in the update.

Yes, the problem is that for some reason jiggle was being multi-enqueued without this and sometimes WHAM tried to use a skill you didn't have the MP for and thus failed to enqueue it. This was a bigger problem when I used my own list of options and didn't use opts directly, but still pop up from time to time. Since there is no current handling for what to do when something fails to enqueue (apart form aborting) this needs to be there for now to ensure a somewhat more fluid running of the script. Better handling of enqueueing and failure to do so would probably also work.

PHP:
        for i from 0 to count(not_ok) - 1 {
            switch(aid.group(1)) {
                case "use ":    if(not_ok[i].id == aid.group(2) && ((item_amount(to_item(to_int(aid.group(2)))) - times_happened(not_ok[i].type + " " + not_ok[i].id) <= not_ok[i].amount || to_item(to_int(not_ok[i].id)).reusable == true) || not_ok[i].amount == -1))
                                    return false;
                                break;
                case "skill ":    if(not_ok[i].id == aid.group(2))
                                    return false;
                                break;
            }
        }

This functionality is being added to BatBrain, because I am a dirty idea thief. Won't be necessary then either. :)

Well, no, but until the new version is out and users dontuse-files get ported to the new system it needs to stay there :)

PHP:
        switch(aid.group(1)+aid.group(2)) {
            case "use 2065":    //PADL-phone does not work against Bugbear chefs
            case "use 2354":    //Neither does the windchimes
                return (to_string(m) != "trendy bugbear chef");
            case "use 2453":    //Goodfella contracts
                return (my_effective_familiar() == $familiar[Penguin Goodfella]);
            case "use 2848":    //Gnomitronic thingamabob
                return (item_amount($item[gnomitronic hyperspatial demodulizer]) > 0 && !happened($item[gnomitronic hyperspatial demodulizer]));
            case "use 3391":    // Frosty's iceball. Don't use it!
                return false;

All unnecesssary so far. The PADL phone and windchimes are already being ignored unless you're on the Battlefield and the monster appears there normally in appearance_rates() (the trendy bugbear chef does not). I've added Goodfella contracts to build_items() so after the update they will be ignored unless you have a penguin familiar and enough meat to use it. The Gnomitropic thingy is already flagged as once-only. Frosty's iceball is flagged as custom in batfactors, which means it is deliberately ignored.

PADL and windchimes were added before it got added to BatBrain and didn't get removed once they were, Frosty is from DAM (where it was due to DAM destroying one such by mistake) and I think Batfactors had it listed as a normal action once. The gnomithingie is there because the check in attack_action as it stands now does nto actually check that you have the item, only that the calculated damage is higher than the monsters HP and if the monster HP is currently <0 due to monster variance and no Manuel the 0 damage from not having the item will lead to BatBrain returning that this is the best attack_action, which it clearly isn't since you may not have one.

PHP:
            case "use 4698":    //Imp Air
            case "use 4699":    //Bus Pass, don't use unless we are already past the steel item quest
                return (get_property("questM10Azazel") == "finished");

This seems like an excellent candidate for something BatBrain should auto-blacklist, because simply ignoring goals is not a thorough enough solution to prevent accidentally using these. I'll be sure to blacklist these conditionally (only 5 of them, and only if the quest is unfinished, meaning if you have extras, they'll be available for use) before updating.

Sounds good.

PHP:
            case "use 5676":    //Pool torpedos only work under water
                return (my_location().zone == "The Sea");

Unnecessary, I think. Torpedos are already listed in batfactors as doing 0 damage outside of the Sea. This ought to cause your script to ignore them unless you are in the Sea.

I'm not sure it was tht always, but I may be wrong. I know it got added due to a bug report in this thread, but I am not sure how long ago that was.

PHP:
            case "skill 66": //Flying Fire Fist, don't auto-use this if it will expend Salamanderenity.
                if(have_effect($effect[Salamanderenity]) > 0) return false;
                else return true;

This is useful if you are sure you always want to hoard Salamanderenity, but BatBrain's default handling is probably better. It already considers the actual meat cost of the amount of Salamanderenity you would lose as part of the value of the skill. In other words, if it would take 10 casts of Salamander Kata to restore your Salamanderenity to its current level, using Flying Fire Fist would cost an additional meatpermp*10*mp_cost(Salamander Kata), in addition to the regular cost of casting Fire Fist. I think BatBrain's default handling is superior, because it allows the skill to be available, although it will probably be quite unprofitable unless you have very few turns of Salamanderenity or you're in an extreme combat.

This was taken from DAM as well and could very well get improved as discussed above.

PHP:
            case "skill 1003": //Thrust-Smack
            case "skill 1004": //Lunge-Smack
            case "skill 1005": //Lunging Thrust-Smack
            case "skill 2003": //Headbutt
            case "skill 2015": //Kneebutt
            case "skill 2103": //Head + Knee Combo
                return (weapon_type(equipped_item($slot[weapon])) != $stat[Moxie] && no_cunctatitis() && no_teleportitis());
            case "skill 1023": //Harpoon!
                return equipped_item($slot[weapon]) != $item[none] && no_cunctatitis();

Most of this is necessary, but the weapon_type() check is not, as BatBrain checks that your attack stat is muscle before adding melee skills. I suspect that's there from before BatBrain was fixed. I've also stolen the unarmed check for Harpoon! for the next update, since KoL evidently allows you to cast skills you can't cast.

PHP:
            case "skill 2005": //Shieldbutt
            case "skill 2105": //Head + Shield Combo
            case "skill 2106": //Knee + Shield Combo
            case "skill 2107": //Head + Knee + Shield Combo
                return (item_type(equipped_item($slot[off-hand])) == "shield" && weapon_type(equipped_item($slot[weapon])) != $stat[Moxie] && no_cunctatitis() && no_teleportitis());

The weapon_type() check is again unnecessary. I was quite surprised to discover that checking for a shield may actually be necessary! It should not be, however -- BatBrain should not include shield attacks if you aren't wearing a shield. I've fixed that for the update as well.

Sounds good on the shield-part and I think that the item_type-checks are there as a remnant from when I made my own list from opts.

PHP:
            case "skill 7021":    //Ask Richard for a Bandage
            case "skill 7022":    //Ask Richard for a Grenade
            case "skill 7023":    //Ask Richard to Rough the Hobo Up a Bit
                return false;    //Due to a KoL-bug these skills cannot be enqueued via skill number.

Since BatBrain using these skills will cause errors until KoL fixes the bug, it seems like this is another good candidate for BatBrain to auto-blacklist, at least until the bug is fixed. Added that as well.

Thanks.

PHP:
            case "skill 7061":    //Spring Raindrop Attack
            case "skill 7062":    //Summer Siesta
            case "skill 7063":    //Falling Leaf Whirlwind
            case "skill 7064":    //Winter's Bite Technique
                return ((equipped_amount($item[haiku katana]) - (times_happened("skill 7061") + times_happened("skill 7062") + times_happened("skill 7063") + times_happened("skill 7064"))) > 0);

Oooh! BatBrain's new blacklist should allow for a really nice fix here, since blacklisting a skill with a nonzero integer X means that no more than X of them will be allowed per combat. However, a perfect solution is a bit complicated as the blacklist would have to be reduced in set_happened() for all katana skills, and if they were only being queued, then reversing that would be difficult when the queue is cleared. As I've thought about it for more than 10 minutes without arriving at a perfect conclusion, I'm going to make a TODO: note and move on. Keep this.

I'll keep this in for now then.

PHP:
            case "skill 7074":    //Consume Burrowgrub is only ok three times per day
                return to_int(get_property("burrowgrubSummonsRemaining")) > 0;
            case "skill 7113":    //Squeeze stress ball can only be used 5 times per day
                if(to_int(get_property("_stressBallSqueezes")) >= 5)
                    return false;
                break;

Now these skills can take advantage of the new blacklist to avoid enqueueing too many of them. You can remove this bit after BatBrain updates.

I look forward to that :)

PHP:
            case "skill 7131":
            case "skill 7132":
            case "skill 7133":
            case "skill 7134":
            case "skill 7136":
                if(!no_bears())
                    return false; //Don't try multiple bear skills in one combat
            case "skill 7135":    //Bear Hug should only be used against plural monsters if you are a zombie slayer
                if (my_path() == "Zombie Slayer" && howmanyfoes > 1 && no_bears()) return true;
                else if (my_path() != "Zombie Slayer" && no_bears()) return true;
                else return false;

I still haven't gotten bear skills integrated. I guess not particularly enjoying Zombiecore and not having a set of arms to boot are factors here. Keep this.

I don't either but as other people seem to have that not having this leads to problems :)

PHP:
            case "skill 11000": //Mighty Axing 
            case "skill 11001": //Cleave
                return (no_cunctatitis() && no_teleportitis() && have_equipped($item[Trusty]));
            case "skill 11006": //Throw Trusty
                return have_equipped($item[Trusty]);

BatBrain wasn't checking for Trusty for both Cleave and Throw Trusty. Added those checks, so now your check for Trusty equipped is unnecessary. I'm assuming here that none of those skills work unarmed.

I think that is correct yes, and I'll remove that then.

PHP:
            case "skill 12010":    //Ravenous Pounce
            case "skill 12011":    //Distracting Minion
                return no_cunctatitis() && no_teleportitis();

All good. I'm beginning to like the idea of a flag for melee skills. Then you could just check that flag rather than each skill case.

That would certainly help with some things yes.

PHP:
            case "jiggle":
                if (equipped_item($slot[weapon]) == $item[Staff of the Staff of Life])
                    return to_float(my_hp()) / my_maxhp() < 0.4;
                else if (equipped_item($slot[weapon]) == $item[Staff of the All-Steak])
                    return has_goal(m) < 0.15;
                else
                    return true;

The bug there for All-Steak has already been mentioned, but otherwise this is all good. These new chefstaffs present a bit of difficulty, since all chefstaffs share the same action id "jiggle". We can't deliberately ignore that id, so it's going to need some custom handling. TODO.

Well, you can still only use one jiggle per fight. ANd so far there are only 4 limited use chefstaffs, which currently aren't being tracked by Mafia, so currently there is no way to avoid using it more than 5 times per day since, as you say, the macroid is the same for all of them. WHen Mafia adds tracking we should be able to check equipped_item($slot[weapon]) versus the relevant property and decide upon that.

PHP:
            case "attack":
                return (my_path() != "Avatar of Jarlsberg" && ((my_path() != "Avatar of Boris" && no_cunctatitis() && no_teleportitis()) ||
                        (my_path() == "Avatar of Boris" && (!have_equipped($item[Trusty]) && no_cunctatitis() && no_teleportitis()) || (contains_text(to_string(m),"Naughty Sorceress") || m == $monster[Bonerdagon] || have_effect($effect[temporary amnesia]) > 0))));
        }

The new BatBrain auto-blacklists "attack" for AsoJ (I guess that would be the plural of AoJ). Otherwise, this is all good.

Yes, the AoJ fix is there mainly since BatBrain wasn't updated yet since AoJ came out. I look forward to removing that since that logic does need to get slightly less convoluted :)

OK! I hope this was helpful -- it was intended as helpful, not critical. I really should have looked at this sooner to note some of BatBrain's failings. Some of them were really quite silly. Silly failings. Anyway, yay collaboration! Hopefully you will breathe a sigh of relief as you delete most of this function after the update. :)

Speaking of, I'm on track for an update this week. Or perhaps I should wait till 13.3.31? And I could call this version 1.31.31! It's only ten more days...

[/QUOTE]

Well, waiting to the last of March would allow me more time to adapt WHAM :)
 
Okay, I'm back to the see again and debugging on my lunch hour!

Code:
[989] An Octopus's Garden
Encounter: octopus gardener
Strategy: /home/scottk/.kolmafia/ccs/Destroy.ccs [default]
Round 0: Crowther loses initiative!
You lose 133 hit points
ATT: 435 (94% Ã 51.95, death in 15)
DEF: 372 (97.73% Ã 58.11, win in 11)
HP: 608, Value: 3,836.3 ., RES: 0
WHAM: Monster HP is 608.0.
WHAM: Running SmartStasis
Profit per round: ActionProfitDamageOtherbase (0.)0.--
1/5 monsters drop goals here.
Custom action: use 821 (stun first with use 5561)
Auto-funk: merging 'use 5561' and 'use 821'.
Custom action: use 822 (no stun)
Round 1: Crowther executes a macro!
Round 1: Crowther uses the Rain-Doh indigo cup and uses the bubbly potion!
You gain 171 hit points
Round 2: Crowther uses the smoky potion!
You lose 124 hit points
WHAM: Starting evaluation and performing of attack
WHAM: Reached WHAM_round_limit while looking for a way to kill the monster. Executing the current strategy and continuing from there.
WHAM: Enqueuing a stun to help with the battle
WHAM: Enqueueing attack with your weapon (macroid attack). Estimated damage: 56.78931940087406.
WHAM: Enqueueing attack with your weapon (macroid attack). Estimated damage: 56.78931940087406.
WHAM: Enqueueing attack with your weapon (macroid attack). Estimated damage: 56.78931940087406.
WHAM: Enqueueing Candyblast (macroid skill 3022). Estimated damage: 32.0.
WHAM: Enqueueing Candyblast (macroid skill 3022). Estimated damage: 32.0.
WHAM: Enqueueing Candyblast (macroid skill 3022). Estimated damage: 32.0.
WHAM: Enqueueing Candyblast (macroid skill 3022). Estimated damage: 32.0.
WHAM: Enqueueing Candyblast (macroid skill 3022). Estimated damage: 32.0.
WHAM: Enqueueing Candyblast (macroid skill 3022). Estimated damage: 32.0.
WHAM: We are going to 10-shot with Entangling Noodles, attack with your weapon, attack with your weapon, attack with your weapon, Candyblast, Candyblast, Candyblast, Candyblast, Candyblast and Candyblast.
Round 3: Crowther executes a macro!
Round 3: Crowther casts ENTANGLING NOODLES!
Round 4: Crowther attacks!
Round 5: octopus gardener takes 56 damage.
Round 5: Crowther attacks!
Round 6: octopus gardener takes 5 damage.
You lose 125 hit points
Round 6: Crowther attacks!
Round 7: octopus gardener takes 55 damage.
You lose 92 hit points
Round 7: Crowther casts CANDYBLAST!
Round 8: octopus gardener takes 36 damage.
You lose 105 hit points
Round 8: Crowther casts CANDYBLAST!
Round 9: octopus gardener takes 34 damage.
You lose 134 hit points
Round 9: Crowther casts CANDYBLAST!
Round 10: octopus gardener takes 34 damage.
Round 10: Crowther casts CANDYBLAST!
Round 11: octopus gardener takes 32 damage.
You lose 136 hit points
Round 11: Crowther casts CANDYBLAST!
Round 12: octopus gardener takes 36 damage.
You acquire an item: Wint-O-Fresh mint
You lose 106 hit points
Round 12: Crowther casts CANDYBLAST!
Round 13: octopus gardener takes 31 damage.
You lose 94 hit points
Look! You found 1 Wint-O-Fresh mint (50.)!

Conditions not satisfied after 1 adventure.
Autorecovery failed.
What I notice here is death was predicted in 15 rounds and I died earlier. Then I noticed that damage is predicted as 94% x 51.95, but I'm getting hit for 94-136 damage. That would be enough to cause things to fail. I know nothing about monster damage formulas. Time to look into that.

The first attack the monster got in is obviously a critical hit, but yes ~115 is definitely more than 52...
 
The first attack the monster got in is obviously a critical hit, but yes ~115 is definitely more than 52...
It's about double, so I did another silly hack. I added "if (my_location().zone == "The Sea") res[m.attack_element] = res[m.attack_element] * 2;" to m_regular() in BatBrain and now things are working well, but I really doubt that's the correct formula.

P.S. I'm excited about all the upcoming changes! It sounds awesome.

EDIT: Stupid Mer-kin healers are still a problem.
 
Last edited:
Crowther: I'm noting some bang potions there. That could be the source of the problem in that fight -- especially if you threw two monster-buffing ones and don't have Manuel.
 
Crowther: I'm noting some bang potions there. That could be the source of the problem in that fight -- especially if you threw two monster-buffing ones and don't have Manuel.
Good point. That was after losing three fights in a row with verbosity too low. I have the Manuel and those potions turned out to be "bubbly: detection (have 304) smoky: mental acuity (have 2032)", but still a good point. Sorry I didn't check before.
 
Hmmm, is it possibly ignoring DA? Or maybe there's a DA penalty for diving too? Just throwing things out there now.

Also, I've decided on 13.3.31 for the update, that synchronicity of palindromes doesn't happen often enough to justify missing it!
 
Back
Top