Winterbay's Helpful Automatic Monsterbasher (WHAM)

You don't
Code:
if (to_int(get_property("fistSkillsKnown")) > 0) fvars["fistskills"] = to_int(get_property("fistSkillsKnown"));
at the top? I think, if I read the code correct, that eval() gets called with fvars as a list of potential variables which then gets replaced in much the same way you have up there in said eval-function.
Well idk then I had to make that change for it to work for me even with that line, and I'm using an unmodified BatBrain otherwise.
 
Unsure if this is all that needs to be changed, I will update the post accordingly if I find other weirdness, but I dislike reading through BatBrain.ash.
When reading Zarqon's code, I think it's all about the flow. It makes it hard to pick up a specific information without following the logical flow from start to end, but once you twist your mind around what's going on, you realize how smoothly everything comes together.

I guess he doesn't write code like an engineer writing a clear and maintainable piece of software, but like someone who takes pleasure in weaving together logical patterns.
 
you realize smoothly everything comes together

I'm not really sure how unconventional and difficult to maintain code can be at the same time considered "smooth", but if you say so.

Reading zarqon's code, for me, is like reading code written by my boss: a good idea for the business that hasn't been thought of before, written in spare time, in between doing other things, hasn't read a code standards book in his life but at the end of the day it gets a job done. It's spaghetti code essentially, "I can see what you're trying to do, but what were you thinking!?". Zarqon has even managed to confuse himself with his own logic flow in the past.

I dislike looking at BatBrain because almost every time I do, I find something completely not functioning as intended with it (and nobody seems to realize). Sometimes, I'd much rather be blissfully unaware of what goes on behind the scenes when I click "run".

I highly respect zarqon for his ideas and his fairly unique approach to solving certain problems, but being a little more clear and concise certainly wouldn't go unappreciated.

I know zarqon has said in the past that his code isn't really written with the intention of other people understanding or maintaining it, but the reality of all coding is that there are going to be bugs and it's not always going to be the person who writes that code who is going to find them.
 
Last edited:
... zarqon has said in the past that his code isn't really written with the intention of other people understanding or maintaining it, ...

tl,dr: if other people won't understand your code, then you can bet time will come *you* will need to understand that code ... and won't.
 
tl,dr: if other people won't understand your code, then you can bet time will come *you* will need to understand that code ... and won't.

Oh yes, I feel that every time I reopen one of my two big excel files at work where I've built somewhat advanced macros into them and need to understand why something isn't working as intended. I do not understand Visual Basic/Macro language well enough to debug it easily (and the error messages are generally very unhelpful) and it is most often 3-4 months between the need to open them up and change things so I forget what I was thinking at the time. My lack of good comments isn't helping either I guess... :)
 
When checking suitability of skill consideration, it actually parses fight.php for unavailable skills and it doesn't break if it finds that the skill is unavailable... It doesn't work at all.

I changed:
Code:
if (skillsbit == "" ? !have_skill(to_skill(sk)) : !contains_text(skillsbit,"value=\""+sk+"\"")) continue;
to
Code:
if (skillsbit == "" ? !have_skill(to_skill(sk)) : !contains_text(skillsbit,"value=\""+sk+"\"")) break;
and now WHAM runs a heck of a lot better for me.

Now it's properly excluding skills that aren't available, which probably solves a bunch of problems that Winterbay has had to write around for a long time now.

Edit: Unsure if this is all that needs to be changed, I will update the post accordingly if I find other weirdness, but I dislike reading through BatBrain.ash.

What does it matter if you break or continue? Neither of them will lead to it getting added to the general available options in opts[] since the adopt()-call that adds that specific skill to opts[] is within said foreach-loop. Adding a break would surely make it skip out of the loop entirely and thus skip processing any further skills after the one that is not available any more (unlike continue which should move on to the next skill in the list), or is my non-programmer brain making things up?
 
is my non-programmer brain making things up?

Probably not. I don't think I posted the correct fix, but what I can tell you is that prior to making that change, WHAM was considering skills I couldn't use.

I think the conditional logic is messed up somewhere there, I tried a few different things and made edits to the post but in the end, breaking was the simplest fix that allowed me to do a run without getting stuck in endless fight.php loops every single combat due to unavailable skills being consistently considered the best option.

I intended to edit my post after finding the correct fix, but I got kinda sick of looking at BatBrain and was just happy to finally be able to stop baby-sitting KoLmafia. I might look more today, but feel free to look into it. You're probably more familiar with the inner workings of BatBrain than I am.

Edit: This might provide some clues, I added some print statements to see if that particular condition is being fired, it seems to work which suggests to me that something later down the track isn't working and I my "fix" simply breaks out before whatever goes wrong actually happens.

