BatBrain -- a central nervous system for consult scripts

1.18 Updates!

Sorry to make two updates so close together, but in addition to fixing Bors' issue I fixed a sneaky little bug that somehow made it into 1.17 unnoticed. All player damage for all actions was being capped on the low end at 1, even if it started off as 0. Unacceptable!

To make the update worth your while, I also improved support for Boris skills. BB now has conservative guesstimates for Mighty Axing (assumes regular hitchance/damage but with no fumble, also includes the bonus stat point) and Cleave (assumes Muscle +20% +20 to-hit, and sextuples the weapon portion of the damage). Additionally, BB now also knows about Song of Fortune granting an auto-crit for your first attack. The other skills were already added previously, including Louder Bellows, so I think Boris skills are fully supported now to the extent they have been spaded.

Enjoy!
 
I'm getting
Record expected (BatBrain.ash, line 217)
when it runs. Any ideas?

EDIT: IGNORE ME, SORRY
 
Last edited:
I keep getting an odd error popping up, don't know what it means. It's not causing everything to completely stop. Usingm BB 1.18 and SS 3.12 and a simple script that just attacks repeatedly once SS is done.
Code:
[7700] Haunted Gallery
Encounter: cubist bull
Strategy: C:\Users\Fluxxdog\Desktop\backup\ccs\default.ccs [default]
Round 0: fluxxdog wins initiative!
ATT: 92 (6% × 5.44, death in 1713)
DEF: 83 (95.45% × 1,048.4, win in 1010000)
HP: 97, Value: 637.07 μ
[COLOR="#FF0000"]Expression syntax error for 'modifier_eval()': expected end, found prismatic
Expression syntax error for 'modifier_eval()': expected end, found prismatic[/COLOR]
Round 1: fluxxdog executes a macro!
Round 1: fluxxdog casts MIGHTY AXING!
Round 2: cubist bull takes 1052 damage.
Round 2: fluxxdog wins the fight!
You gain 279 Meat
You gain 20 Beefiness
You gain 4 Wizardliness
You gain 7 Roguishness

> ashtest current_gear() [COLOR="#0000FF"]<==Simply shows what's equipped in current slots[/COLOR]

Returned:     aggregate item [slot]
acc1 => ring of conflict
acc2 => Space Trip     safety headphones
acc3 => bone spurs
hat => Uncle Hobo's stocking     cap
off-hand => none
pants => buoybottoms
shirt => none
weapon     => Trusty
Anything more you need from me? I'm not sure if this is supposed to be fixed yet or not from reading old posts.
 
Only stuff in my batfactors.txt with prismatic is the d8 and d12... looks like normalize_dmgtype should turn "prismatic" back into "hot,cold,spooky,sleaze,stench" in the "foreach ty,in,rec in factors" immediately following...
 
A search in batbrain for "prismatic" shows "case "prismatic": return "hot,cold,spooky,sleaze,stench";" so it appears it is already doing that. The question is then, why isn't that working...
 
I had that too, already fixed locally. It will be fixed in the next update, but if it really bothers you and you want to fix it before then, you need to move the command that normalizes damage types above the "skill" check. So, around line 465 or so, you should have this:

