BatBrain -- a central nervous system for consult scripts

From the new content (probably not relevant until the monsters get added to Mafia):

Clara has 50% resistance, a softcap of 500, and an exponent of 0.5.
Unusual construct has 50% resistance, a softcap of 500, and an exponent of 0.5.
Granny Heckleton has 50% resistance, a softcap of 200, and an exponent of 0.5.

restless ghosts have 100% physical resistance.
restless ghost also has 75% elemental resistance (probably 25% per difficulty).
cyclopean moomy has 60% resistance (probably 20% per difficulty).
tough-as-nails grizzled bear has a softcap of 50, and an exponent of 0.7 (possibly higher softcap at lower difficulties).
These monsters all get +200% init on hard.

greycat's data says that Glenn has 50%, a cap of 100, and an exponent of 0.5.
 
I've just added the new combat skills to batfactors so that they can be accessed by my script, but there's a lot of information left to fill in...

Code:
skill	7268	Cowboy Kick	0	0	custom, once
skill	18001	Cowcall	0	0	
skill	18002	Pistolwhip	0	0	
skill	18003	Hogtie	0	0	
skill	18007	Unleash Cowrruption	0	0	
skill	19000	Lavafava	0	0	
skill	19001	Pungent Mung	0	0	
skill	19002	Canhandle	0	0	once
skill	19003	Bean Screen	0	0	stun 3, once
skill	19006	Beanstorm	0	0	
skill	19007	Beancannon	0	0	custom banish, endscombat, once
skill	20000	Snakewhip	0	0	
skill	20001	Fan Hammer	0	0	
skill	20002	Extract Oil	0	0	custom
skill	20003	Bad Medicine	0	0	
skill	20006	Good Medicine	0	0	
skill	20007	Long Con	0	0	custom attract, once
 
Well, Bad Medicine delevels monsters by (10+Medicine)%, where Medicine is the Medicine level shown by the briefcase of snakes. Good Medicine also scales w/ Medicine, and Snakewhip is dependent on venom.
 
Good medicine heals 20 + 5*medicine. I didn't run numbers on Snakewhip yet, but it does scale pretty clearly with venom.

Good medicine, bad medicine are once. Fan hammer disables shoot (which otherwise is once).
 
Whelp, that means we'll have to wait for mafia to provide information on medicine level before those can be added to the data file.

That sucks.
 
zarqon, to support Avatar of West of Loathing, BatBrain needs a tiny update: All unarmed attacks by Cow Punchers are automatic hits. Please add that bizarre exception to hitchance.

Also, is there a reasonable way to determine if a skill can only be used once? Sometimes I need to know if happened() is particularly relevant. To figure this out for my own combat script I borrowed the following ridiculously complicated code from WHAM:

Code:
boolean once(advevent act) {
	matcher optid = create_matcher("(skill |use |jiggle|attack)(?:(\\d+),?(\\d+)?)?",act.id);
	if(optid.find() && contains_text(factors[(optid.group(1) == "use " ? "item" : (optid.group(1) == "skill " ? "skill" : "chef")), (optid.group(1) != "jiggle" ? to_int(optid.group(2)) : to_int(equipped_item($slot[weapon])))].special, "once"))
		return true;
	return false;
}

I'm just suggesting that it would be really nice if advevent had a boolean once field. If we both missed a simpler method please tell us! Otherwise please add one.
 
Looking at that code I am very very certain that i did not write that. I must've stolen it from some older iteration of BatBrain in the first place. I'm definitely not good enough of a programmer to come up with that one :)
 
Last edited:
Good point. That kinda reeks of zarqon's touch, doesn't it? You probably stole it from some part of BatBrain in the distant past.
 
Hehe. SmartStasis also currently contains a fairly recent function to determine whether an action is "once", to avoid submitting a once-only action with repeats.

I know that for some reason I've been deliberately avoiding adding a "once" field to advevents. Yet, at the moment I can't think of a compelling reason why I shouldn't. Can you?
 