Code:
Clobber in skillsbit
Entangling Noodles in skillsbit
The 17 Cuts in skillsbit
Feed in skillsbit
WHAM: Enqueueing Summer Siesta (macroid skill 7062).
WHAM: Failed to enqueue Summer Siesta (entry 2 in the strategy).
WHAM: The following combat strategy was attempted: 
Rain-Doh blue balls
Summer Siesta
Feed

The "in skillsbit" is what I added. As you can see, WHAM/BatBrain knows that Summer Siesta isn't in skillsbit prior to attempting to enqueue, but still enqueues it anyway.
 
Last edited:
Yeah, doesn't changing that continue to a break make it stop considering all skills after that in the list?
 
Yeah, doesn't changing that continue to a break make it stop considering all skills after that in the list?

Correct. I must admit I wasn't understanding what the code was doing properly, I didn't realize BatBrain was actually looping through every known skill in the database.

In theory, what you would expect though is that if I had that break there, combat would stop entirely because the for loop is probably going to break before it even considers skills I actually have. That's not what was happening though, combat was working perfectly.

I think what may be happening is the options are being retained (somehow). I don't understand why Summer Siesta would even appear as an option if that condition were met and the for loop were to continue, as Winterbay said, addopt doesn't run until much later in the loop.

What I would expect to happen is that build_options is ran, 2nd line of build_options clears opts (supposedly?) do some more stuff, come down to build_skillz, iterate through every known skill, if a known skill doesn't appear in the drop down menu of the skills list (skillsbit), it should skip the remainder of the for loop and try the next skill, therefore never reaching the code that adds it to opts.
 
Squeeze Stress Ball is causing an infinite loop, might be in SmartStasis.
 
Last edited:
Squeeze Stress Ball is causing an infinite loop, might be in SmartStasis.

I posted about it here. The issue is actually with BatBrain not removing unavailable skills from options.

I haven't put my finger on where the issue lies yet, but what I posted here should at least stop WHAM from infinite looping, at the expense of possibly other skills not being considered (I haven't had time to investigate further).
 
Well, not really. The skill can get used 5 times per day and it can currently get enqueued more times than that since it may be ok to use the first time it's cast but not the second time. I need to add code to make sure it gets enqueued at most 5 times per day.
 
I need to add code to make sure it gets enqueued at most 5 times per day.

The skill shouldn't even be in options if it has been used 5 times. AFAIK, you can only use it once per combat but up to 5 times a day.

Tracking how many times it has been used in a day is pretty irrelevant, because BatBrain should be removing it from options if it doesn't appear in the skill dropdown.
 
Wanted to note that it's still sometimes ignoring the set variables.
WHAM: Current monster HP is calculated to 221.0
WHAM: Starting evaluation and performing of attack
WHAM: Could not find a way to kill the monster. Trying the best available option since you've set WHAM_AlwaysContinue to true.
WHAM: We are going to 1-shot with Knob Goblin superseltzer.
Round 29: Theraze executes a macro!
Round 29: Theraze uses the Knob Goblin superseltzer!
You gain 29 Mojo Points
Round 30: mer-kin healer heals 277 hit points.
WHAM: Current monster HP is calculated to 498.0
> zlib WHAM

Copy/paste/modify/enter any of the following lines in the CLI to edit settings:

zlib WHAM_AlwaysContinue = false
zlib WHAM_happymediumglow =
zlib WHAM_hitchance = 0.5
zlib WHAM_maxround = 30
zlib WHAM_noitemsplease = false
zlib WHAM_round_limit = 10
zlib WHAM_safetymargin = 10
(If no values were shown, no settings or values matched your input text. Type "zlib vars" to see all.)
So my always continue is false, but WHAM keeps believing it's true. Any additional lines I need to add to help figure this out?

Edit: Appears from this:
Code:
				//There is no way of directly killing the mob in our current state, we need to either restore HP, MP or delevel
				//TODO: Add HP and MP restoration and weight those with deleveling
				delevel = delevel_option();
				while(delevel.id != "" && killer.id == "") {
					if(!enqueue(delevel))
						break;
					delevel = delevel_option();
					killer = attack_option();
					if(my_stat("hp") < m_dpr(0,0))
						break;
				}
				if(killer.id == "" && !to_boolean(vars["WHAM_AlwaysContinue"])) {
					vprint("WHAM: Unable to delevel until you can kill the monster without it killing you. Try it yourself.", "purple", 3);
					return sorted_kill;
				} else {
					vprint("WHAM: Could not find a way to kill the monster. Trying the best available option since you've set WHAM_AlwaysContinue to true.", "purple", 5);
					allMyOptions(hitchance); //Recalculate our options before doing this part
					sort myoptions by -to_profit(value);
					sort myoptions by kill_rounds(value.dmg)*-(min(value.profit,-1));
					enqueue(myoptions[0]);
					kill_it[i].hp = monster_stat("hp");
					kill_it[i].my_hp = my_stat("hp");
					kill_it[i].profit = (i == 0 ? get_action(myoptions[0]).profit : kill_it[i-1].profit + get_action(myoptions[0]).profit);
					kill_it[i].options = myoptions[0].id;
					reset_queue();
					act(page); //Needed so that items that some things do not get out of synch with batbrain
					return kill_it;
				}