PHP:
   foreach kw in $strings[prismatic,pasta,sauce,perfect] if (factors[ty,in].dmg.contains_text(kw))
      factors[ty,in].dmg = factors[ty,in].dmg.replace_string(kw,normalize_dmgtype(kw));
   if (ty == "skill") {
 
Double post AGGGHH

Attention BatBrain scripters! As promised, I'm revamping enqueue() and macro() to allow for reduction of the queue to a string with the new get_macro(), and would like some input on two points to reduce the shock to your systems when this is released and allow for a smooth transition:

  1. Are you using the three-parameter form of enqueue (advevent, pre, post)? If so, how?
  2. Do you ever enqueue an action with a repeat condition and then enqueue more actions afterwards?


I ask because my present revamp eliminates both of those possibilities, so if you're doing either of those in your script, you'll either need to make a good defense for those forms to persist, or find out how to use the new method to accomplish the same end.

Some explanation follows so you can decide whether to quietly acquiesce or vehemently defend.

Removal of pre and post. From an organization standpoint, I want the queue of events to be separate from the macro that results from the queue, with a single function get_macro() to convert the queue of actions into a macro. That means eliminating macro information from the queue itself and instead adding it during get_macro(). Thus, the removal of forms of enqueue() which allow scripters to include macro information, such as pre/post and repeat conditions. Pre/post in particular is dangerous as it grants scripters the ability to easily thwart BB's predictions.

Removal of repeat conditions from enqueue(). Speaking of thwarting BB's predictions, BB's predictive queueing is almost entirely useless the moment you enqueue an action with repeat conditions. Therefore, enqueue() will no longer be able to accept repeat conditions. As soon as you have repeat conditions, further actions are numerically meaningless since they occur at an unknown point in the combat and should therefore not be added. If you intend to repeat an action using the BALLS "repeat" command rather than simply enqueueing the action again, the queue should either be stored or performed at that point. To this end, only macro() will continue to accept repeat conditions; enqueue() will not.

Okay, any defenders? Chime in now to defend or else you'll be chiming in later to complain!

You'd need a very good argument to change my mind about 2, but I could be swayed on 1, depending on how you are using it.
 
Attention BatBrain scripters! As promised, I'm revamping enqueue() and macro() to allow for reduction of the queue to a string with the new get_macro()

Ooooo! Smexy! I've been waiting eagerly for that. Is reset_queue() completely functional now so that all prediction and potential happenings are removed? I wish I was in a good place to rewrite DAM for it, but in a few months... probably then.

would like some input on two points to reduce the shock to your systems when this is released and allow for a smooth transition:

1. Are you using the three-parameter form of enqueue (advevent, pre, post)? If so, how?

I actually have a very clear example of using this. It will seem a little bit odd when you look at it, but I couldn't find another way of neatly looping a sequence of two actions.

Code:
string splashSauce() {
	vprint("Destroy will attempt to use Saucesplashing",3);
	if(m_regular() > 15 && enqueue(get_action($skill[entangling noodles])))
		vprint("Destroy with: Entangling Noodles",3);
	if(enqueue(get_action($skill[Wave of Sauce]), "sub sauceloop", ""))
		vprint("Destroy with: Wave of Sauce",3);
	if(enqueue(get_action($skill[Saucegeyser]), "", "endsub"))
		vprint("Destroy with: Saucegeyser",3);
	return macro("", "call sauceloop; repeat");
}



2. Do you ever enqueue an action with a repeat condition and then enqueue more actions afterwards?

Removal of repeat conditions from enqueue(). Speaking of thwarting BB's predictions, BB's predictive queueing is almost entirely useless the moment you enqueue an action with repeat conditions. Therefore, enqueue() will no longer be able to accept repeat conditions. As soon as you have repeat conditions, further actions are numerically meaningless since they occur at an unknown point in the combat and should therefore not be added. If you intend to repeat an action using the BALLS "repeat" command rather than simply enqueueing the action again, the queue should either be stored or performed at that point. To this end, only macro() will continue to accept repeat conditions; enqueue() will not.

I don't use any enqueuing AFTER a repeat condition, but I do use conditional repeats. Is that going to be a problem?

Code:
enqueue(s, "!times "+min(maxround - safetyMargin - round, die_rounds() - 1));

In that example I expect to kill the monster with action s. The great thing about that is that I limit the number of times an action can repeat so that if it goes over that number of rounds I know that something went wrong and I can return to the script and review the situation or else turn things over the user to handle it manually.
 
Last edited:
I do have a use for the "pre"-command, namely to build my own subs for MP-regenration in case my MP is too low for what WHAM decides it is best to do and also to try and add HP-restoration to the execution. It is currently not implemented correctly but that is what the script tries to use it for.

For repeat I've only used that for "attack until monster is dead" (for example enqueue(get_action($skill[Drunken Baby Style]), "");) and so would probably not have a big problem rewriting to use macro() in that case instead of enqueue.
 
Great! Two scripters chiming in right off. Thanks guys!

I wish I was in a good place to rewrite DAM for it, but in a few months... probably then.

I noticed with some wonder that you haven't been posting in my threads with your usual regularity. Hope all is well, or on the way to well!

I couldn't find another way of neatly looping a sequence of two commands

Why not this?

PHP:
string splashSauce() {
	vprint("Destroy will attempt to use Saucesplashing",3);
	if(m_regular() > 15 && enqueue(get_action($skill[entangling noodles])))
		vprint("Destroy with: Entangling Noodles",3);
	while (enqueue($skill[Wave of Sauce]) && enqueue($skill[Saucegeyser])) {}
	return macro();
}

Note that I also removed get_action(). You can't do this yet, but the update will have versions of enqueue() and macro() that accept skills and items.

I don't use any enqueuing AFTER a repeat condition, but I do use conditional repeats. Is that going to be a problem?

Nope -- macro(advevent, string) can still be called to perform repeat conditions on the last action. Additionally, get_macro() can also accept a repeat conditions string, so if you are reducing various queues to strings that information will not be lost.

In your second example, since you expect to kill the monster at that point it may as well be a call to macro() rather than enqueue(), right?

I do have a use for the "pre"-command, namely to build my own subs for MP-regenration in case my MP is too low for what WHAM decides it is best to do and also to try and add HP-restoration to the execution. It is currently not implemented correctly but that is what the script tries to use it for.

Without code to judge by, I'm going to suggest that is something you could better implement by sorting opts a la stasis_action() and attack_action(). I think mp_action(int target) and hp_action(int target) would be great functions to have, perhaps even in BatBrain. As a starting point, this will choose an action that costs less than 500 meat and restores you up to your target MP, if such an action exists:

PHP:
advevent mp_action(int target) {
   if (my_stat("mp") >= target) return new advevent;
   sort opts by -to_profit(value);
   foreach i,opt in opts {
      if (opt.mp <= 0) continue;
      if (opt.mp + my_stat("mp") >= target && to_profit(opt) > -500) return opt;
   }
   return new advevent;
}

Okay. Unless you're not satisfied with my answers, I'm calling this "no serious objections."

As you can see, as BB evolves the idea is to get further away from BALLS and more towards ASH. If saving server hits is important, why not saving server processing cycles as well?

You guys write DAM and WHAM. Is Theraze still sharing and supporting spamattack? Perhaps it has a better name by now, perhaps SHAZAM? Either way, she has certainly been making use of BB, so I'll wait for her and if she also has no objections, it'll be full steam ahead. I'll do another "in-thread beta" to give you time to prepare your updates again.
 
As for the first, I admit I would prefer to have a little loop as opposed to a long repeated sequence of the same two actions. I just prefer submitting a shorter string, but yeah it would work and I guess it is okay. I could actually argue that your method is superior since it allows me to properly use BatBrain's full predictive power to measure the outcome.

There is a simple way to view changes to HP and MP at the end of all enqueued actions, right?

For the second... actually that's a little bit more troublesome, but I could rewrite my program to work differently. As it is, I queue up sequences of actions and then use macro() to execute them all at the end. It would take a bit of rewriting to make it work, but the script will be so seriously in need of rewriting anyway (to take advantage of BatBrain's increased powers) that I'm not too angstful about it.

