Zlib
About Zarqon's Useful Function Library
Behold, a single function library containing most of zarqon's most useful functions, which will be used by most of his scripts. He grew tired of tweaking a function that was in multiple scripts and making sure he had changed them all. It would be nice, he thought in his customary italics, to have it in just one place.
In choosing which functions to include, he have tried to select only those functions which are a) super useful, or 2) needed by another of the included functions. It's a bit less efficient in terms of individual scripts, but in terms of repeated code across a family of scripts it is far simpler.
Functions
excise
string excise(string source ,string start ,string end )
- The original source string
- start after this string
- end before this string
This function returns a portion of the source string, from after the first occurrence of start to just before the first occurrence of end. If either start or end are missing, it will return an empty string. You can also supply either start or end as blank strings to specify the actual start or end of the source string.
normalized
string normalized(string mixvar ,string type )
- mixvar is the string to normalize
- type is the datatype to normalize to
Returns mixvar, normalized to the specified KoLmafia type, which can be any primitive type or ASH datatype constant. For example, normalized("badger", "familiar") would return "Astral Badger".
rnum
string rnum(float n ,int place )
- n is a number
- place is the number of decimal places to round to
Returns your number n as a human-readable string. For ints, this means it adds commas where appropriate. For floats, it also rounds to the nearest place after the decimal. Default place for the float-only version is 2, although it may display fewer digits if they are 0's. Examples: rnum(12580) => "12,580", rnum(3.14152964,3) => "3.142", rnum(4.00008) => "4", rnum(123456789.87654321) => "123,456,789.88". Recommended as a substitute for to_string().
set_avg
void set_avg(float to_add ,string which_prop )
- to_add is the data point to add
- which_prop is the property to add data to
Useful for adding spading to scripts. Adds one more statistic to an average value being stored in a property. For example, calling this script three times with the values 2, 4, and 6 for to_add would result in the property which_prop containing "4.0:3", with 4.0 being the average of the three numbers added and 3 being the amount of numbers averaged.
get_avg
float get_avg(string which_prop )
- which_prop is the property to access
Returns an average value set by set_avg().
eval
vfloat eval(string expression ,float [string] values )
- expression is the base expression
- values is a map of values to replace
By Jason Harper. Evaluates expression as a math expression, and allows you to substitute values for variables, as described in much greater detail here. A brief version of this documentation is also included in ZLib. (NB: This section needs more infoz.)
vprint
boolean vprint(string message ,int level )
boolean vprint(string message ,string color ,int level )
- message and color are used as in the function
print()
- level is a verbosity reference
Wrapper for print() and abort(), prints message depending on vars["verbosity"] setting. It has a boolean return value so it can replace { print(message); return t/f; } if level == 0: abort with message if level > 0: prints message if verbosity >= level, returns true if level < 0: prints message if verbosity >= abs(level), returns false
First, level controls the return value -- if level is positive, vprint will return true; if negative, it will return false. If level is 0, vprint() will abort with the specified message. You can see now that vprint already replaces both abort() and error(). I recommend using it in place of abort() in case a savvy user wishes to avoid or otherwise handle aborts somehow.
So this takes care of my annoyance with needing brackets and two commands just to return a boolean along with user feedback. How about the verbosity issue?
Ladies and gentlemen, there is now a new ZLib setting "verbosity" (integer). If the absolute value of level is more than verbosity, the message will not be printed. This allows users to control the chattiness of scripts, and allows authors to include debug print statements which can be shown by setting verbosity high.
Recommendations for Verbosity Levels in vprint()
0: abort error
+/- 1: absolutely essential (and non-cluttering) information -- use very sparingly, since a verbosity of 1 is basically "silent mode"
+/- 2: important and useful info -- this should generally be your base level for your most important messages
+/- 4: interesting but non-essential information
+/- 6: info which an overly curious person might like to see on their CLI
+/- 10: details which are only helpful for debugging, such as "begin/end functionname()" or "current value of variable: value"
This will allow users who want extra levels of detail printed to see that detail without cluttering the CLI for users who don't prefer to see all the details. In addition, it allows users to specify a verbosity of 0 to see ONLY mafia output (no script output at all), which could prove handy.
There is also a version of vprint() without the color parameter. The default color is black for positive values of level, and red for negative values. So, basically you don't need to use the version with color unless you want to specify a different color or override the default colors.
vprint_html
boolean vprint_html(string message ,int level )
- message is used as in the function
print_html()
- level is a verbosity reference
Same as vprint() above, but wraps print_html()
.
abs
- n is a number of either int or float type.
Returns the absolute value of the number n in the same datatype as supplied.
minmax
float minmax(float a ,float min ,float max )
- a is the original number
- min is the minimum return value
- max is the maximum return value
Returns a, but no less than min and no more than max.
check_version
string check_version(string software ,string property ,string this_version ,int thread )
- software is the script name, which must match the page source of the thread being parsed
- property is used as part of the name of the property saved to user preferences
- this_version is the version of the script currently running
- thread is the script's thread-number on kolmafia.us
Server-friendly once-daily version-checking. If the user hasn't checked yet today, visits the specified thread on the kolmafia.us forums to find the current version of your script. The thread must include "<b>software version</b>" for the version info to be successfully parsed (using the thread's script's version, which may differ from this_version). Optionally, you may include "[requires revision XXXX]" in the post if you want to indicate a required minimum revision of mafia. If a new version is available, alerts the user in large text and provides an update link, then waits for a sufficiently annoying interval in case the user wishes to abort operation to go update the script. The return value is a blank string unless an update is found, in which case it is a <div id='versioninfo'> containing the update message. This allows this function to work equally well for relay scripts. The current version is stored to a daily property, standardized to "_version_"+property. Example:
check_version("Hardcore Checklist","checklist","1.2.7",1045);
load_current_map
boolean load_current_map(string map_name ,aggregate destination )
- map_name is the name of the map, without the file extension
- destination is a previously-declared map to load with data
Acts as a wrapper for the built-in file_to_map()
with automatic update capability. The first time the function is called for a given map each day, it will check Zarqon's Map Manager to see if an update for the given map_name is available, and if so will load from there. Otherwise, it merely loads it from disk. (Note: you should not include a file extension, such as ".txt" in the map_name parameter.)
setvar
void setvar(string name ,string default )
void setvar(string name ,boolean default )
void setvar(string name ,int default )
void setvar(string name ,float default )
void setvar(string name ,item default )
void setvar(string name ,location default )
void setvar(string name ,monster default )
void setvar(string name ,element default )
void setvar(string name ,familiar default )
void setvar(string name ,skill default )
void setvar(string name ,effect default )
void setvar(string name ,stat default )
void setvar(string name ,class default )
- default is the default value
This sets per-character script variables (but only the first time, after that the stored value will be used, rather than default). Several interesting possibilities now present themselves to users and script authors.
For Users
- Script settings are now all saved in one place, separate from mafia settings. I've read more than one post wishing that script-defined settings and mafia settings would be separate. This provides a solution.
- Script settings are independent from scripts. This means that you will no longer need to edit scripts to adjust your setttings. Further, when you download a script update, the script will use your saved settings and you won't need to reset them!
- To see all of your current settings, type "zlib vars" in the CLI. To change a setting, type "zlib settingname = value". If you're adjusting threshold, you can use "up" or "down" as the value to adjust your threshold relatively. This is almost exactly as convenient as mafia settings (possibly more so since you don't need to open a text file to find setting names!).
- If for some reason you prefer to open a text file, ZLib settings are stored in a file called vars_myname.txt in your data directory.
- Scripts that use this feature will add more settings, but not until after you run them once. Script documentation should tell you which settings to change to get your desired behavior.
For Script Authors
- Script settings may now be used across scripts, in exactly the same way that mafia settings are. Basically, this works almost exactly like mafia settings, except that new settings can only be created by setvar() or manually editing the file ("zlib nonexistentsetting = value" will fail).
- Settings are only stored if you run a script that defines/uses them. So your settings file will not contain any extraneous unused settings.
- Script authors can now test for a setting's existence, which means you can check to see if a user has used a given script. It's almost as good as a script_exists() function. This can allow scripts to work together with other scripts, if they exist!
- Scripts with overlapping or related functionality can be designed to access a single shared setting, in much the same way that my scripts have until now all shared a "threshold" mafia setting. Changing a single setting can now change the behavior of every script that accesses that setting.
Functional Details
When importing ZLib, it loads a map of your script settings from vars_myname.txt. It is a basic string[string] map called vars. To access a script setting within an ASH script, use vars[varname]. To check if a setting exists you can simply use if (vars contains varname).
When a script calls setvar("threshold",4), ZLib checks to see if a variable called "threshold" already exists in vars. If so, the existing value is not changed. If not, it sets it to 4 and saves the map back to vars_myname.txt.
The dfault parameter can be any primitive or ASH type ($item, $effect, etc), but not a map, array, or record.
At present, nothing is done with types and they could all have just been strings, but I have some plans involving a remote server containing setting documentation, where it would be quite useful to have data types saved along with the variablenames.
Choosing Setting Names
The file of script settings will contain all script settings, sorted alphabetically. Also, there is no way to detect if a setting is unused, so if you decide to change the name, the old setting will never be deleted. Please think carefully about your setting names. If you have a setting named "setting1", a user will probably not have a clue which script that is for or what it does. True, this can be overcome with documentation, but it is far better to have settings that make sense just by looking at them.
My recommendations:
1. Use a name that clearly identifies what the setting is/does.
2. Prefix your setting names with a script identifier. For example, here are some of my One-Click Wossname script settings:
setvar("ocw_warplan","optimal");
setvar("is_100_run",false);
setvar("ocw_change_to_meat",true);
setvar("ocw_nunspeed",false);
setvar("defaultoutfit","current");
setvar("ocw_f_default","zombie");
setvar("ocw_m_default","");
Those settings which are specific to OCW are prefixed with "ocw_" so as to be found together in the settings file. However, some of the settings are usable across scripts, and are not so prefixed. For example, I intend to use the "is_100_run" variable in every script that swaps familiars, so as to avoid tainting a 100% run. Likewise, the "defaultoutfit" will be used by nearly all of my adventuring scripts that swap outfits (MacGuffin, OCW).
have_item
int have_item(string to_lookup )
- map_name is the name of the map, without the file extension
A residual function, used by the following and probably in several other scripts. Returns the amount of an item you have both in your inventory and equipped. Functionally equivalent to the built-in function available_amount()
, except that its parameter is a string. (Zarqon please verify.)
has_goal
float has_goal(item check_me )
float has_goal(monster check_me )
float has_goal(location check_me )
- check_me is the item, monster or locationto check
At the base of this function is the item parameter version, which returns the chance that the item check_me is or results in a goal. If is_goal(item) == true or it's a bounty item, returns 1.0. Otherwise, returns the chance that you would get a goal from using the item. For example, with a goal of black pepper, has_goal($item[black picnic basket]) would return 0.58. Many thanks to aqualectrix for creating and sharing the container items results map.
When supplied a monster as the parameter for check_me, returns the percent chance that encountering the given monster will result in a goal, taking into account +items, pickpocket availability (and +pickpocket), and Torso. For instance, with no +item and black pepper as a goal, has_goal($monster[black widow]) would return 0.087 (0.58 basket contains pepper * 0.15 basket drop rate). Also note that it will add multiple goals together, so with white pixels as a goal, a Blooper would return 2.1.
When supplied a location as the parameter for check_me, returns the chance that adventuring at a given location will yield a goal. For our black pepper example, has_goal($location[black forest]) would return 0.0174 (0.2 black widow appearance rate * 0.087 chance that a widow has black pepper). Presently this accounts for combat frequency modifiers but not Olfaction, and it will be off for areas with noncombats that grant goals, because it assumes that all noncombats do not yield items.
obtain
boolean obtain(int qty ,string condition ,location place )
boolean obtain(int qty ,string condition ,location place ,string filter )
- qty is the quantity of the item or choice adventure desired
- condition is the item or choice adventure to use as a goal
- location is the place to adventure to obtain your goal
- filter is an optional combat filter used the same as in
adventure()
Attempts to get qty (minus existing) of condition, either by purchasing (if you have the KoLmafia preference set), pulling from Hangk's, or adventuring at the specified place. It also works with choice adventures.
use_upto
boolean use_upto(int qty ,item thing ,boolean purchase )
- qty is the quantity to use
- thing is the item to use
- purchase is true if KoLmafia should purchase extras if you don't already have qty
Gets (if purchase is true) and uses qty of the item(s) thing if possible. Otherwise, uses as many as you have up to qty.
resist
boolean resist(element resist_it ,boolean really )
- resist_it is the element to resist
- really is true to actually attemp resistance, false to check only
Returns whether you are able to resist a given element resist_it, or if really is true, attempts to actually achieve that resistance (casting buffs, changing gear, or equipping your Exotic Parrot) and returns its success.
my_defstat
int my_defstat()
Returns the value of your buffed defense stat, taking into account Hero of the Half-Shell.
get_safemox
int get_safemox(location where )
- where is the location to check for safe moxie
int get_safemox(location wear) Using mafia's location/monster data, returns the safe moxie of a given zone where.
auto_mcd
boolean auto_mcd(int check_me )
boolean auto_mcd(monster check_me )
boolean auto_mcd(location check_me )
- check_me is the int, monster or location to check
If your ZLib setting "automcd" is true, automatically adjusts your mind-control device for maximum stat gains based on safe moxie and your ZLib "threshold" setting. Does not adjust for MCD-sensitive areas (certain bosses, Slime Tube), or areas with no known combats. Returns true unless KoLmafia is unable to do so, even though the script thinks it should be capable (still returns true if you can't currently access an mcd-changing device).
best_fam
familiar best_fam(string type )
- type is the type of familiar ability to check for
Returns your heaviest familiar of a given type (currently possible: items, meat, produce, stat, delevel). If your ZLib "is_100_run" setting is anything other than $familiar[none], returns that familiar (so you don't have to make the check in your script).
send_gift
boolean send_gift(string recipient ,string message ,int_meat ,int [item] goodies )
boolean send_gift(string recipient ,string message ,int meat ,int [item] goodies ,string inside_note )
- recipient is the player to send to
- message is the outside message
- meat is the amount of meat to send
- goodies is a map of items & amounts to send
- inside_note is an optional inside message
Sends a gift to a player. Able to split large amounts of items. Returns true if the package is sent and false if not. See kmail() below.
kmail
boolean kmail(string recipient ,string message ,int_meat ,int [item] goodies )
boolean kmail(string recipient ,string message ,int_meat )
boolean kmail(string recipient ,string message ,int meat ,int [item] goodies ,string inside_note )
- recipient is the player to send to
- message is the outside message
- meat is the amount of meat to send
- goodies is an optional map of items & amounts to send
- inside_note is an optional inside message if sent as a gift
Sends a kmail to player recipient, returning true if the kmail is successfully sent. Handles splitting the message into multiple messages if the number of item types in goodies is too large. Returns the result of send_gift() if the intended recipient is unable to receive the message due to being in HC or somesuch. Note that you can also specify the inside_note to be used inside gifts in that case. Use "\n" to specify a new line in the message.
Making use of Zlib
To include this library in your script, simply add the following towards the top of your script:
import "zlib.ash";
Then all these functions will be available in your script. Have fun!
More Information
See the thread for ZLib on the mafia forum here.