ZLib -- Zarqon's useful function library

They're compiled into the jar though right? I don't have any overridden

The batfactors data file is publicly editable and not part of the SVN. BatBrain checks to see if there is a new copy the first time you run it on a given day.
 
I suspect no amount of large type and bold face can fend it off every time.

Anything bolder than this is just too much.
 
Is there any way to used normalized safely on a list of items when some of the items have commas in their name?

Code:
> ash import <zlib.ash>; string res = "buddy bjorn"; foreach it in $items[] { if(index_of(to_string(it),",") != -1) res = list_add(res, to_string(it)); } print(res); print(""); print(normalized(res, "list of item"));

buddy bjorn, Happy Birthday, Claude! cake, "I Love Me, Vol. I", Staff of Ed, almost, Maxing, Relaxing, A Crimbo Carol, Ch. 1, A Crimbo Carol, Ch. 2, A Crimbo Carol, Ch. 3, A Crimbo Carol, Ch. 4, A Crimbo Carol, Ch. 5, A Crimbo Carol, Ch. 6, Victor, the Insult Comic Hellhound Puppet, myrrh-soaked, chocolate-covered bacon bath ball, Notes from the Elfpocalypse, Chapter I, Notes from the Elfpocalypse, Chapter II, Notes from the Elfpocalypse, Chapter III, Notes from the Elfpocalypse, Chapter IV, Notes from the Elfpocalypse, Chapter V, Notes from the Elfpocalypse, Chapter VI, holy bomb, batman, A Crimbo Carol, Ch. 1 (used), A Crimbo Carol, Ch. 2 (used), A Crimbo Carol, Ch. 3 (used), A Crimbo Carol, Ch. 4 (used), A Crimbo Carol, Ch. 5 (used), A Crimbo Carol, Ch. 6 (used), Aye Aye, Captain, Aye Aye, Tooth Tooth, Oh, the Humanitini, Earth, Wind and Firewater, tiny plastic Hank North, Photojournalist, Chef Boy, R&D's business card, Irish Coffee, English Heart, Ouija Board, Ouija Board, "2 Love Me, Vol. 2", History's Most Offensive Jokes, Vol. IX, Trash, a Memoir, 1,970 carat gold

Buddy Bjorn, Happy Birthday, Claude! cake, Happy Birthday, Claude! cake, "I Love Me, Vol. I", "I Love Me, Vol. I", Staff of Ed, none, Maxing, Relaxing, Maxing, Relaxing, none, none, none, none, none, none, none, none, none, none, none, none, Victor, the Insult Comic Hellhound Puppet, Victor, the Insult Comic Hellhound Puppet, myrrh-soaked, chocolate-covered bacon bath ball, myrrh-soaked, chocolate-covered bacon bath ball, none, none, none, none, none, Notes from the Elfpocalypse, Chapter III, none, Notes from the Elfpocalypse, Chapter IV, none, none, none, Notes from the Elfpocalypse, Chapter VI, holy bomb, batman, holy bomb, batman, none, A Crimbo Carol, Ch. 1 (used), none, A Crimbo Carol, Ch. 2 (used), none, A Crimbo Carol, Ch. 3 (used), none, A Crimbo Carol, Ch. 4 (used), none, A Crimbo Carol, Ch. 5 (used), none, A Crimbo Carol, Ch. 6 (used), Aye Aye, none, Aye Aye, Aye Aye, Tooth Tooth, Oh, the Humanitini, Oh, the Humanitini, none, Earth, Wind and Firewater, tiny plastic Hank North, Photojournalist, tiny plastic Hank North, Photojournalist, Chef Boy, R&D's business card, Chef Boy, R&D's business card, Irish Coffee, English Heart, Irish Coffee, English Heart, Ouija Board, Ouija Board, Ouija Board, Ouija Board, "2 Love Me, Vol. 2", "2 Love Me, Vol. 2", History's Most Offensive Jokes, Vol. IX, History's Most Offensive Jokes, Vol. IX, none, Trash, a Memoir, 1,970 carat gold
Returned: void

As you can see, some items get doubled (Ouija Board, Ouija Board, for example), whereas others are completely deleted (A Christmas Carol, all chapters)

It would probably be solution enough to be able to supply an argument for glue to normalized like you can with list_add and list_delete.
 
Oh, that would be a rather important problem you've found there. Ew. For now in r30 I've made the change you suggest, adding an optional glue parameter. But this is more of a workaround than a fix; it won't help people who add a monster with a comma name in it to any of their BatMan options, for instance. This will require a bit more thought.

