BatBrain -- a central nervous system for consult scripts

Winterbay

Active member
Seeing as those values are a heck of a lot better than no values I've just updated the official batfactors with them (as well as the new chefstaffs).
 

Crowther

Active member
Seeing as those values are a heck of a lot better than no values I've just updated the official batfactors with them (as well as the new chefstaffs).
Yeah, it's getting close and it's better than nothing, but I keep finding trouble. *sigh*

The weak elements bonus isn't right for capped spells. I'm fighting Oil Barons who have 144 HP and are sleaze aligned. WHAM is choosing freeze "spelldmgpercent*min({10,12.5,15}+0.4*buffedmys+spelldmg+elembonus,mpcost*10) cold" for a one-hit, because even though it's capped at 50 damage (mpcost*10), my 100% spell damage bonus brings it to 100 damage, then BatBrain doubles the damage to 200 because cold beats sleaze. The problem is, Jick's new cap is applied after the elemental weakness bonus and before the spell damage percent bonus, so the spell only does 100 damage. BatBrain currently doesn't support that ordering.
 

Winterbay

Active member
Seeing as Jarlsberg's skill seem to work differently I'd hazard a guess for those only. That said, I think that Oil Barons have a innate damage absorption as well (both for normal damage and spells) couldn't that also be part of the reason?
 

Crowther

Active member
Seeing as Jarlsberg's skill seem to work differently I'd hazard a guess for those only. That said, I think that Oil Barons have a innate damage absorption as well (both for normal damage and spells) couldn't that also be part of the reason?
I forgot about that. Yeah, too bad I commented on it in the main forums already. Ugh.

I've done some more spading. Curdle does scale. I'll do the math soon. I found bake's RNG range and it seems if chop, etc have a myst cap, it's lower than the default mpcost cap. I guess I'll have to try increasing MP cost of those just to be sure there's no myst cap.

EDIT:
Okay, almost done here! I figured out Curdle. It caps really fast at .5*myst. I couldn't find any myst cap for chop, etc. I ran +6 MP cost and 219 buff myst. The MP cost cap would hit at 265 myst, so there might still be another cap, but I can't see why anyone would care.

So, unless anyone can find a counter example or I find one myself, I'm going to say, the following is close enough:

Code:
skill   14000   Curdle  spelldmgpercent*min(4+0.5*buffedmys+spelldmg+elembonus,15) stench       0       0
skill   14003   Boil    spelldmgpercent*min({10,12.5,15}+0.4*buffedmys+spelldmg+elembonus,mpcost*10) hot        0       0
skill   14004   Fry     spelldmgpercent*min({40,45,50}+min(0.3*buffedmys,50)+spelldmg+elembonus,mpcost*10) sleaze       0       0
skill   14014   Chop    spelldmgpercent*min({10,12.5,15}+0.4*buffedmys+spelldmg+elembonus,mpcost*10)    0       0
skill   14013   Slice   spelldmgpercent*min({40,45,50}+min(0.3*buffedmys,50)+spelldmg+elembonus,mpcost*10)      0       att -9
skill   14023   Bake    spelldmgpercent*{4,4.5,5} hot   0       0
skill   14024   Grill   spelldmgpercent*min({40,45,50}+min(0.3*buffedmys,50)+spelldmg+elembonus,mpcost*10)*2 hot,spooky 0       0
skill   14033   Freeze  spelldmgpercent*min({10,12.5,15}+0.4*buffedmys+spelldmg+elembonus,mpcost*10) cold       0       0
skill   14034   Blend   0       0       stun 3
I'm sure somethings wrong. I always am. Oh, right. Somethings wrong with Grill. I've no idea where to start figuring that one out. Also, I haven't looked to see how long blend really lasts. *shrug*

EDIT: Okay, I'm officially burned out on spading Jarlsberg spell damage. It looks like Greycat is working on it on the wiki and he believes that I got slice wrong. He's probably right. I probably never would have started spading this if I'd known that Jick had messed with the formulas. Anyway, it was fun for a while, now it's frustrating and I know to stop when I have to remind myself it's just a game.
 
