Difference between pages "Help talk:Frequently Asked Questions" and "BatBrain"

From Kolmafia
(Difference between pages)
Jump to navigation Jump to search
imported>Heeheehee
m
 
imported>Zarqon
 
Line 1: Line 1:
==Setting up symlinks for Dropbox on non-Windows systems==
+
{{TOCright}}{{DISPLAYTITLE:BatBrain (BatBrain.ash)}}
Open the command-line interface for your OSFor linux, type in:<br>
+
== About BatBrain ==
ln -s ~/.kolmafia /path/to/dropbox/folder/KoLmafia
+
BatBrain is a function library intended to greatly simplify writing a [[Custom_Combat_Script#Consult_Scripts|consult script]]A general introduction, changelog, download, and forum discussion can be found in the [http://kolmafia.us/showthread.php?6445 BatBrain thread], but this page is the best place for scripters interested in writing a consult script with BatBrain to start.  NOTE: BatBrain is not built into KoLmafia, it is a separate ASH script which you must download and import to make these functions available.
  
For a Mac, type in:<br>
+
== What It Does ==
ln -s /Library/Application\ Support/KoLmafia /path/to/dropbox/folder/KoLmafia
 
  
==Setting up symlinks for Dropbox on a Mac==
+
yadda yadda
If you're using a Mac, and the section above made no sense, here are step-by-step instructions that will get you there.
 
*Open Terminal.app.  This is in /Applications/Utilities, or you can just use Spotlight to find it.
 
*Open Finder, and navigate to the folder containing your Dropbox folder.
 
*In Terminal, type "cd ", then drag the Dropbox folder onto the Terminal window, then press Enter.
 
**Leave the quotes out for all of these commands and make sure to include the trailing space.  Copy-pasting the commands is advised.
 
*In Terminal, type "ln -s /Library/Application\ Support/KoLmafia KoLmafia", then press enter.
 
*You now have a symbolic link, and Dropbox will back up your mafia settings files.
 
  
 +
== Spreads ==
  
 +
BatBrain handles all damage done (both to you and to the monster) as spreads.  In fact, it defines a data type called "spread":
  
My suggestion; we just create a "Dropbox" page here on the wiki, link to that from the FAQ, add the external link to the text above, and call it a day. Any other input? --[[User:StDoodle|StDoodle (#1059825)]] 02:30, 19 June 2010 (UTC)--[[Special:Contributions/75.48.127.248|75.48.127.248]] 02:29, 19 June 2010 (UTC)
+
<syntaxhighlight>
:That seems like a better solution than what we have right now -- I kinda added (rather sloppily) the question on a whim, and it looks like everyone else has just been building off of that foundation. --[[User:Heeheehee|Heeheehee]] 03:59, 19 June 2010 (UTC)
+
typedef float[element] spread;
 +
</syntaxhighlight>
 +
 
 +
This means that all damage is a map of floats keyed by element, with positive values for damage and negative values for healing.  We could have just used float[element] everywhere, but it strikes us as cleaner to use the single word "spread".  You'll see this datatype occur fairly frequently if you peruse BatBrain and if you're writing a combat script, you may have to deal with one.  Fortunately, there are some functions for dealing with spreads:
 +
 
 +
{{HideLink|to_spread}}{{Function|
 +
name=to_spread|
 +
return_type=spread|
 +
parameter1={{Param|string|dmg}}|
 +
}}
 +
{{Function|
 +
name=to_spread|
 +
return_type=spread|
 +
parameter1={{Param|string|dmg}}|
 +
parameter2={{Param|float|factor}}|
 +
p1desc={{pspan|dmg}} is the damage string, in the same format used by batfactors.|
 +
p2desc={{pspan|factor}} is optional; supply this if you want to factor the supplied damage by an amount other than 1.0|
 +
}}
 +
This function creates a spread from a string.  For example, an attack which deals 10 hot damage would deal to_spread("10 hot") damage.  The format for {{pspan|dmg}} is flexible and described in greater detail on the [[batfactors]] page.  An optional {{pspan|factor}} parameter is available as shorthand for factor(to_spread()).
 +
 
 +
{{HideLink|merge}}{{Function|
 +
name=merge|
 +
return_type=spread|
 +
parameter1={{Param|spread|first}}|
 +
parameter2={{Param|spread|second}}|
 +
p1desc={{pspan|first}} is the first spread to merge|
 +
p2desc={{pspan|second}} is the second spread|
 +
}}
 +
Basic arithmetic, a + b.  It returns a spread combining the damage in first and second.
 +
 
 +
{{HideLink|factor}}{{Function|
 +
name=factor|
 +
return_type=spread|
 +
parameter1={{Param|spread|f}}|
 +
parameter2={{Param|float|fact}}|
 +
p1desc={{pspan|f}} is the spread to factor|
 +
p2desc={{pspan|fact}} is the factor|
 +
}}
 +
More basic arithmetic, this time multiplication.  This function returns spread f factored by fact.
 +
 
 +
{{HideLink|to_html}}{{Function|
 +
name=to_html|
 +
return_type=string|
 +
parameter1={{Param|spread|src}}|
 +
p1desc={{pspan|src}} is the spread to convert to HTML|
 +
}}
 +
This function returns an HTML string showing a spread the way KoL does, with elemental damage parenthesized and appropriately color-coded.
 +
 
 +
{{HideLink|dmg_dealt}}{{Function|
 +
name=dmg_dealt|
 +
return_type=float|
 +
parameter1={{Param|spread|action}}|
 +
p1desc={{pspan|action}} is the damage spread for a given source of monster damage|
 +
}}
 +
This function returns the actual damage a given spread would deal to your current opponent, accounting for the monster's resistances, vulnerabilities, and damage cap where applicable.  For example, when fighting Groar, any cold damage present in {{pspan|action}} would be reduced to 1, and any damage of his vulnerable elements would be doubled.  Secondly, any damage over Groar's soft damage cap would be reduced appropriately, and finally the damage would be summed together into a single float and returned.
 +
 
 +
{{HideLink|dmg_taken}}{{Function|
 +
name=dmg_taken|
 +
return_type=float|
 +
parameter1={{Param|spread|pain}}|
 +
p1desc={{pspan|pain}} is the damage spread for a given source of player damage|
 +
}}
 +
This function returns the actual damage a given spread would deal to the player, accounting for the player's elemental resistances and vulnerabilities.
 +
 
 +
== Advevents ==
 +
 
 +
Now that we've discussed spreads, we can really get down to it. Absolutely everything that happens, every single "adventure event" that takes place, is treated as an advevent.  Your familiar performs an advevent every round, the monster performs an advevent, each action you have available is an advevent, and sometimes even your current gear or running effects contribute an advevent or two.  Your current combat environment could be described with an advevent, and in fact any adjustments made to your current environment when enqueueing actions are tracked in an advevent.  Get the picture? Advevents make BatBrain's world turn.  And here's what they look like:
 +
 
 +
<syntaxhighlight>
 +
record advevent {          // record of changes due to an event
 +
  string id;              // macro-ready name -- attack/jiggle/skill s/use i
 +
  spread dmg;            // raw dmg dealt to the monster, before resists/vulns
 +
  spread pdmg;            // raw dmg taken by the player, before resists/vulns
 +
  float att;              // monster attack adjustment
 +
  float def;              // monster defense adjustment
 +
  float stun;            // stun chance (expressed as average rounds stunned)
 +
  float mp;              // mp gained/lost
 +
  float meat;            // meat gained/lost
 +
  float profit;          // profit cache to avoid recalculating
 +
  int rounds;            // rounds consumed
 +
  substats stats;        // substats gained/lost
 +
  boolean endscombat;    // whether or not this action ends the combat
 +
  string custom;          // flag for special actions that should not be used in normal automation
 +
  string note;            // user-friendly name or special note
 +
};
 +
</syntaxhighlight>
 +
 
 +
Note that each advevent contains two spreads, one for damage to the monster and one for damage to the player.  The rest is mostly self-explanatory, but a few things require clarification.
 +
 
 +
First, the profit field will contain nothing (0) until to_profit() is called on the advevent in question, at which point the result is cached in this field for further reference, since to_profit() has a fair amount of calculations and is thus much more expensive (in processing terms) than simply checking a.profit.  Keep that in mind if you're calling to_profit() a lot; chances are you could speed up your script by changing a few of those to check the profit cache instead.
 +
 
 +
Second, substats is another datatype defined by BatBrain, and it's simply a float[stat] map.
 +
 
 +
The custom field will be empty for most actions, so scripts ought to be checking a.custom == "" before using an action in regular automation.  For special actions, the custom field will contain the type of custom action (and sometimes additional information).  Some custom types currently being used are: attract, banish, copy, yellow, and runaway.
 +
 
 +
Finally, the note field is not really used by BatBrain, but is used by BatMan RE to display extra information about certain actions (such as notices of estimates due to unspaded numbers, or ongoing damage not predicted by BatBrain, etc).
 +
 
 +
Here are some functions to help you deal with advevents should the need arise:
 +
 
 +
{{HideLink|to_event}}{{Function|
 +
name=to_event|
 +
return_type=advevent|
 +
parameter1={{Param|string|id}}|
 +
parameter2={{Param|spread|dmg}}|
 +
parameter3={{Param|spread|pdmg}}|
 +
parameter4={{Param|string|special}}|
 +
parameter5={{Param|int|howmanyrounds}}|
 +
}}
 +
{{Function|
 +
name=to_event|
 +
return_type=advevent|
 +
parameter1={{Param|string|id}}|
 +
parameter2={{Param|spread|dmg}}|
 +
parameter3={{Param|spread|pdmg}}|
 +
parameter4={{Param|string|special}}|
 +
}}
 +
{{Function|
 +
name=to_event|
 +
return_type=advevent|
 +
parameter1={{Param|string|id}}|
 +
parameter2={{Param|string|special}}|
 +
parameter3={{Param|int|howmanyrounds}}|
 +
}}
 +
{{Function|
 +
name=to_event|
 +
return_type=advevent|
 +
parameter1={{Param|string|id}}|
 +
parameter2={{Param|string|special}}|
 +
p1desc={{pspan|id}} is the ID of the event. BALLS-friendly name (will be used in macros)|
 +
p2desc={{pspan|dmg}} is for damage/healing to the monster.|
 +
p3desc={{pspan|pdmg}} is for damage/healing to the player.|
 +
p4desc={{pspan|special}} is for specifying other qualities of the action, such as deleveling, stunning, meat gained/lost, etc.|
 +
p5desc={{pspan|howmanyrounds}} is optional, default 0. It specifies the number of rounds this action takes.  Will be 0 for all but actual player actions.|
 +
}}
 +
Builds and returns an advevent, used ubiquitously by BatBrain internally but also useful to a scripter for creating custom actions that are not present in opts[]. You may omit both spreads if the event being constructed deals no damage to either monster or player. The format for the special field is generally a comma-delimited list of "keyword value", although some keywords lack values. The format is described in greater detail on the [[batfactors]] page -- quite a few keywords are available.  Note that if you have an elemental form, all damage specified in {{pspan|dmg}} will be converted to that element by this function.
 +
 
 +
{{HideLink|merge}}{{Function|
 +
name=merge|
 +
return_type=advevent|
 +
parameter1={{Param|advevent|first}}|
 +
parameter2={{Param|advevent|second}}|
 +
p1desc={{pspan|first}} is the first advevent to merge|
 +
p2desc={{pspan|second}} is the second advevent|
 +
}}
 +
As with the spread version, this function combines two advevents into a single advevent by individually combining each field.  It isn't always just simple addition, however.  First of all, the id field will be merged using a semicolon and a space, so if you were merging "jiggle" with "attack", the new combined id would be "jiggle; attack".  This allows merging events to retain a BALLS-friendly ID.  Second, if both first and second are single item actions and you have Funkslinging, the events will be merged into a single funkslinging action "use X,Y".  The rounds field likewise will be added together unless it's being auto-funked, in which case 1 + 1 = 1.  Last, the stun field is not simply added together, because if you perform two actions, each with a 50% stun chance, that does not guarantee a 100% stun chance; that's a 75% stun chance, because you have a 50% chance of stunning 50% of the time when the first action fails to stun.  Merging takes this into account.
 +
 
 +
{{HideLink|factor}}{{Function|
 +
name=factor|
 +
return_type=advevent|
 +
parameter1={{Param|advevent|f}}|
 +
parameter2={{Param|float|fact}}|
 +
p1desc={{pspan|f}} is the advevent to factor|
 +
p2desc={{pspan|fact}} is the factor|
 +
}}
 +
This function multiplies an advevent by {{pspan|fact}}, and is much more straightforward than merge().  All numeric fields are simply multiplied, with one exception: the rounds field is not multiplied since that would be undesirable.  BatBrain uses this function internally to apply the hitchance of an event to the event.
 +
 
 +
{{HideLink|to_profit}}{{Function|
 +
name=to_profit|
 +
return_type=float|
 +
parameter1={{Param|advevent|haps}}|
 +
parameter2={{Param|boolean|nodelevel}}|
 +
p1desc={{pspan|haps}} is the advevent to evaluate|
 +
p2desc={{pspan|nodelevel}} is optional, default false. If supplied as true, will ignore profit from deleveling.|
 +
}}
 +
Returns the profit of performing the action {{pspan|haps}} at the current point in the combat.  It looks ahead one round (including the monster's event, your familiar's event, and any equipment and effects) and determines what you gained and lost, and converts all of that to a single number, which it returns.  This is a very useful function for combining with other criteria and sorting opts[].  HP and MP gain/loss are evaluated based on your _meatpermp and _meatperhp properties, which are set by Bale's Universal Recovery Script.  If you are not using this script, basic calculations are made using the price of common restoratives.  HP/MP regeneration is also factored into the profit appropriately.  By default, this function includes profit from deleveling (i.e. reducing the monster's attack by X means it will deal Y less damage, effectively earning you Y HP).  However, this may be undesirable if you intend to stun beforehand, so an optional {{pspan|nodelevel}} flag was included.
 +
 
 +
== Other Useful Functions ==
 +
 
 +
{{HideLink|monster_stat}}{{Function|
 +
name=monster_stat|
 +
return_type=float|
 +
parameter1={{Param|string|which}}|
 +
p1desc={{pspan|which}} can be "att","def". or "hp"|
 +
}}
 +
This function wraps ASH's monster_attack(), monster_defense(), and monster_hp() functions. Please use this function instead of the ASH functions, since the value may differ if you have enqueued actions causing BatBrain to predictively alter the monster's stats.
 +
 
 +
{{HideLink|my_stat}}{{Function|
 +
name=my_stat|
 +
return_type=float|
 +
parameter1={{Param|string|which}}|
 +
p1desc={{pspan|which}} can be "hp","mp", "Muscle", "Mysticality", or "Moxie"|
 +
}}
 +
This function wraps ASH's my_hp(), my_mp(), and my_buffedstat() functions. Anytime you're checking any of these five stats, please use this function rather than the ASH functions, for the same reason as above.
 +
 
 +
{{HideLink|happened}}{{Function|
 +
name=happened|
 +
return_type=boolean|
 +
parameter1={{Param|string|occurrence}}|
 +
}}
 +
{{Function|
 +
name=happened|
 +
return_type=boolean|
 +
parameter1={{Param|skill|occurrence}}|
 +
}}
 +
{{Function|
 +
name=happened|
 +
return_type=boolean|
 +
parameter1={{Param|item|occurrence}}|
 +
}}
 +
{{Function|
 +
name=happened|
 +
return_type=boolean|
 +
parameter1={{Param|advevent|occurrence}}|
 +
p1desc={{pspan|occurrence}} is the advevent ID you want to check|
 +
}}
 +
Use this function to check if an action has already happened during this combat.  For example, if you have already used a seal tooth on a previous round, or you have enqueued a seal tooth, happened("use 2") will return true.  In addition to canonical action ID's (BALLS syntax), BatBrain also gives you a few other handles for special events: crit, shieldcrit, smusted, stolen, icecapstun, hipster_stats, sealwail, and lackstool.

Revision as of 05:14, 10 September 2013

About BatBrain

BatBrain is a function library intended to greatly simplify writing a consult script. A general introduction, changelog, download, and forum discussion can be found in the BatBrain thread, but this page is the best place for scripters interested in writing a consult script with BatBrain to start. NOTE: BatBrain is not built into KoLmafia, it is a separate ASH script which you must download and import to make these functions available.

What It Does

yadda yadda

Spreads

BatBrain handles all damage done (both to you and to the monster) as spreads. In fact, it defines a data type called "spread":

typedef float[element] spread;

This means that all damage is a map of floats keyed by element, with positive values for damage and negative values for healing. We could have just used float[element] everywhere, but it strikes us as cleaner to use the single word "spread". You'll see this datatype occur fairly frequently if you peruse BatBrain and if you're writing a combat script, you may have to deal with one. Fortunately, there are some functions for dealing with spreads:


to_spread

spread to_spread(string dmg )

spread to_spread(string dmg ,float factor )

  • dmg is the damage string, in the same format used by batfactors.
  • factor is optional; supply this if you want to factor the supplied damage by an amount other than 1.0

This function creates a spread from a string. For example, an attack which deals 10 hot damage would deal to_spread("10 hot") damage. The format for dmg is flexible and described in greater detail on the batfactors page. An optional factor parameter is available as shorthand for factor(to_spread()).


merge

spread merge(spread first ,spread second )

  • first is the first spread to merge
  • second is the second spread

Basic arithmetic, a + b. It returns a spread combining the damage in first and second.


factor

spread factor(spread f ,float fact )

  • f is the spread to factor
  • fact is the factor

More basic arithmetic, this time multiplication. This function returns spread f factored by fact.


to_html

string to_html(spread src )

  • src is the spread to convert to HTML

This function returns an HTML string showing a spread the way KoL does, with elemental damage parenthesized and appropriately color-coded.


dmg_dealt

float dmg_dealt(spread action )

  • action is the damage spread for a given source of monster damage

This function returns the actual damage a given spread would deal to your current opponent, accounting for the monster's resistances, vulnerabilities, and damage cap where applicable. For example, when fighting Groar, any cold damage present in action would be reduced to 1, and any damage of his vulnerable elements would be doubled. Secondly, any damage over Groar's soft damage cap would be reduced appropriately, and finally the damage would be summed together into a single float and returned.


dmg_taken

float dmg_taken(spread pain )

  • pain is the damage spread for a given source of player damage

This function returns the actual damage a given spread would deal to the player, accounting for the player's elemental resistances and vulnerabilities.

Advevents

Now that we've discussed spreads, we can really get down to it. Absolutely everything that happens, every single "adventure event" that takes place, is treated as an advevent. Your familiar performs an advevent every round, the monster performs an advevent, each action you have available is an advevent, and sometimes even your current gear or running effects contribute an advevent or two. Your current combat environment could be described with an advevent, and in fact any adjustments made to your current environment when enqueueing actions are tracked in an advevent. Get the picture? Advevents make BatBrain's world turn. And here's what they look like:

record advevent {          // record of changes due to an event
   string id;              // macro-ready name -- attack/jiggle/skill s/use i
   spread dmg;             // raw dmg dealt to the monster, before resists/vulns
   spread pdmg;            // raw dmg taken by the player, before resists/vulns
   float att;              // monster attack adjustment
   float def;              // monster defense adjustment
   float stun;             // stun chance (expressed as average rounds stunned)
   float mp;               // mp gained/lost
   float meat;             // meat gained/lost
   float profit;           // profit cache to avoid recalculating
   int rounds;             // rounds consumed
   substats stats;         // substats gained/lost
   boolean endscombat;     // whether or not this action ends the combat
   string custom;          // flag for special actions that should not be used in normal automation
   string note;            // user-friendly name or special note
};

Note that each advevent contains two spreads, one for damage to the monster and one for damage to the player. The rest is mostly self-explanatory, but a few things require clarification.

First, the profit field will contain nothing (0) until to_profit() is called on the advevent in question, at which point the result is cached in this field for further reference, since to_profit() has a fair amount of calculations and is thus much more expensive (in processing terms) than simply checking a.profit. Keep that in mind if you're calling to_profit() a lot; chances are you could speed up your script by changing a few of those to check the profit cache instead.

Second, substats is another datatype defined by BatBrain, and it's simply a float[stat] map.

The custom field will be empty for most actions, so scripts ought to be checking a.custom == "" before using an action in regular automation. For special actions, the custom field will contain the type of custom action (and sometimes additional information). Some custom types currently being used are: attract, banish, copy, yellow, and runaway.

Finally, the note field is not really used by BatBrain, but is used by BatMan RE to display extra information about certain actions (such as notices of estimates due to unspaded numbers, or ongoing damage not predicted by BatBrain, etc).

Here are some functions to help you deal with advevents should the need arise:


to_event

advevent to_event(string id ,spread dmg ,spread pdmg ,string special ,int howmanyrounds )

advevent to_event(string id ,spread dmg ,spread pdmg ,string special )

advevent to_event(string id ,string special ,int howmanyrounds )

advevent to_event(string id ,string special )

  • id is the ID of the event. BALLS-friendly name (will be used in macros)
  • dmg is for damage/healing to the monster.
  • pdmg is for damage/healing to the player.
  • special is for specifying other qualities of the action, such as deleveling, stunning, meat gained/lost, etc.
  • howmanyrounds is optional, default 0. It specifies the number of rounds this action takes. Will be 0 for all but actual player actions.

Builds and returns an advevent, used ubiquitously by BatBrain internally but also useful to a scripter for creating custom actions that are not present in opts[]. You may omit both spreads if the event being constructed deals no damage to either monster or player. The format for the special field is generally a comma-delimited list of "keyword value", although some keywords lack values. The format is described in greater detail on the batfactors page -- quite a few keywords are available. Note that if you have an elemental form, all damage specified in dmg will be converted to that element by this function.


merge

advevent merge(advevent first ,advevent second )

  • first is the first advevent to merge
  • second is the second advevent

As with the spread version, this function combines two advevents into a single advevent by individually combining each field. It isn't always just simple addition, however. First of all, the id field will be merged using a semicolon and a space, so if you were merging "jiggle" with "attack", the new combined id would be "jiggle; attack". This allows merging events to retain a BALLS-friendly ID. Second, if both first and second are single item actions and you have Funkslinging, the events will be merged into a single funkslinging action "use X,Y". The rounds field likewise will be added together unless it's being auto-funked, in which case 1 + 1 = 1. Last, the stun field is not simply added together, because if you perform two actions, each with a 50% stun chance, that does not guarantee a 100% stun chance; that's a 75% stun chance, because you have a 50% chance of stunning 50% of the time when the first action fails to stun. Merging takes this into account.


factor

advevent factor(advevent f ,float fact )

  • f is the advevent to factor
  • fact is the factor

This function multiplies an advevent by fact, and is much more straightforward than merge(). All numeric fields are simply multiplied, with one exception: the rounds field is not multiplied since that would be undesirable. BatBrain uses this function internally to apply the hitchance of an event to the event.


to_profit

float to_profit(advevent haps ,boolean nodelevel )

  • haps is the advevent to evaluate
  • nodelevel is optional, default false. If supplied as true, will ignore profit from deleveling.

Returns the profit of performing the action haps at the current point in the combat. It looks ahead one round (including the monster's event, your familiar's event, and any equipment and effects) and determines what you gained and lost, and converts all of that to a single number, which it returns. This is a very useful function for combining with other criteria and sorting opts[]. HP and MP gain/loss are evaluated based on your _meatpermp and _meatperhp properties, which are set by Bale's Universal Recovery Script. If you are not using this script, basic calculations are made using the price of common restoratives. HP/MP regeneration is also factored into the profit appropriately. By default, this function includes profit from deleveling (i.e. reducing the monster's attack by X means it will deal Y less damage, effectively earning you Y HP). However, this may be undesirable if you intend to stun beforehand, so an optional nodelevel flag was included.

Other Useful Functions

monster_stat

float monster_stat(string which )

  • which can be "att","def". or "hp"

This function wraps ASH's monster_attack(), monster_defense(), and monster_hp() functions. Please use this function instead of the ASH functions, since the value may differ if you have enqueued actions causing BatBrain to predictively alter the monster's stats.


my_stat

float my_stat(string which )

  • which can be "hp","mp", "Muscle", "Mysticality", or "Moxie"

This function wraps ASH's my_hp(), my_mp(), and my_buffedstat() functions. Anytime you're checking any of these five stats, please use this function rather than the ASH functions, for the same reason as above.


happened

boolean happened(string occurrence )

boolean happened(skill occurrence )

boolean happened(item occurrence )

boolean happened(advevent occurrence )

  • occurrence is the advevent ID you want to check

Use this function to check if an action has already happened during this combat. For example, if you have already used a seal tooth on a previous round, or you have enqueued a seal tooth, happened("use 2") will return true. In addition to canonical action ID's (BALLS syntax), BatBrain also gives you a few other handles for special events: crit, shieldcrit, smusted, stolen, icecapstun, hipster_stats, sealwail, and lackstool.