I can work with this.


I noticed with some wonder that you haven't been posting in my threads with your usual regularity. Hope all is well, or on the way to well!
Thanks for your concern. Be reassured that nothing is wrong for me; I am happy and healthy. I'm simply differently occupied.

Lately I've been thinking about scrapping my recovery script. And rewriting it from scratch. Ugh. That'll eat up a lot of my time also. Unfortunately I'm growing ever more dissatisfied with it. It was my first serious ash scripting project and that really shows. Unfortunately it is so darn complicated that I know it will be a nightmare to fix. I've got some ideas that will greatly simplify functionality will increasing effectiveness and hopefully that will keep me from losing my mind when I tackle that project.
 
I haven't looked at BatBrain in a while, I'm looking forward to picking at the new code.

Is Theraze still sharing and supporting spamattack? Perhaps it has a better name by now, perhaps SHAZAM? Either way, she has certainly been making use of BB
If I'm not mistaken, Theraze is a he.
 
I've never been clear on that, so I've taken to alternating until he corrects me on one of them. :)

There is a simple way to view changes to HP and MP at the end of all enqueued actions, right?

Well, you can always check my_stat("hp|mp") for a post-queue assessment of your HP/MP. You can also check the global adj event, which contains all current adjustments. For example, if you enqueue one action that costs 5 MP, and no other factors alter your MP, adj.mp will contain -5.

Glad you can work with it, and glad you're okay.

I've got some ideas that will greatly simplify functionality will increasing effectiveness and hopefully that will keep me from losing my mind when I tackle that project.

May I suggest a sortable map of records containing recovery actions, perhaps called opts? Maybe then you could queue them up to determine the optimum order in which to perform them. ;)
 
Is Theraze still sharing and supporting spamattack? Perhaps it has a better name by now, perhaps SHAZAM? Either way, she has certainly been making use of BB, so I'll wait for her and if she also has no objections, it'll be full steam ahead. I'll do another "in-thread beta" to give you time to prepare your updates again.

DAM was just so much more awesome than spamattack that I haven't changed my personal copy of SA since August 25th. I have no objections. :)