Last edited:

Winterbay

Active member
It would appear that Groar has a ~50% resistance to at least spells (based on Boil doing 86 damage instead of the 220 it does on other cold aligned monsters). Can anyone else confirm having seen this?
 

Theraze

Active member
Slice also does about 40% of expected, since I see 86 or so instead of the 210 it predicts. Not sure what causes a 60% resistance, but... hey, boss?
 

fxer

Member
From my post over here it looks like you can't mix CCS and a combat filter very well, should I be using BatBrain to accomplish my original goal, which was to handle buffing and banishing a monster with the Nanorhino?

Can BatBrain be scripted to handle using a combat skill to get the Nanorhino buff, and using the Unleash Nanites skill to banish a monster all while submitting the entire combat as a macro?

side question: is there a guide or simple batbrain script to use as a reference for what BatBrain can do?
 

Winterbay

Active member
For 1: Yes it can.
"Simple" version:
Code:
if(have_effect($effect[<nanorhino buff>] == 0) && get_action("skill <number>").id != "") enqueue(get_action("skill <number>"));
if(get_action("skill " + to_int($skill[Unleash Nanites])).id != "") enqueue(get_action("skill " + to_int($skill[Unleash Nanites])));
macro();

For 2: It'd be great, but at the moment there isn't one. Your best bet is to look at WHAM and BatMan_relay and try to figure out what is going on (or ask specific questions I guess).
 

fxer

Member
Frigging beautiful, thanks as always Winterbay, I'll work on that tonight and certainly come up with more questions :p
 

fxer

Member
Having a bit of trouble, can't seem to get enqueue() to actually queue anything?

Consult script:
PHP:
void main(int initround, monster foe, string pg) {
	act(pg); // now you can smack down the monster with BatBrain-powered gusto!

	if( have_effect($effect[nanobrawny]) > 0 ){
		print("Have Buff");
		enqueue( $skill[Unleash Nanites] );
	} 

	print("Enqueued: " + count(queue));
	macro();
}

CCS:
PHP:
[ default ]
consult customconsult.ash
consult SmartStasis.ash

Output
Code:
[154348] Giant's Castle (Top Floor)
Encounter: Raver Giant
Round 0: fxer wins initiative!
Have Buff
Enqueued: 0
Round 1: fxer executes a macro!
Round 1: fxer tries to steal an item!
Round 2: fxer executes a macro!
Round 2: fxer uses the fat stacks of cash!
..
 

zarqon

Well-known member
The trouble here is that enqueue(skill) and enqueue(item) only work for actions which are included in batfactors, since both of those functions use get_action() to find the action in opts. Since Release Nanites is not in batfactors, you need to use to_event() to construct your Nanites action first, before enqueueing it:

enqueue(to_event("skill 7137","",1));

If you know exactly what the action will do when you perform it, you could expand the to_event() function for greater predictive accuracy. Check out the build_custom() function in SS for examples.

However, isn't this easily macroable? "if haseffect 1129; skill 7137; endif;"

