BatBrain -- a central nervous system for consult scripts

By the way, here's my horrible version that seems to actually work (kinda).

Main Issues:
1) Not really macroable, I'm just exploiting BatBrain's damage formulas (biggest issue, it takes like 15 seconds per combat)
2) Since I didn't know how to get the maximum possible damage, I took the expected damage and multiplied by 1.5 (number picked out of the air)
3) If I wasn't using this in aftercore, I'm pretty sure I would get beaten-up because it takes 8-12 rounds per combat.
4) Pretty sure I'm using some square peg in round hole programming.


Code:
import "SmartStasis.ash";

//don't want to use any combat items except a seal tooth
boolean only_tooth(advevent a) {
	matcher aid = create_matcher("(use )(?:(\\d+),?(\\d+)?)?",a.id);
	if(aid.find())
	{
		switch(aid.group(1)+aid.group(2)) {
		case "use 2":  
			return false;
		}
		return true;
	}
	return false;
}

advevent attack_downto(int targethp)
{ 
	sort opts by -dmg_dealt(value.dmg);
	foreach i,opt in opts 
	{ 

		if (	(dmg_dealt(opt.dmg) == 0) ||
				(monster_stat("hp") - ceil(dmg_dealt(oneround(opt).dmg))) < targethp ||
				(opt.id == get_action("attack").id) ||
				only_tooth(opt))
		{
			continue;
		}
		
		//if it isn't a seal tooth, multiple by 1.5, just to make sure we don't go below 24
		//by accident
		if(opt.id != "use 2" && opt.id != "skill 3020" &&
		   (monster_stat("hp") - ceil(dmg_dealt(oneround(opt).dmg))*1.5) < targethp)
		{
			continue;
		}
		
		print("Attack action chosen: "+opt.id,8);
		print("Should deal: "+dmg_dealt(oneround(opt).dmg));
		return opt;
	} 
	
	return new advevent; 
}  

boolean main(int initround, monster foe, string pg)
{
	//init page
	page = act(pg);

	//always stun
	enqueue(get_action($skill[entangling noodles]));
	
	while (monster_stat("hp") > 24)
	{		
		enqueue(attack_downto(24));
		macro();
		reset_queue();
		print("Monster HP:"+monster_stat("hp"));
	}
	
	reset_queue();
	print("Should be at 24 HP, Comboing now.");
	enqueue(get_action($skill[Disco Dance II: Electric Boogaloo]));     
	enqueue(get_action($skill[Disco Dance of Doom]));     
	macro(get_action($skill[Disco Face Stab]));   
}
 
Last edited:
3) If I wasn't using this in aftercore, I'm pretty sure I would get beaten-up because it takes 8-12 rounds per combat.