I already tried to think of a reason that it wouldn't be a good thing before I made the request. It seems that it would be reasonable to add that to build_items() and build_skillz() as well as build_options() for jiggle. Perhaps you just didn't like having to add such similar code in all three places?
 
Custom action: use 547 (stun first with skill 7182)
Custom action: use 547 (no stun)
Custom action: use 549 (no stun)
Auto-funk: merging 'use 547' and 'use 549'.
Custom action: use 550 (no stun)
Round 1: Theraze executes a macro!
Round 1: Theraze casts SOUL BUBBLE!
Round 2: Theraze uses the 334 scroll!
Round 3: Theraze uses the 334 scroll and uses the 30669 scroll!
You acquire an item: 668 scroll
Round 4: Theraze uses the 33398 scroll!
Round 5: Theraze casts SUCKERPUNCH!
The auto-funk code in BatBrain (lines 1491-1499) appear to not catch stun-first items properly. This makes me waste a LOT of turns farming scrolls. Heh.
 
Spading for AWoL spells:
Pistolwhip: stuns and deals sixgun damage
Cowcall: Deal (62-70) + (0.4 * Mysticality) + min(turns of Cowrruption remaining, 100) Spooky Damage to your opponent
Lavafava: Deals two hits of (4-5)+floor(0.1*Mys) Hot Damage, each hit hard capped at 50 and rolled separately
Pungent Mung: Deals (sixgun damage)+(10-15)+(0.5*Mys) Stench Damage, the stench damage is hard capped at 100
Beanstorm: Deals two different elemental hits of (20-30)+(0.25*Mys), uncapped
Shoot: Does sixgun damage.
Fan Hammer: Does sixgun damage three times.
Bad Medicine: Delevels monster attack and defense by ( 10 + Medicine Level ) %. This can exceed 100% with a Medicine level greater than 90.
Good Medicine: Gain HP equal to 10 * current medicine level, and staggers opponent.

sixgun damage: (by weapon holstered)
Code:
switch(holstered) {
case $item[Pecos Dave's sixgun]:
   return 50:
case $item[hamethyst-handled sixgun]:
case $item[baconstone-handled sixgun]:
case $item[porquoise-handled sixgun]:
case $item[custom sixgun]:
   return 35:
case $item[makeshift sixgun]:
   return 25:
case $item[reliable sixgun]:
   return 20;
case $item[rinky-dink sixgun]:
   return 15;
case $item[toy sixgun]:
   return 5;
}

That damage is increased by Well-Oiled Guns. How much?

To support this I believe that mafia needs to track hostered gun, medicine level and venom level. Is that correct? Anything else needed?
 
I have a brand spanking new computer, and haven't set up TortoiseSVN yet, but once I do we shall have us some cowpunching auto-hits.

Also, let me re-ask a question from a while back: when fighting the NS, how can you determine whether or not the mirror was broken?

And now, ladies and gentlemen, for some assorted responses to posts:

@Bale: I think I remember why I didn't want to add a "once" field -- it was a design consideration to encourage certain algorithm types over others. If you are using BatBrain as intended, you don't deal with specific ID names and instead enqueue or perform actions based on results criteria, and once-only items will not be present in opts[] if you have either performed or enqueued the action. But as it happened, SS needed to know the once information to avoid submitting with repeats. I'll sit on this a bit more, but I'm close to being persuaded.

@Magus_Prime: SS actually has rather thorough support for mayflies, so I'm a bit surprised by your report. Note this bit at the top of the function:

PHP:
boolean should_mayfly() {                // TODO: make this return an advevent
   if (!have_equipped($item[mayfly bait necklace]) || to_int(get_property("_mayflySummons")) == 30) return false;
   switch (where.zone) {
      case "Dreadsylvania":                                 // Freddies!
      case "Twitch":                                        // Chroner!
      case "Spring Break Beach":                            // Beach Bucks!
      case "Conspiracy Island":                             // Coinspiracy!
      case "That 70s Volcano":                              // Volcoinos!
      case "Dinseylandfill": return true;                   // Fun Funds!
   }

I note that The Glaciest hasn't been added yet, but other charter zones should all be using your mayflies like mad. I've added the Glaciest locally and will update it when I can. Did you only encounter this issue in the Glaciest, or is there a larger problem here?

@heeheehee: Thanks for the BatBrain-relevance-specific monster spading reports! However, the physical resistance information goes in mafia now, not batfactors. I note that as it seems you have commit access, you might add that information in yourself. :)

@Theraze: I haven't done the scrolls sidequest in quite some time but I suppose I could have another go of it, to try to make scroll support native to SS. There is presently no special handling for scrolls. You could try deleting the damage-to-profit check from the auto-funk code and see if that fixes it for you.

@Bale again: I'd suggest requesting medicineLevel and venomLevel properties, and a "Sixgun Damage" numeric modifier (similar to the "Song Duration" modifier for accordions). Then we should be able to fully support all that stuff.
 
Also, let me re-ask a question from a while back: when fighting the NS, how can you determine whether or not the mirror was broken?
There doesn't seem to be any code in Mafia to handle the status of the mirror.

@heeheehee: Thanks for the BatBrain-relevance-specific monster spading reports! However, the physical resistance information goes in mafia now, not batfactors. I note that as it seems you have commit access, you might add that information in yourself. :)
Sure, the main relevance was the softcap / exponent for the monsters; I figured I might as well include the other info I'd noticed, as well.
 