Also:

Function Added

This update also adds a new (to Zlib) function:

boolean qprop(string test)

I've found myself needing/using something like this in quite a few scripts. Adding it to ZLib allowed me to simplify a number of scripts, and provides a proper solution for scripters who may be otherwise tempted to take shortcuts. People who have perused the CanAdv code are already familiar with it, but it is a bit changed in this instance to allow a wider range of logical checks.

Basically, qprop() simplifies checking quest properties. The "test" parameter should be supplied like so:

<quest property> <logical operator> <possible property value>

For instance:
  • To check that a quest is complete: qprop("questLXXSomequest == finished")
  • To check that a quest has reached or passed "step2": qprop("questLXXSomequest >= step2")
  • To check that a quest is not complete: qprop("questLXXSomequest != finished")
  • To check that a quest hasn't reached step3 yet: qprop("questLXXSomequest < step3")

For convenience, various forms of operators are accepted (i.e. both "==" and "=", or both "<>" and "!=").

The function converts these text properties to numbers internally, so to save the function a completely insignificant amount of milliseconds (and more importantly yourself a little typing) you can also just use numbers directly instead of text values, where "step3" is 3, unstarted is -1, started is 0, and finished is 999. Thus the last example above would also work as qprop("questLXXSomequest < 3").

One more bit of shorthand: you can supply only the property name by itself to check whether the quest is finished. The first example above would also work as qprop("questLXXSomequest").

This ought not to break any existing scripts because thus far I've only seen qprop()s with more than one parameter.

Enjoy!
 
Also:

Function Added

This update also adds a new (to Zlib) function:

boolean qprop(string test)

...

Enjoy!

Oh my god, I sure will. Any possibility of some sort of shorthand for checking if a quest is between two values? Something like qprop("questLXXSomequest == step1-step3") or qprop("step1 < questLXXSomequest < step3") or qprop("questLXXSomequest between step1,step3"). Or, you know, whatever notation.