I've never been clear on that, so I've taken to alternating until he corrects me on one of them. :)

Male. :) The character gender varies on various games, but the forum doesn't have a spot for gender, so the avatar gets to cause confusion. I did change the displayed one to the male avatar a while ago, so that should make it a bit less odd. ;) Only get confused again when I go for the "Under the knife" trophy.
 
Haha, thanks, I consider myself corrected! (Although you missed out on a chance to be mysteriously genderless like Vaarsuvius in Order of the Stick) Retrospective apologies for occasionally referring to you as lacking the very Y chromosome which you do indeed possess.

And all systems go with the revamp then! Expect an in-thread beta here late tomorrow (GMT-9, mind you).
 
Eh, it's the internet. There's always to possibility that my forum account is, in and of itself, another character. I mean, to do well in RP muds and so on basically takes the ability to disassociate yourself from reality in a major way.

But hey, looking forwards to new BB soon. :D
 
May I suggest a sortable map of records containing recovery actions, perhaps called opts? Maybe then you could queue them up to determine the optimum order in which to perform them. ;)

You could suggest that, but it would be a little bit late since I've already decided to steal the idea from BatBrain. It's the details that make it tricky since some things can be expended for keeps while others have a simple meat value and a third category can be used X times every day.
 
Okay, I've got it sorted on my end, and it seems to be working fine. Didn't need to make as many edits as I'd supposed. Here are the declarations for new/altered functions:

boolean enqueue( advevent | skill | item )
Adds the specified event to the queue and adjusts the internal combat environment accordingly. Returns false if the event was not added (blank event, not enough MP, over round limit). This function no longer accepts any macro information, including repeat conditions. Enqueueing an action therefore will no longer "corrupt" the action id.

string get_macro( [ string rep ] )
Returns the queue in BatBrain-enhanced macro form, including various auto-responses: poison removal, learning Rave skills, acquiring molybdenum tools and elemental discs, and using your major yellow ray on specified monsters. Accepts an optional string specifying repeat conditions for the final action. It is impossible to add repeat conditions for actions mid-queue; however, repeat conditions will be added automatically for pickpocketing (will pickpocket twice where possible) and running away (if running away was the last action in the queue, it will be automatically repeated with no conditions).

macro()
As before. Executes the current queue as a macro and resets the queue and all queued happenings.

macro( advevent | skill | item [, string rep ])
Identical to calling enqueue(action) followed by macro(), except that in this form you have the option of specifying repeat conditions for the action you are enqueueing.

Bonus function which you may have missed earlier:

boolean finished()
Returns true if the combat is done (actually done, not predictively done)


You will note that both enqueue() and macro() are now a little more flexible in terms of what parameters they accept, so they can save you some steps.

While I was at it, I tweaked item_val() to solve or at least reduce the NPZR toast issue, and added the skill/item blocking/conversion for O.A.F.s and Black Cats, which has been listed as TODO for a long time, and recently became relevant to me as I have begun a masochistic TT Kittycore run.

Below is the in-thread beta to allow DAM/WHAM/BAM/THANKYOUMAAM authors time to make any adjustments necessary to their scripts. We'll go with a week again, unless Bale and Winterbay both chime in earlier than that to say they're ready to go.

EDIT: attachments removed.
 
Last edited:
So, instead of checking "if(round > maxround)" we can now do "if(finished())"? That sounds like a brilliant idea :)
Downloading and verifying script as we speak...

Edit: Is there any way of adding things to batround without hacking batbrain? I realised that I do have two things in my WHAM_round-function that is being used: Aborting if I acquire Temporary Amnesia (during an execution of spells/skills) and to allow for a custom stopping point (to avoid the battle drawing on for too long potentially making you want to finish it off yourself).

Edit, edit: Bah, you just forgot to add "string" to your macro-list up there didn't you... :)
 
Last edited:
Yeah, I thought spelling it out as finished() would be a lot more intuitive for scripters, who wouldn't otherwise immediately grasp why round > maxround works.

Your Amnesia-abort definitely sounds like something that should be in BatBrain! Would you mind posting your code so I can steal the useful bits i.e. not do all the work myself?

As for the second issue, how about BatBrain including a global string variable "batround_insert", empty by default, which a calling script can edit to insert extra responses into batround? I like both the ease and flexibility of that.

I noticed a facepalm-ish problem with my Black Cat solution -- merging a reduced action with a reduced regular attack changes the action id to "<whatever>; attack". Oops.

I think I should fix all three of those before considering this update releasable.
 
Back
Top