ZLib -- Zarqon's useful function library

zarqon

Well-known member
r32 Updates!

This update brings us some pretty big changes for script settings. And most of them are the sort of changes where, after the fact, you look at them and think "Dang, why didn't I just make it work like this to begin with?" Or rather, I look at them and think that. You look at them and think whatever you're about to comment below.

Inspired by Veracity's recent work around properties, I have slightly overhauled the way ZLib handles script settings:

  • First, setvar() now saves the default value and type information to vars_defaults.txt. Your vars_<myname>.txt file is not edited at this point.
  • Since the defaults are now saved separately, vars_<myname>.txt now only contains values that have been changed from the default.
  • Improved CLI output for searching/editing settings when running ZLib in the CLI.
  • Since type information is now saved for each setting, we can now normalize settings when changing them rather than the next time setvar() is called! You get immediate feedback on whether your edit worked as desired.

Important Note

There's also a new function:

string getvar(string varname)

Hitherto, we have simply used a direct vars[] lookup to reference script settings. However, with this new implementation, I'd eventually like vars[], just like vars_myname.txt, to contain only those settings which have been changed from the default. Hence, this new function, which really should have existed since the dawn of script settings.

"Script settings had a dawn?" Yes.

So, if you are a script author using ZLib's handy-dandy script settings, at some point not too far from now you'll want to

search: vars[
replace with: getvar(

And handle the closing ] to ) as well. For all your scripts. I'll be doing this over time with my scripts as well.

Since this is a not insignificant change I'll give everyone loads of time to transition. Let's say... six whole months! Or maybe a year! For now, ZLib adds the default values back in to vars[] so as not to break existing scripts. But in the meantime, let's all encourage each other to be better versions of ourselves and use getvar(), not vars[].

I've also updated this information on ZLib's Wiki page (which you can get to by typing "ashwiki zlib" in the CLI). And in the big info-post I made when I first introduced script settings, in case anyone has linked to that post.

The best and most exciting part of the script settings revamp is yet to come -- a new relay script for editing ZLib script settings and mafia properties. I have everything except the actual editing part complete and it's looking awesome:

PrefrefPlus.PNG

Changes to Kmail Functions

Also this update brings us the fix suggested by AlbinoRhino above, implemented by digitrev in his New You script, and as it turns out, suggested by Bale in this very thread back in June of 2011. Somehow that suggestion passed right by me back then without ever catching my eye. My eye was no doubt looking at some far-off vision of the future and was not so easily distracted by the mundane reality of the present!

So, the future is now! Since items, etc. can be received mid-kmail, the message field will now be the entire message.

Also, I discovered a little bug in kmail() which I'm quite surprised no one spotted yet. When sending meat and more than 11 different items to a person who can receive non-gift items, the amount of meat specified would be sent in all the item group kmails, not just the first. I have driven the windshield of correct code through the flight path of this bug, and it exists no more.

Enjoy the future, everyone!
 

zarqon

Well-known member
In case it's helpful, I updated all my scripts (and everyone else's) to use getvar() by doing this simple batch search/replace in Notepad++:

notepad replace.PNG

I have posted it here for you to copypasta. Since regexes are of course extremely dangerous beasts, I have enclosed the search in a protective code tag. Please remove it from your clipboards immediately after use.