I doubt it could be done in under 8 rounds in a run that's serious enough where disco bleeding isn't a major waste of resources (one where you're running a good amount of +ML). With under 20 skills hardcore permed, it probably isn't feasible or worth the MP cost.

Also, boo for reminding me that I should probably be doing this now that vcrisis isn't the main combat strategy.
 
Yeah, it's actually worth a surprising amount of substats over the course of a run. I do softcore runs mostly so mp/skills aren't an issue. Dying because I'm running 100+ ML is an issue.
 
Oh, I was looking at the wrong character then. Still, I have a feeling that the MP cost involved makes it not worthwhile even if you're being fueled by a Crown of Thrones. That looks like around 40 extra MP/fight, which you'll need to fund with seltzer at least some of the time, and the 320 meat could have been used to buy 2.4 mainstat instead of getting 3 overall substats.
 
Yeah, in practical application what I would do is probably only use it if I had a surplus of mp and a potato type familiar. Otherwise I'd call bale's script. But that part is pretty easy to handle.
 
I still mostly stand by my code for this application -- it considers your survivability and any other sources of damage, and will even use options like Entangling Noodles to prolong your life. The only change I would make would be to submit each action after enqueueing it, so all you'd have to do is change the while loop line like so:

PHP:
while (enqueue(attack_downto(24)) && !contains_text(page,"WINWINWIN")) macro();
 
Last edited:
Oh dear. It seems that kneebutt does not actually give +20 to hit. Yeah, the wiki and all common knowledge was wrong. It appears that the bonus to hit is probably twice your level with a maximum of 20. Sadly not much low level spading was done on this in the dark days before fisting.

Also, your current script seems to disallow the unarmed bonus for kneebutt. That's a mistake. Master of the Surprising Fist is definitely effective on kneebutt. So... you'll want to fix that for hitchance() something like....

Code:
case 2015: case 2103: attack = my_stat("Muscle") + (unarmed() && have_skill($skill[master of the surprising fist]) ? 20 : 0) + min(my_level() * 2, 20); break;
 
That could explain why my level 7 myst class was missing so much with his kneebutts that spamattack said to use. Well that and the fact that the script didn't take hitchance into account at all for skills, only basic attacks, so now it rejects anything that has a hitchance of less than 75%.
 
Oh dear. It seems that kneebutt does not actually give +20 to hit. Yeah, the wiki and all common knowledge was wrong. It appears that the bonus to hit is probably twice your level with a maximum of 20. Sadly not much low level spading was done on this in the dark days before fisting.

Did you collect some data? For now I started up a thread for that.
 
Sorry, no solid data. This is based upon the experiences of myself and some clannies in HCN who have been noting the rate of misses with Kneebutt when it should have been a certain hit. (It was the "that should NOT have been too much ML" kind of spading.)

Real spading (the kind with numbers and statistics) is seriously needed.
 
I've been trying to get my consultscript to use Release the Boots but it is not yet in batfactors so I made the following change to mine:

Code:
skill	7115	Release the Boots	0	physical

I also added the following to the build_skillz-function in batbrain, unfortunately the damage formula against bosses appears to not be spaded yet (at least it's not on the wiki) so I made something up that at least is plausible.
Code:
case 7115: if (m.phylum == $phylum[none]) {d = to_spread(8*fvars["fweight"],"physical");} else {d = to_spread(monster_stat("hp"), "physical");} break;

Also, it is not really "physical" as such since it works against resistant monsters but to_spread seems to demand an element. Or am I wrong?

The usage is then made conditional based upon "has_goal".

Edit: Uploaded an updated batfactors.txt which adds Release the Boots (so that it can at least be accessed even though it's not in Batbrain yet) and a missing scroll that I wanted to be able to use in a function for building scrolls with RAMs.
 
Last edited:
Today I'm fixing round parsing for multi-round pages -- in the process I discovered that all those helpful round numbers I can see in the relay browser are added by mafia -- it took me about 20 minutes to figure out why my regex wasn't matching those very clear Round X! messages (they weren't actually there).

Also, as a very cool part of the happenings revamp I'm going to use all the <!-- macroaction: blahblah --> messages that KoL adds to the page text to record all actions taken as happenings.

So far, I've accounted for two differences in canonical names (standard macro commands) vs. KoL's reported macroaction names: 1) single-item uses are shown as "use X, 0" and b) pickpocketing is shown as "steal" despite the canonical macro command being "pickpocket". For the former I'm simply not including the ", 0" in the matcher's group, for the latter I'm converting the name in set_happened().

Other than that, everything seems to match up so far. I haven't been able to test jiggling though, so could someone jiggle in a macro and tell me what the macroaction HTML comment is on the resultant page? Thanks!

@Winterbay: For insta-kills I usually do to_spread(6*monster_stat("hp"),"hot,cold,spooky,sleaze,stench,physical"); That way physically resistant monsters will still be seen as dead by this.
 
Last edited:
Getting this error as I'm adventuring underwater with my Cuddlefish using a fishy wand:
Evaluator syntax error: can't understand underwaterfam/3
Factoring in fishy wand: damage, meat 11.1111, stun 0.111, att -2, def -2
Evaluator syntax error: can't understand underwaterfam/3

Appears to be from this part of batfactors.txt
gear 3822 fishy wand {100,150,200}*underwaterfam/3 physical,hot,cold,stench,spooky,sleaze meat 11.1111, stun 0.111, att -2, def -2
but I have no clue how it's supposed to be fixed...
 
I think you may need to add a line somewhat like this at the start of batbrain:
Code:
fvars["underwaterfam"] = to_int(numeric_modifier("Underwater Familiar"));
 
1.15 Updates!

Two very important updates this time. First, the longstanding bug with round number detection is finally fixed. This should correct possibly confusing behavior in your scripts, since previously on a page load which displayed rounds 3-7, BatBrain erroneously thought it was now round 3 rather than 7.

Second, the happenings revamp is complete. All actions (which were submitted as macros) are now recorded as happenings. Additionally, all enqueued actions are recorded as happenings. These are two separate numbers, one for the number of times an event actually happened, and one for the number of times it was enqueued. If either number is > 0, happened(<actionname>) will be true. When resetting the queue, the queued number for all happenings is reset to 0, which means the queue is now reversible. Woohoo!

Also added a few other tweaks. BB now only builds the list of dangerous poisons once at the beginning of combat, since using attack_action() 5 times each time an action was enqueued was significantly slowing down script execution. Additionally the deleveling amounts for DB skills are now correctly doubled if Mistletoe has happened this combat.

Enjoy! Coming next: auto-funk will be fixed, there will be a shiny to_macro() function for the queue which returns a string, thus allowing you to collapse queues into easily-storable strings, and there will be a new global advevent for what happens when you win the combat.
 
Wowsers!

Enjoy! Coming next: auto-funk will be fixed, there will be a shiny to_macro() function for the queue which returns a string, thus allowing you to collapse queues into easily-storable strings, and there will be a new global advevent for what happens when you win the combat.

Holy Mother of Code; that's just amazing! So we will be able to use to_macro() to save the queue as a string called testmacro and then later run macro(testmacro)? That'll revolutionize my use of BatBrain!
 
Three new things that can only be used once per fight! Thank goodness you've got the code to handle them. 3-5 damage per round starting from the round you use them and continuing until the end of combat.

blue raspberry troll doll
cinnamon troll doll
grape troll doll
 
You can just add those to batfactors, assuming the Map Manager does indeed mysteriously work again. Use the "once" keyword in the special field. Make a note ("!!" keyword) about their ongoing damage. It appears that we'll also need an "ongoing" event in addition to the static "base" event.
 
I mysteriously updated batfactors with the three troll dolls. (It is so weird that we don't have five of them.)
 
Is this a good way to detect if something (say smartstasis) has used a free runaway to end the fight, if as with Bale's DAM or my Spamattack currently does, you include SmratStasis in the consult-script?

Code:
foreach str in $strings["use 2956", "skill 7015", "use 5231", "use 3121", "use 4251", "use 4872", "skill 7095", "use 3775", "skill 7024", "use 1959", "use 4045"]
{
	if(happened(str)) //Make sure we exit the script instead of aborting if a free runaway happened
		exit;
}
 
Back
Top