EDIT: Also, some thoughts on a non-workaround solution to normalized. How about when you get the normalized name, you check if that contains a comma (or whatever the glue is), and if so, you check if the name continues past where you had cut it off, and if so, you ignore that bit? That would only fix matters for the cases that are getting doubled now, wouldn't help with the ones that are becoming none. So maybe in that case if you get none as the result, check starting from the same point, but going one glue further, and see if that's a valid item, in which case you use that? That could be kind of problematic though, because what about items (or whatever else you're normalizing a list of) that have more than one comma or whatever else in the name? A quick check via some ash says there's no items with multiple commas, but there's a single enemy with multiple commas: "loose coalition of yetis, snowmen, and goats", but who knows what the future holds?
 
Last edited:
I'm afraid in those cases you'd probably best stick to ASH:

($strings[step1, step2, step3] contains get_property("questLXXSomequest"))

or two separate qprop() calls would be slightly less elegant but would also work.

qprop("questLXXSomequest >= 1") && qprop("questLXXSomequest <= 3")
 
Suggested change (because I'm getting an SVN failure over and over again

Code:
if (zv[proj].vdate == today_to_string()) return "";
[B][U]--->>>>   zv[proj].vdate = today_to_string();[/U][/B]
   vprint_html("Checking for updates (running <a href='http://kolmafia.us/showthread.php?t="+thread+"' target='_blank'>"+soft+"</a> rev. "+svn_info(proj).revision+")...",1);
   if (!svn_at_head(proj)) {
      cli_execute("svn update " + proj);
      msg.append(soft+" has been updated from r"+zv[proj].ver+" to r"+svn_info(proj).revision+".  The next time it is run, it will be current.");
   }
  [B][U]--->>>>    //zv[proj].vdate = today_to_string();[/U][/B]

That way it will only check once a day even if it fails.
Otherwise you have to edit the script to skip the check.
 
Last edited by a moderator:
Good idea.

I've been getting the same error today and was looking for a way to gracefully fail rather than stop automation, but didn't come up with anything. Unfortunately there's no way to prevent an abort here because svn_at_head() triggers a hard abort when it can't connect, even though the function's return value is captured. Your suggestion here will at least drastically reduce the failures and make it possible for the script to work when you try again.

The fun part here is that since Sourceforge is evidently down, I can't commit the fix.
 
Good idea.

I've been getting the same error today and was looking for a way to gracefully fail rather than stop automation, but didn't come up with anything. Unfortunately there's no way to prevent an abort here because svn_at_head() triggers a hard abort when it can't connect, even though the function's return value is captured. Your suggestion here will at least drastically reduce the failures and make it possible for the script to work when you try again.

The fun part here is that since Sourceforge is evidently down, I can't commit the fix.

While waiting, why not step back a bit and discuss whether it is still necessary for a script author to override a user's preference for updates? Why it is necessary to increase code complexity by using an alternative/enhanced technique for updating scripts?

I could argue either way so I have no especially strong opinions but it does seem like forcing an update is no longer the benefit it was in he pre-SVN days.
 
I've just moved this script from "Scripting Discussion" to "Informational Scripts" because it was created in a forum that isn't intended for discussing and supporting an active published script.
 
Since there's no particularly appropriate forum for library scripts, I accept your moving of a script which doesn't provide information but is intended as a tool for scripters from Scripting Discussion to Informational Scripts. :P

BTW, the above fix was added to the version checking, though I didn't announce it here.
 
Since there's no particularly appropriate forum for library scripts, I accept your moving of a script which doesn't provide information but is intended as a tool for scripters from Scripting Discussion to Informational Scripts. :P

It is something that has been nagging my mind for the last few years, but I left the status quo alone since I was on the fence about it. Veracity decided to follow your lead which finally caused me to do something since I felt both of those library scripts were slightly better off here. At least now it is residing in the "Repository" section of the forums, instead of filed under "Discussion." Unfortunately there is no sub-forum called "Script Scripts" where both of these threads could reside. 'Tis kind've a shame since "Script Scripts" is such a nice title...
 
Code:
void load_kmail(string calledby) { // loads all of your inbox (up to 100) into the global "mail"
   mail.clear();                   // optionally, specify your script in "calledby"
//   matcher k = create_matcher("'id' =\\> '(\\d+)',\\s+'type' =\\> '(.+?)',\\s+'fromid' =\\> '(-?\\d+)',\\s+'azunixtime' =\\> '(\\d+)',\\s+'message' =\\> '(.+?)',\\s+'fromname' =\\> '(.+?)',\\s+'localtime' =\\> '(.+?)'"
//      ,visit_url("api.php?pwd&what=kmail&format=php&count=100&for="+url_encode(calledby)));
// heeheehee's JSON matcher
    matcher k = create_matcher('"id":"(\\d+)","type":"(.+?)","fromid":"(-?\\d+)","azunixtime":"(\\d+)","message":"(.+?)","fromname":"(.+?)","localtime":"(.+?)"'
      ,visit_url("api.php?pwd&what=kmail&count=100&for="+url_encode(calledby)));
   int n;
   while (k.find()) {
      n = count(mail);
      mail[n].id = to_int(k.group(1));
      mail[n].type = k.group(2);
      mail[n].fromid = to_int(k.group(3));
      mail[n].azunixtime = to_int(k.group(4));
      matcher mbits = create_matcher("(.*?)\\<center\\>(.+?)$",k.group(5).replace_string("\\'","'"));
      if (mbits.find()) {
         mail[n].meat = extract_meat(mbits.group(2));
         mail[n].items = extract_items(mbits.group(2));
[COLOR=#ff0000][B]         mail[n].message = mbits.group(to_int(mail[n].meat > 0 || count(mail[n].items) > 0));[/B][/COLOR]
      } else mail[n].message = k.group(5);
      mail[n].fromname = k.group(6);
      mail[n].localtime = replace_string(k.group(7),"\\","");
   }
}

Zarqon,

If I'm interpreting this code correctly, the highlighted line appears to assume that items/meat are only found at the end of a kmail. With the New-You messages, the Affirmation cookie is actually acquired in the middle of the message. This causes the portion of the message that describes the daily bounty quest to be lost from "mail[n].message".

I was writing a script to parse the bounty quest message and this was the first time I ever tried zlib's mail functions. Perhaps there is a good reason it's designed this way which isn't obvious to me. I can change my local copy of zlib, if necessary, but thought I would post this to see if you were interested in changing the kmail parsing in the official version to accommodate such messages. Thanks !
 
Looks like you're quite right. It's been quite a while since I've looked at the mail functions -- probably at the time they were written, items or meat being received mid-message would have been unheard-of. I'll activate my New-You thingy and have a look.

Veracity has inspired me with her fairly recent activity around mafia properties, so I'll be rolling out a bunch of pretty cool stuff to do with that soon. For starters, ZLib vars will now store the type and default in a one-per-computer file, and your personal vars file will only contain values you've changed from the defaults. And the WOSSMAN will be replaced by something better that also handles mafia properties. BWAHAHAHA
 
Back
Top