Code:
Find: \bvars\[\"(.+?)\"\]
Replace with: getvar\(\"\1\"\)
 

xKiv

Active member
Of course, that will only catch accesses by literal names, not by variables (vars["barf"] vs. string vname="barf"; vars[vname]).
It will also not catch accesses using single quotes (ash accespts that too).
It will also mangle monstrous codes that use something like vars["prefix" + '["i am a troll"]' + ".postfix"]

So, you know, regexes. Use at your peril. Verify.
 
Mangling that monstrous code sounds like a bonus ;)

And nice work zlib, I was already wondering why mafia reported updating all my variables when I ran a few of my scripts.
 

zarqon

Well-known member
@xKiv: Thank you for clarifying that, I hadn't meant to imply that the regex was a one-size-fits-all easy fix! I first clicked the "Find All" button to review all the instances it would change and make sure they were correct. I had to revert a few of them afterwards. Also another search for just the opening vars[ would be recommended to catch those other cases. Fortunately ZLib vars are nearly always referenced by literal name, so those cases should be few to nonexistent.
 

Theraze

Active member
Question. EatDrink had some values that changed from boolean to ints. I manually used vars[] to rewrite them when people have invalid values, but... is there some better way to do it rather than setting vars[] with updatevars() to seal it, since setvar() will only set it if's completely blank...?

Second EatDrink question - it allows users to set any item they'd like to avoid (or gorge) and each gets its own eatdrink_avoid_item or eatdrink_fav_item var. We then use var_check to search through vars to see if it's set and, if set, verify that it's true. The delisting of defaults will make EatDrink start consuming astrals and other quest items without warning. Does EatDrink need to have its own version of getvar to not complain about over 18650 missing avoid and fav records?
 
Last edited:

zarqon

Well-known member
You can continue to write to vars[] as before, though checking for a variable in vars is not a guarantee that it does or does not exist. You would also have to check vardefaults[].

However, though I wasn't clear what you meant by "delisting of defaults" I think you're fine in this case, as values that are not present in defaults can still exist and will not be removed (quite necessary given we're transitioning from not having defaults). Usually that would mean you haven't run the script the setting belongs to yet, but it could also be used for arbitrary values. It would only be removed from vars if you set it to a value that is the same as the default.
 

coandco

Member
The new update of ZLib seems to have broken Harvest.ash rather completely. I'm seeing some frankly bizarre behavior that I don't understand, where I'm getting conflicting values for variables via the CLI and in-script:
Code:
> zlib har_farming_location

Copy/paste/modify/enter any of the following lines in the CLI to edit settings:

zlib har_farming_location = Barf Mountain
Requests complete.

That's as it should be. But when I try to access that same variable in a pared-down test script, test.ash:
Code:
import <zlib.ash>;

print("har_farming_location is " + getvar("har_farming_location"));
Code:
> call scripts\test.ash

har_farming_location is The Castle in the Clouds in the Sky (Top Floor)

I'm pretty sure "The Castle in the Clouds in the Sky (Top Floor)" is the default value of the variable as set by the Harvest.ash script, but I haven't run anything in between my direct zlib invocation and my test.ash call. What am I missing here? Why are values available via direct zlib invocation but not by the new getvar() call?
 

Theraze

Active member
However, though I wasn't clear what you meant by "delisting of defaults" I think you're fine in this case, as values that are not present in defaults can still exist and will not be removed (quite necessary given we're transitioning from not having defaults). Usually that would mean you haven't run the script the setting belongs to yet, but it could also be used for arbitrary values. It would only be removed from vars if you set it to a value that is the same as the default.

Since this is a not insignificant change I'll give everyone loads of time to transition. Let's say... six whole months! Or maybe a year! For now, ZLib adds the default values back in to vars[] so as not to break existing scripts. But in the meantime, let's all encourage each other to be better versions of ourselves and use getvar(), not vars[].

That's the delisting I was talking about. If we parse through the vars list as currently...
Code:
boolean var_check(string vari) { 
    if(vars contains vari) 
        return vars[vari].to_boolean(); 
    return false; 
}
As long as vars contains the defaults, then var_check as it exists will continue to work. If the defaults are delisted from vars, then we need to change var_check to be a modified form of getvar to check specific values without spamming the screen, even if they happen to have verbosity up to 9.
 

coandco

Member
That is required for the new property changes to work. Zargon needs to make it a dependency

Hmm. That didn't help. I installed vprops and edited my test script, which now reads:
Code:
import <vprops.ash>;
import <zlib.ash>;

print("har_farming_location is " + getvar("har_farming_location"));

I'm seeing the exact same behavior:

Code:
> zlib har_farming_location

Copy/paste/modify/enter any of the following lines in the CLI to edit settings:

zlib har_farming_location = Barf Mountain

> call test.ash

har_farming_location is The Castle in the Clouds in the Sky (Top Floor)

I'm at a loss for where to look to diagnose this problem.
 

zarqon

Well-known member
@coandco: That's new. Can you duplicate this issue and then open both your vardefaults.txt and vars_<myname>.txt files and tell me the values of that setting in each file?

@txrangersxx: Funny because it works for me without vprops installed. :)

@Theraze: Aha. This bit of ZLib loads the defaults into another global map called vardefaults:

PHP:
record singlesettingdefault {
   string type;         // int, string, boolean, etc. (later can be "list of X" or filter/mask)
   string val;          // default value as initialized in setvar
   string init;         // use date for now to form groups; ideally establishing script
};
static {
   singlesettingdefault[string] vardefaults;  // stores all script setting default values
   file_to_map("vars_defaults.txt",vardefaults);
}

So for cases where you were checking vars[] for x, you'll have to check both. This ought to behave like your previous function did:

PHP:
boolean var_check(string vari) { 
    if(vars contains vari || vardefaults contains vari)
        return getvar(vari).to_boolean(); 
    return false; 
}

If these variables aren't being set with setvar() though, there's no need to change anything, since they will never be present in vardefaults[].

This is much cleaner:

PHP:
boolean var_check(string vari) { 
    return getvar(vari).to_boolean();
}

but as you mentioned it does output those verbosity 4 alerts when trying to access settings that don't exist in either vars or vardefaults. That's a rather unorthodox use of script settings and would probably be better suited to a separate data file (imagine if BatBrain tracked happenings in ZLib vars, haha), so I'm not going to remove that friendly warning message as it is helpful for all the more "intended" uses. :)
 

coandco

Member
@coandco: That's new. Can you duplicate this issue and then open both your vardefaults.txt and vars_<myname>.txt files and tell me the values of that setting in each file?

Okay. I've confirmed the issue still exists:
Code:
> zlib har_farming_location

Copy/paste/modify/enter any of the following lines in the CLI to edit settings:

zlib har_farming_location = Barf Mountain

> call test.ash

har_farming_location is The Castle in the Clouds in the Sky (Top Floor)

Here's the setting in vars_defaults.txt:
Code:
har_farming_location	location	The Castle in the Clouds in the Sky (Top Floor)	20170516 00:41:09 PDT

When I open vars_CrankyOne.txt, the line isn't present. In fact, "Barf Mountain" doesn't show up in any text file in the data directory:
Code:
E:\Temp\data>grep -i "Barf Mountain" *.txt

E:\Temp\data>

I'm really not sure where it's getting "Barf Mountain" from when I do the zlib CLI invocation, but it's definitely there. Is there some sort of debug switch I could turn on to get more output from zlib?
 

coandco

Member
Hmm. I restarted KoLMafia completely, and the CLI and script invocations of zlib are now in sync once more... as the default values. I had to completely redo all of my Harvest.ash settings, but they now seem to be holding steady across Mafia restarts, and I was able to do my farming. We'll see what they look like once rollover hits. Hopefully this was a one-time thing, though the other thread that got linked here doesn't fill me with hope, as other people are complaining about their stuff getting repeatedly reset.
 
Top