BatBrain -- a central nervous system for consult scripts

Probably uses it while you have HP/MP missing and not otherwise. Since the meat is... what, 4.95 meat per round, if we hold that there's a 1/4 chance of 60 meat, with a 1/3 chance of that? In reality, the chance of meat is probably even lower, since there's... 6 different (I'm thinking off the top of my head) attacks instead of 1?
 
1.16 Update!

There have been enough worthwhile changes to my local copy of BB that I figured it was time for an update, despite the fact that none of the features I previously promised are included yet. :)

The big ones:

  • BB has been rearranged a bit and it now has a function called set_monster(monster) which handles setting all the global variables and fvars and such for a specific monster. This means that you can now use BB to check how defeatable/dangerous a given monster is outside of combat. Pretty friggin' sweet. For consult scripts, you will not notice a change: set_monster() is automatically called when you call act() without previously initializing BB to a specific monster.
  • BB now caches a few important values per round: the base round event (including your familiar, equipment, and effects), and the monster event (including its attack and possible special moves, and the retaliation event). This means that when BB sorts actions by profit, it doesn't have to calculate these values every time for each action. I've wanted to do this for a while but my previous implementation left something to be desired. This is working much better and I'm very happy to release it.
  • Also in the interest of speed, if combat is finished act() will exit after finishing its detections, before rebuilding options or responding to specific events. Duh, right?

Those of you using BB-powered scripts should find that you are laying down much more rapid smack these days.

Beyond that, there were some other smaller improvements, such as a bugfix for the Crown of Thrones (stasis would continue even after the enthroned familiar dropped its item), and an improved sort algorithm for attack_action().

Enjoy! Those other features really are coming, I promise.
 
Thanks.

I've kinda been looking forward to those enhanced queue features so I can rewrite DAM to take advantage of them. While I continue waiting I'll enjoy the super speed smack down.

I have a request: Could you add potato effects for the pants rack? Considering the popularity of the spangly mariarchi pants for superfairy power it seems a shame not to take advantage of the super potato effect that comes along with it.
 
Something I noticed yesterday, while testing out automating the basement with my spamattack script, is that the blocking of actions done by the monsters there are not properly initiated by batbrain. I added a local change so that the dimensional horror gets a "blocks_attack" boolean set to true and changed hit_chance to reflect this (adding a multiplication of to_int(!blocks_attacks) to the first "through"-calculation).

There are probably much better ways of doing it, but since Mafia now properly separates those monsters it might be good to take a look at that part of the monster-switch.

Edit: Or have you already fixed this in 1.16? At least there is a special handling for the horror which I don't remember seeing in 1.15...

Edit, edit: No, not fixed but it was there. So changing the attack-decision from "kill_rounds(get_action("attack"))" to "kill_rounds(regular(1))" solves that part of the problem...
 
Last edited:
@Bale: Since it's a batfactors issue, you could add them yourself (or even just the spanglepants) if you have time before I do. Which, knowing what I know of you (5,543) and me (2,278), is probable.

I'm looking forward to to_macro() too -- the big problem at the moment is the low hp aborts. I want to keep action id's pure in the queue, only adding all the fancy stuff when it's actually time to convert it to a macro. However, this turns out to be quite a trick, the way things are. I'm thinking of just abandoning them altogether -- if you're automating, you want to automate, right?

@Winterbay: What? get_action("attack") and regular(1) are identical as far as damage -- the latter just doesn't include the onhit and critical events. You're meant to use the former.

