ZLib -- Zarqon's useful function library

Cool. :) I can do that. Here's a file with the majority of the stat-gain & deleveling familiars. I used stat and delevel as the type. I listed both the Barrrnacle-like (delevels at beginning of combat) and the Skeleton-like (delevels during combat) familiars under the one type "delevel". That could be divided into two types if that is desired. If you want any others let me know.

Edit: sorry, :o didn't see where you said to upload it. Adding it to the script registry now. And it's been added. Nice!
 
Last edited:
Thanks for the help FN Ninja, it looks great!

Before more types are added (I need to add an "elemental damage" type for the upcoming physresist.ash CCS), I want to make a change to best_fam() -- some way of ranking the strength of the familiar for a given type needs to be added, so that best_fam() will still work in the event that all familiars of a given type are the same weight. If your only meat-producing familiars are a NPZR and Fuzzy Dice, presently best_fam() would choose the Fuzzy Dice since it is the first match in the list, which is definitely sub-ideal behavior.

Once I make the change, there will be an integer value after the type, e.g.

Fuzzy Dice produce 1
Ninja Pirate Zombie Robot produce 7, delevel 3

Higher numbers indicate higher effectiveness or desirability. For example, even though a Nervous Tick has the same meat production as a Leprechaun, its meat number would be higher. Numbers should be chosen with a bit of room in between to allow room for future expansion.

Also note: if adding types, make sure the type names don't match any familiar names. You can check this in the CLI using ash to_familiar("typename");

> ash to_familiar("delevel")

Returned: none

This is useful for allowing scripts to use strings for desired familiars. If the specified string does not match a familiar (i.e. to_familiar() returns $familiar[none]), it can be assumed to be a familiar type and passed along to best_fam().

BONUS EDIT: speaking of this new format, I'm working on it now and it seems like a regex may be the best way to parse the effectiveness, but I am deathly afraid of regexes, since I was attacked by one as a child. Anyone know of an efficient regex method to get the relevant integer here, given the string (i.e. "meat")? I have a substring, index_of method already but would be glad of a more effective way.

items 4, meat 5, delevel 1 <-- "delevel" should return 1
 
Last edited:
Code:
string testString = "items 4, meat 5, delevel 1";

int[string] parsed;
matcher m = create_matcher("(\\w+)\\s+(\\d+)", testString);
while (m.find()) {
	parsed[m.group(1)] = to_int(m.group(2));
}

print(parsed["delevel"]);
 
Z, feel free to copy the familiar evaluation code from farm.ash and include it in zlib if it helps. It determines the best familiar programmatically for +meat and +items already. There's some areas that aren't calculated (like meat production) but it's robust if new familiars are added to the game etc.
 
Thanks Jason, that regex is now tucked away safely in ZLib.

That's right, Updates!

As soon bestfamiliars.txt is updated (by the community, I hope, otherwise I'll get to it when I get to it), we'll have ourselves thoroughly useful (and expandable) function in best_fam(). It now allows for prioritizing of familiars, as I posted above. The nice thing about this update is that it allows for the previous data format to still work (as before) -- familiar types do not require an effectiveness ranking (assumed to be 0 in that case), but if it is there, it will be used.

On a related note, can anyone explain to me how this ASH function works?

float numeric_modifier( familiar, string, int, item )

Also added the small tweak to obtain() discussed above.

One other change which may require editing your ZLib-empowered scripts, and for which I apologize: the is_100_run setting makes more sense as a familiar rather than a boolean, so I changed it. It should hold your chosen familiar for your 100% run, or $familiar[none] if you are not doing a 100% run (default).

I'll be using this to add 100%-run policing to BBB.

@dj: thanks for the suggestion, but I think it's too late to go a programmatic-calculation direction with this. People are generally pretty awesome about updating the data files, since they are publicly updateable.
 
I remember that numeric_modifier. Jason added it specifically for the sake of DerDrongo's equipt script.

Revision: 7289
Author: jasonharper
Date: 1:39:30 AM, Friday, May 22, 2009
Message:
Adds a modified version of DerDrongo's patch that implements:
float numeric_modifier(familiar, string, int, item)
which returns the value of a modifier that would apply if the specified
familiar was in use, with the given weight and equipment item.
 
@Z: no problem. Programmatic works particularly well for the +item/+meat problem; less well when you throw the gates wide and try to consider things like lepreghoutoes. Horses for courses and all that. :)
 
Thanks for the update!

I've been wondering how hard it would be for obtain to support "outfit" as a condition? Right now I'm using it like this for outfits:

Code:
foreach itm in $strings[miner's helmet,7-Foot Dwarven mattock,miner's pants]{
  if(!obtain(1,itm,$location[Itznotyerzitz Mine])) abort();
}
 
It might be best if you just added each of the three items as a condition and adventured. That is the same thing as adding the outfit as a condition.
 
That is what obtain does in the code above. It adds the item as a condition and then adventures, but obtain tries to retrieve the item and pull from storage before adventuring. That's why I use it.
 
So, if I understand, what you want is the ability to obtain multiple items at the same time? Perhaps by sending a map of items? There wouldn't be any practical differences in the effectiveness of how it works though.
 