If you always want to perform this first before even considering other actions (which is what your current script will do since it's a separate script from SS), you can skip enqueueing altogether and call macro() directly:

PHP:
void main(int initround, monster foe, string pg) { 
    if( have_effect($effect[nanobrawny]) > 0 ) macro("skill 7137"); // short script, and faster since it doesn't even build your combat environment!
}

It usually saves a server hit over the CCS version too, because you're checking in the script rather than the macro.

The best option would be to import SS rather than BatBrain, and copy its main() into your script's main(), with one small change: right after it calls build_custom(), check for Nanobrawny and add another custom action. Releasing Nanites would then be part of SS's custom actions macro, and you would only need to consult one script.
 

fxer

Member
Thanks again zarqon, I took your advice and imported SS and copied its main() into my script, a snippet now looks like:

PHP:
void main(int initround, monster foe, string pg) {
	act(pg);
	vprint_html("Profit per round: "+to_html(baseround()),5);
	// custom actions
	build_custom();

	// Attempt to get Nanobrawny buff from nanorhino
	if( my_fam() == $familiar[nanorhino] && have_effect( $effect[nanobrawny] ) == 0 && get_action( muscleCombatSkill ).id != ""){
		// Track the number of nanorhino uses today
		set_property("_nanorhinoUses", get_property("_nanorhinoUses").to_int() + 1);
		custom[count(custom)] = to_event("skill " + muscleCombatSkill.to_int(),"",1);
	}
	// Attempt to unleash the nanites if it will banish a monster
	if( have_effect($effect[nanobrawny]) >= 40 && banish_monster() == foe){
		custom[count(custom)] = to_event("skill " + $skill[Unleash Nanites].to_int(),"",1);
	}

1) Is that what you had in mind as the best option?

2) Injecting the Nanorhino stuff at this stage of the script allows Entangling Noodles to be cast first, which causes the rhino to buff with Nanobrainy then I can't get Nanobrawny by using Toss when it gets to my custom actions. Should I put my code BEFORE build_custom()? I think that means I wouldn't have a chance at pickpocketing the monster and generally toying with him before I banish, but at least it's only one adv per day as he'll never show up again.

EDIT: Looks like putting my code before build_custom() doesn't work, as it still attempts to cast entangling noodles before using the muscle combat skill. Maybe your suggestion of calling macro() directly, before build_custom(), is what I need to do, becoming:

PHP:
void main(int initround, monster foe, string pg) {
	act(pg);
	vprint_html("Profit per round: "+to_html(baseround()),5);
   
	// Attempt to get Nanobrawny buff from nanorhino
	if( my_fam() == $familiar[nanorhino] && $familiar[nanorhino].image == "nanorhinoc.gif"){
		// Track the number of nanorhino uses today
		set_property("_nanorhinoUses", get_property("_nanorhinoUses").to_int() + 1);
		//custom[count(custom)] = to_event("skill " + get_combat_skill("muscle").to_int(),"",1);
		macro("skill " + get_combat_skill("muscle").to_int());
	}
	// Attempt to unleash the nanites if it will banish a monster
	if( have_effect($effect[nanobrawny]) >= 40 && banish_monster() == foe){
		//custom[count(custom)] = to_event("skill " + $skill[Unleash Nanites].to_int(),"",1);
		macro("skill " + $skill[Unleash Nanites].to_int());
	}
	
	// custom actions
	build_custom();

I only really get 1 attempt per day to try this code so we'll find out tomorrow :p

Edit: It worked! Still has the issue above where I can't pickpocket or whatever first to try and boost my profits ever so very slightly but so what. Thanks for the help zarqon, let me know if you still see a better way for me to write this!
 
Last edited:

Crowther

Active member
I've finished with Jarlsberg and sold my pan. I believe the caps I put in some of those spells are wrong. Just the caps that apply to the mysticality bonus. Not a huge problem, since it just wastes a little of Jarlsberg's near infinite MP. Good luck!
 

fxer

Member
I'm curious about the setting: setvar("BatMan_baseSubstatValue",5.0);

if I set that to 0 will BB stop firing bottle rockets with the BRC equipped? Just kind of burns mana when I don't need the substat points, will that have other repercussions I wouldn't like?
 

zarqon

Well-known member
Probably yes. Setting it to 0 will make BatBrain consider all stat gain worthless, including stat gain from killing monsters. You realize that you need to set that by calling ZLib in the CLI though right, and not in the script? setvar() simply specifies the default value to store in your settings file, so once the script has run once (thus populating your settings file with the default value) editing the script itself will not change anything.

ETA: Marking actions as combat-enders is on my to-do list for the next release. Once that gets done, BatBrain will sort any combat-enders to the end of the custom actions queue before performing it. It will also avoid using unnecessary stuns beforehand.
 
Last edited:

zarqon

Well-known member
I'm starting to get very excited about the next BatBrain/SS/BatMan RE release. It fixes a number of bugs, introduces or expands support for some things, and adds some very cool functionality, most notably an action blacklist, which is user-tweakable via BatMan RE and gets prepopulated with things BatBrain already knows you don't want to use, like possible tower items and "attack" when you're an AoJ. Want BatBrain to completely forget a certain action exists? Simply blacklist it! Want to always hold 5 double-ice shards in reserve? Blacklist just 5 of them. Want to cast Shieldbutt no more than twice per combat? Blacklist it and set it to 2. Getting excited yet?

There's one more thing I want to add before this release, and that's soft damage caps. Groar beat me up this run because BatBrain overestimated Boil's damage to him, and I realized it wouldn't be mindstumpingly hard to properly account for those caps. So I'm compiling a list of monsters with said caps; so far I have the following monsters on the list:

  • Groar
  • Naughty Sorceress (forms 1 and 2)
  • all the final Nemesis bosses
  • all the Hobopolis bosses
  • Gang of hobo muggers
  • Mother Slime
  • Mer-kin raider
  • Trophyfish
That's probably all the important ones, but see any I'm missing? I'd like to get them all in one swell foop.
 

zarqon

Well-known member
Any idea what the cap is for the BRICKO airship, Magus? It's not on the Wiki.

After several hours of Wiki scouring tonight, BatBrain has wised up about a wide variety of monsters. Once I add the soft caps, BatBrain's knowledge of monsters will amaze Manuel himself. Here's what I've scrounged up for soft caps (pardon my shorthand):

PHP:
  // soft damage caps
   switch (m) {
      case $monster[demon of new wave]:
      case $monster[gorgolok, the demonic hellseal]:
      case $monster[lumpy, the demonic sauceblob]:
      case $monster[somerset lopez, demon mariachi]:
      case $monster[spaghetti demon]: 75 + (X-75)^0.65
      case $monster[stella, the demonic turtle poacher]: 50 + (X-50)^0.65

      case $monster[gorgolok, the infernal seal (volcanic cave)]:
      case $monster[lumpy, the sinister sauceblob (volcanic cave)]:
      case $monster[somerset lopez, dread mariachi (volcanic cave)]:
      case $monster[spaghetti elemental (volcanic cave)]:
      case $monster[spirit of new wave (volcanic cave)]:
      case $monster[stella, the turtle poacher (volcanic cave)]: 100 + (X-100)^0.85

      case $monster[chester]:
      case $monster[zombo]: 500+floor((x-500)^0.65)
      case $monster[ol scratch]: 500+floor((x-500)^0.7)
      case $monster[oscus]: 500+floor((x-500)^.75)
      case $monster[frosty]: 3 damage from hot/spooky
      case $monster[hodgman, the hoboverlord]: 500+floor((ceiling(0.75*x)-500)^0.85)    // if frosty is undefeated: 300+floor((ceiling(0.05*x)-300)^0.75)

      case $monster[BRICKO cathedral]: 
      case $monster[gargantuchicken]: 1000+floor((x-1000)^0.2)
      case $monster[groar]: 50+(X-50)^0.7
      case $monster[brushfire]: 5000 + (X-5000)^0.7
      case $monster[gang of hobo muggers]: 500+floor((x-500)^0.7)
      case $monster[mer-kin raider]: 400+floor((x-400)^0.75)
      case $monster[mother slime]: 200+floor((x-200)^0.7)
      case $monster[trophyfish]: 500+floor((x-500)^0.80)
   }

Other than BRICKO airships, see anything missing?

All this scouring has me plumb tuckered out. Goodnight, Loathers.
 
Last edited:

Magus_Prime

Well-known member
I'm afraid not. I know that it exists and the discussion page on the Wiki theorizes about it but it doesn't seem to have been fully spaded yet.
 
Top