I must admit, it was very satisfying seeing my script become smart about the shadow and basement monsters when Veracity ambiguated the monsters that needed ambiguating. All the code was already there (I hope... we'll see).

I haven't tried to automate the basement using BB yet, but now that it's possible it will be a really good place to tweak its functionality against a wide variety of monster levels -- once it works as intended its adaptability will be fantastic, since one of the stumbling blocks for fully automating the basement is that your strategy often changes at certain points and you have to keep modifying your CCS, as the monsters get stronger. Either that or just totally overkill them towards the beginning with Spectral Snapper or love songs or what have you.

Can you be clearer about what exactly is going wrong against the horror? It looks to me like BB correctly sets damage to 0 for melee attacks against it.
 
Oh... The problem was that my will_attack()-function would attack them since for some reason the damage from my regular attack was calculated such that it would always attack it.

The function currently looks like this (the change mentioned above was made in the "rounds_to_kill"-calculation):
Code:
boolean will_attack()
{
	int rounds_to_kill;
	boolean no_attack = (m == $monster[procrastination giant] || contains_text(to_lower_case(to_string(m)), "quantum"));

	if(get_action("attack").id != "")
	{
		int round_limit = (my_primestat() == $stat[moxie] ? minmax(maxround - round, 1, maxround) : minmax(maxround - round, 1, 10));
		rounds_to_kill = to_int(kill_rounds(regular(1)));

		//Info printing
		vprint("SpamAttack: " + (rounds_to_kill + round  < maxround ? "You will kill the monster in " + rounds_to_kill : "You won't kill the monster before " + maxround) + " rounds with your basic attack.", "purple", 7);
		vprint("SpamAttack: The monster will take " + (die_rounds() > maxround ? "more than " + maxround : die_rounds()) + " rounds to kill you.", "purple", 7);
		//Debug info printing
		vprint("rounds_to_kill: " + rounds_to_kill + ", round_limit: " + round_limit + ", maxround: " + maxround + ", die_rounds(): " + die_rounds() + ", hitchance(\"attack\"): " + hitchance("attack"), "purple", 9);		
		
		if(rounds_to_kill < round_limit && die_rounds() > rounds_to_kill && hitchance("attack") > 0.5)
		{	//How many rounds will it take me to kill the monster by attacking
			vprint("SpamAttack: Expected received damage per round: " + m_dpr(0,0) + ", Rounds to kill: " + rounds_to_kill + ", Expected damage: " + dmg_dealt(get_action("attack").dmg) + ", Hit chance: " + hitchance(1),"purple",9);
			if(!no_attack) //Do not attack evil monsters
			{
				vprint("SpamAttack: Monster is weak. We are just going to bash its head in. It'll take " + rounds_to_kill + " rounds.", "purple", 2);
				return true;
			}
		}
	}
	return false;
}

I have not run into a horror today yet so don't know if it actually works better, I just assumed so since regular(1) had handling for the horror while the calculation for opts is a bit unclear to me :)
 
Has zlib's my_defstat been updated recently? Mafia currently complains that batbrain is trying to call my_defstat(boolean) which isn't defined in my zlib at least. Line 535:
[code res = max(1.0,max(0.0,max(monster_stat("att"),0.0) - my_defstat(true)) + 0.225*max(monster_stat("att"),0.0) - numeric_modifier("Damage Reduction")) * (1 - minmax((square_root(numeric_modifier("Damage Absorption")/10) - 1)/10,0,0.9));[/code]
 
@Bale: Since it's a batfactors issue, you could add them yourself (or even just the spanglepants) if you have time before I do. Which, knowing what I know of you (5,543) and me (2,278), is probable.

Um? Really? I looked it over with respect to adding it into batfactors and my conclusion was that your hatrack/pantsrack code only supports them as attacking familiars. How do I add pants as a potato or barrrnacle?
 
Double posting, since completely different question:
"Weapon of the Pastalord" is always physical unless you are attuned when half the damage is physical and half is of the other element. At the moment this seems to not be the case and batbrain reports 191 damage against a physical resistant monster when it in fact is 1. I think it did work earlier so the question is what changed?

Edit: For what it's worth I can't reproduce the dimensional horror anymore in 10243 so either some change I did fixed it or some change in Mafia fixed it :)
 
Last edited:
How do I add pants as a potato or barrrnacle?

BB doesn't need to know anything about barrrnacle-types, since they only act at the beginning of combat. As far as BB is concerned, it's the same as fighting a rather weak version of a monster with a useless familiar.

There are plenty of examples of potato-types in the hatrack category.

batbrain reports 191 damage against a physical resistant monster when it in fact is 1. I think it did work earlier so the question is what changed?

I don't think I changed anything about the way WotP is handled. Perhaps BB just doesn't know about that monster's resistance?
 
I don't think I changed anything about the way WotP is handled. Perhaps BB just doesn't know about that monster's resistance?

It was durign my basementing attempts and the monster in question was the ghost of fernswarthy n great-grandfather which I assume by this code is classed as a resistent monster:
Code:
case $monster[the ghost of fernswarthy n great-grandfather]: mres[$element[none]] = 1; maxround = 50; break;

For now I've changed lines 445-446 to:
Code:
if (to_skill(in) == $skill[weapon of the pastalord] )//&& !contains_text(factors[ty,in].dmgtypes,"physical")
   factors[ty,in].dmgtypes = "physical";
which while it will stop the pastalord weapon from being non-physical at least stopped it using it against the ghost.
 
When you release a new version of BatBrain, could you turn the MaxRound Int into a ZLib Variable? I have a couple of accounts that keep failing to kill things like the snow queen unless I drop it down to 20 on them. (they are both running the hobo monkey and in the cases I've seen them fail, the monkey grabbed meat before SS started)
 
Sorry, but I don't believe that fits the bill for a script setting. The maximum round is always 30, unless it's 50. If the script is getting you killed then there is a problem with the script's use of the combat scenario information. Tricking the script by using false information is not a road I want to head down.

It does sound a bit like SS isn't being used correctly, however. If you want SS to properly note events which have happened, they have to happen within the script's execution, which means you can't have any actions in your CCS prior to calling a BB-powered script. If you want to add some actions before the stasis loop, add them in the script, after SS filters the page and detects events which have happened.

If there are no actions in your CCS prior to SS, then that sounds like a bug in the script's detection of monkey theft. Can you confirm either of these possibilities?

Detection of Monkey Theft.

Detection of Monkey Theft.
 
I do have actions prior to SS execution, since SS doesn't always decide that it is best to utilize certain DB combos in fights, while it might not be 'cost effective' it is a marginal gain, for an MP cost that will be regenerated, so I prefer to do them as well, with SS first, it will use too many rounds prior to me being able to do those combos. As I said, the script appears to work properly when the Monkey theft is inside the SS loop, if the monkey steals early, it will stasis until round 30 and either lose the fight due to too many rounds, or break my automation. To get around this issue, I keep going into the script and changing the int max_rounds to 20 vs 30. This resolves my issue, with a very minor change...
 
So what you really want is for SS to use disco combos so you don't have to use them before calling SS, if you're going to use the script the way it's meant to be used.
 
You might be surprised if you did the math -- I really believe SS knows well about the profitability of your combos. MP which will be regenerated is already considered mostly free to use, so I'm fairly confident that in cases where SS doesn't cast certain combos, those combos would actually cost you. If you have evidence to the contrary, I'd be quite interested to see it.

If you want to execute combos even though they might cost you a little bit of meat, you could change line 381, which is where it skips combos that are not profitable:

PHP:
   foreach n,com in combos if (monster_stat("hp") > dmg_dealt(com.dmg) && to_profit(com) > 0 &&

Change that 0 to some other lower number, such as -20. Then, even if the combo will cost you up to 20 meat, it will still cast it. This has the benefit of still filtering out combos appropriately (e.g. not casting meat bonus combos on monsters that don't drop meat).
 
Back
Top