@Magus_Prime: SS actually has rather thorough support for mayflies, so I'm a bit surprised by your report. ... I note that The Glaciest hasn't been added yet, but other charter zones should all be using your mayflies like mad.

I was spending thousands of adventures in The Glaciest.
 
Also, let me re-ask a question from a while back: when fighting the NS, how can you determine whether or not the mirror was broken?

Does it do anything other than grant the Confidence effect in exchange for a turn?
 
Last edited:
Breaking the mirror also makes the NS harder to defeat (adds nostagger as well as +50% base HP).

The Confidence intrinsic is okay for these purposes, but if you leave the tower and adventure somewhere, you lose the effect.
 
@Theraze: I haven't done the scrolls sidequest in quite some time but I suppose I could have another go of it, to try to make scroll support native to SS. There is presently no special handling for scrolls. You could try deleting the damage-to-profit check from the auto-funk code and see if that fixes it for you.

Rather than completely removing that part of the code, I've instead added the rampaging adding machine as another exception monster. Currently looks like this:
Code:
   if (allowfunk && have_skill($skill[ambidextrous funkslinging]) && count(queue) > 0 && m != $monster[the thorax] && m != $monster[rampaging adding machine] && bob.find()) {
though I could have potentially done something like this if we expected to keep this forever:
Code:
   if (allowfunk && have_skill($skill[ambidextrous funkslinging]) && count(queue) > 0 && !($monsters[the thorax, rampaging adding machine] contains m) && bob.find()) {

Since I expect the long-term fix to be either full-funk if you'll survive or no-funk if your health is at risk, I don't think we probably need the second. But it is another option if you end up having a ton of no-funk exceptions.
 
Looks like we can solve the majority of the Sorceress issue by adding "nostagger max(0,1.0-effect(1791))" to batfactors. People who lose their confidence before reaching the NS are probably in the minority, and erring on the side of monster toughness is preferable to erring the other way.

@Theraze: Isn't funkslinging scrolls still desirable? We simply want to make sure the scrolls we want to combine are being funked together, right?
 
For Sorc, anyone who fails to wand-farm before the Sorc will end up losing confidence. Hopefully most people who automate will prepare for that, but...

Yes, we want to funksling. But skipping auto-funk means that it doesn't mess up the matching of items by skipping the first funk and doing all of the others. Does removing the m_dpr stun portion make it funksling without stunning ever? Would it be better to move the no-stun check into that line for the RAM?
Code:
      if (bob.find() && (queue[count(queue)-1].id != a.id || (item_amount(to_item(to_int(bob.group(1)))) > 1 &&
         (m == $monster[rampaging adding machine] || m_dpr(0,-adj.stun)*meatperhp > to_float(vars["BatMan_profitforstasis"])))))
 
Back
Top