Mafia conditions already support "outfit" (ie condition add outfit). I'm asking if obtain can be altered to support "outfit" for cond just like it supports "choicadv". Then, instead of this:
Code:
foreach itm in $strings[miner's helmet,7-Foot Dwarven mattock,miner's pants]{
   if(!obtain(1,itm,$location[Itznotyerzitz Mine])) abort();
}
one could use:

Code:
if(!obtain(1,"outfit",$location[Itznotyerzitz Mine])) abort();
 
FN Ninja: It's possible, but it reduces the accuracy of the return value. Consider:

Code:
boolean obtain(int n, string cond, location locale) {
   if (cond == "choiceadv") cli_execute("conditions clear; conditions add "+n+" choiceadv");
   else if (cond == "outfit") cli_execute("conditions clear; conditions add outfit");
   else {
      if (retrieve_item(n, to_item(cond))) return true;
      if (!in_hardcore() && storage_amount(to_item(cond)) > 0 && take_storage(n-have_item(cond),to_item(cond)))
         return true;
      cli_execute("conditions clear");
      add_item_condition(n - have_item(cond), to_item(cond));
   }
   set_location(locale);
   if (adventure(my_adventures(), locale)) return error("Out of adventures.");
   if (cond == "choiceadv" || cond == "outfit") return (my_adventures() > 0);
   return (have_item(cond) >= n);
}

That uses mafia's auto-translation of "outfit" to the appropriate items, but the return value is only accurate if mafia stops adventuring due to satisfied conditions or being out of adventures. If mafia stops due to you getting beaten up and the zone no longer being available, for example, the return value of true would be inaccurate. I'd rather the function be less script-breaking-able than that.

Also note that this sidesteps the pulling from storage, etc.

A more accurate method would be much larger than doing things the way you're currently doing them.
 
I see that now. Yet another hitch - I've been looking around for a way to return the outfit name associated with the locale to be able to use cli_execute("pull outfit xyz"); but it looks like a map would have to be added for that. Anyways, thanks for looking into it. I just thought it might be nice, but it's definitely not worth reducing the accuracy of the return value.

P.S. Since update 7 obtain has been playing so much nicer with my scripts! It's beautiful!
 
I'm preparing to update the bestfamiliars.txt with some combat familiars and with some ranking numbers, but before I get carried away I have a few questions:

1)Should the "delevel" type be divided into two types. One for Barrrnacle-like (delevels at beginning of combat) and one for Skeleton-like (delevels during combat)? If so, what should the new types be called?

2)
Numbers should be chosen with a bit of room in between to allow room for future expansion.
Is 5 increment numbering enough for future expansion?

3)Because there exist various damage formulas for combat familiars should we add different types for different formulas or just decide what formulas are best and rank those higher under one type? Right now I'm leaning towards the latter.

4)
In addition to the types that already exist:
delevel
stat
produce
meat
items

I'm thinking if adding these:
combat - damages enemy
dodge - prevents enemy attacks
absorb - absorbs damage
restore hp - restores hp
restore mp - restores mp
stasis - restores mp or hp during combat (not sure if this is needed or even wanted. It could also be divided into stasismp & stasishp)
water - can breath underwater
Any suggestions, objections, comments?
I was going to use just "mp" and "hp" for restores mp and hp but to_familiar("mp"); returns Jumpsuited Hound Dog so to keep it consistent rather than using hp & restore mp I have them both with restore.

Edit: Oh yeah, and this one. I forgot Z wanted it.
elemental damage - does elemental damage
 
Last edited:
1) I'd say keep them together. I can't see much practical reason for separating them.

2) Yes.

3) Keep them together. It would be annoying to have to check two categories in a script.

4) Nice! Those types look good. I don't see the stasis category as being necessary. And for combat familiars, assigning numbers would be tricky. For elemental damage I was planning on basing the efficacy number on the average damage dealt at 20 lbs. But you couldn't do this for regular combat familiars since there are other factors contributing to desirability.

Thanks a lot for your help!

Anyone else contributing: make sure to update your file from the server (which only happens when the function is called) before editing the file and uploading a new one.
 
Okay, bestfamiliars.txt has been updated! :D It now has the vast majority of familiars. I ended up not including an absorb type. So the current type options are:

delevel, stat, produce, meat, items, combat, dodge, restore hp, restore mp, water, elemental damage

I wasn't sure how a few familiar mechanics worked so I left them without a ranking in most instances(Mutant Gila Monster, Teddy Bear, Gluttonous Green Ghost, El Vibrato Megadrone). The combat ranking was particularly hard and will probably need to be altered by someone who understands a few of the formulas a little better, but it's a definitive leap in the right direction! ;) I think the elemental damage resistance is fairly good except I wasn't sure on the Grue ranking. Anyways, here's a copy of what I added sorted by type and rank so as to easily identify any ranking changes that should be implemented.
 

Attachments

Sigh. If you read the changelog, you would see that function has been added to mafia, thus removed from ZLib. If you didn't read the changelog, but downloaded a recent daily build before making that report, you wouldn't have noticed anything wrong.
 
Or maybe you should just post a big red warning label in the thread for those who weren't following our discussion in the feature request forum.

Warning: You need to update to a daily build of KolMafia when you update zlib or else some scripts will stop working.
 
Back
Top