that the message is due to a bad if-check. Should probably use this for the killer/always check instead:
Code:
				if(killer.id == "") {
					if (!to_boolean(vars["WHAM_AlwaysContinue"])) {
						vprint("WHAM: Unable to delevel until you can kill the monster without it killing you. Try it yourself.", "purple", 3);
						return sorted_kill;
					} else {
						vprint("WHAM: Could not find a way to kill the monster. Trying the best available option since you've set WHAM_AlwaysContinue to true.", "purple", 5);
						allMyOptions(hitchance); //Recalculate our options before doing this part
						sort myoptions by -to_profit(value);
						sort myoptions by kill_rounds(value.dmg)*-(min(value.profit,-1));
						enqueue(myoptions[0]);
						kill_it[i].hp = monster_stat("hp");
						kill_it[i].my_hp = my_stat("hp");
						kill_it[i].profit = (i == 0 ? get_action(myoptions[0]).profit : kill_it[i-1].profit + get_action(myoptions[0]).profit);
						kill_it[i].options = myoptions[0].id;
						reset_queue();
						act(page); //Needed so that items that some things do not get out of synch with batbrain
						return kill_it;
					}
				}
Alternatively, the else that goes into the alwayscontinue should change from else to else if (killer.id == "") instead.
 
Last edited:
I think what is most interesting is that it thought it could kill the monster with a MP-restorer... But I agree on the change, however it wouldn't have stopped the problem in your case I think seeing as killer.id obviously wasn't empty. Or am I missing something?
 
Last edited:
Condition: There is no successful killer.
Part 1: Try to delevel the monster and then, after delevelling, mark if there's a successful killer.
Part 2a: If there is no successful killer and alwaysContinue is false, abort and let the player sort things out.
Part 2b: If there is a successful killer OR alwaysContinue is true, throw out the killer if it exists and start over.
Afterwards (use if condition is not true or Part 2b finished successfully): Use the killer.

As you can see, if alwaysContinue is set to false and you do delevel the mob, WHAM will slow itself down by tossing out its information on killer actions. Either Part 1 should not try to calculate a new killer skill and WHAM should always abort if delevelling is needed, or Part 2b should NOT trigger if you have a killer action.
 
I am running 11710 of mafia, the most recent WHAM and have my CCS set as follows:

[ default ]
try to steal an item
consult WHAM.ash

But when it runs against Crimbotown monsters it never tries to pickpocket as you can see below:
[7741] Crimbokutown Toy Factory
Encounter: Chairo Kitsune
Strategy: C:\Users\ebrown.LXICORP\Desktop\Dropbox\Kolmafia\ccs\default.ccs [default]
Round 0: txranger wins initiative!
WHAM: Running SmartStasis
WHAM: Starting evaluation and performing of attack
Round 1: txranger executes a macro!
Round 1: txranger attacks!
Round 2: plastic-extruding animelf takes 43 damage.
You lose 73 hit points
Round 2: txranger attacks!
Round 3: plastic-extruding animelf takes 48 damage.
Round 3: Tonald does a rousing rendition of "La Cucaracha" for him, then won't let him attack until Tonald gets a tip for the song.
Round 3: txranger attacks!
Round 4: plastic-extruding animelf takes 39 damage.
Round 4: Tonald does a rousing rendition of "La Cucaracha" for him, then won't let him attack until Tonald gets a tip for the song.
Round 4: txranger attacks!
Round 5: plastic-extruding animelf takes 38 damage.
You lose 74 hit points
Round 5: txranger attacks!
Round 6: plastic-extruding animelf takes 39 damage.
Round 6: Tonald does a rousing rendition of "La Cucaracha" for him, then won't let him attack until Tonald gets a tip for the song.
Round 6: txranger attacks!
Round 7: plastic-extruding animelf takes 39 damage.
You lose 72 hit points
Round 7: txranger attacks!
Round 8: plastic-extruding animelf takes 39 damage.
Round 8: Tonald does a rousing rendition of "La Cucaracha" for him, then won't let him attack until Tonald gets a tip for the song.
WHAM: Starting evaluation and performing of attack
Round 8: txranger executes a macro!
Round 8: txranger attacks!
Round 9: plastic-extruding animelf takes 42 damage.
Round 9: txranger wins the fight!
After Battle: Tonald tosses the hat to the ground and does a kind of disco hat dance around it, shouting "Olé , olé , stayin' alive!"
You acquire an item: plastic ingot
You gain 60 Strongness
You gain 35 Magicalness
You gain 73 Roguishness
 
That's because mafia thinks it isn't safe to do so. Use "pickpocket" in quotes instead to skip that check. It has nothing to do with WHAM.
 
Back
Top