ZLib -- Zarqon's useful function library

atlasica

New member
I just downloaded the latest hourly build, and lo and behold, everything works. Thanks. Was using the weekly build before.
 

Theraze

Active member
The weekly EXE build? That tends to lag behind, sometimes even behind the 1-3 month point releases... Don't use it. Unless you like things failing. :)
 

Raven434

Member
Just started seeing these when I run farm.ash.

Function 'abs( float )' defined multiple times (zlib.ash, line 15)

Version is 10889.
Zlib is r35.
 

Theraze

Active member
Nope... you might have multiple zlibs or something else similar though. Check? I think it was recently-ish changed from returning an int to returning a float.
 

zarqon

Well-known member
I think the int version was actually just removed, since it was pointless.

r36 Update!

I've been finding increasing uses for knowing whether I might need an item for the tower -- not the least of which being BatBrain wanting to throw my stick of dynamite at a monster during the last two runs. So, I decided to move my tower_items() function into ZLib. It returns a boolean[item] map. First, any item your telescope says is required is added to the map with a value of true. Second, any other item you might need (if you have an incomplete telescope) is added to the map with a value of false. Since the function will check your telescope if you haven't yet done so this run, I had to add an optional boolean parameter called "combatsafe" just in case -- specifying this parameter as true will force the function to skip checking your telescope.

I also tweaked load_current_map() so that merely deleting the data file will trigger a reload. You shouldn't have to muck about with zversions.txt.

Also, I just spent a good bit of time updating ZLib's wiki page, bringing it up to date and reformatting somewhat. That page is much more accurate and helpful than previously. Still not finished updating (some of the kmail functions are still missing) but at least all the "not-true-anymore" things were removed. I also think I was able to explain some things better than before. Pop over for a look if you like, you might learn something (especially if you understand English much better than ASH).

Now, who will be the first to report the r36 != integer message this time? It's kind of a fun tradition. :p
 

zarqon

Well-known member
You shouldn't have to add anything. Once I code it, BatBrain will consult this function, and refuse to throw possibly needed tower items.

EDIT: Thanks Winterbay for fixing the tower_items formatting on the Wiki page! I didn't know how to do that.
 
Last edited:

Bale

Minion
You shouldn't have to add anything. Once I code it, BatBrain will consult this function, and refuse to throw possibly needed tower items.

That'll be nice. Then I can remove that protection from DAM. (Yeah, I was already protecting items, albeit in a broad manner.)
 

Winterbay

Active member
You shouldn't have to add anything. Once I code it, BatBrain will consult this function, and refuse to throw possibly needed tower items.

EDIT: Thanks Winterbay for fixing the tower_items formatting on the Wiki page! I didn't know how to do that.

Ok. Then I'll keep it in my local copy for now :)
 

philmasterplus

Active member
This may have been proposed before, but...

Feature Request: Could there be a function that fetches the historical price of an item, guaranteeing that its age is above a certain number? Something like:

historical_price(item it, float age)
mall_price(item it, float age)


The code would be:
PHP:
int historical_price(item it, float age) {
  if (historical_age(it) > age) return mall_price(it);
  return historical_price(it);
}
I've been using this function in several scripts, and probably any script that handles mall prices would benefit from this.
 

zarqon

Well-known member
Would you like something that also returns autosell if the mall price is at minimum? Or would that screw with your scripts and thus be unusable? That's the version I tend to use the most. Could have a function for each, but don't need to kill unnecessary birds. I could see moving something like BatBrain's item_val() up into ZLib, with an added check for historical_age() and an optional "combatsafe" parameter specifying whether or not to allow mall searches.

item_val(item i, [ int expirydays, [ boolean combatsafe ]])

BatBrain's function, for ease of reference:

PHP:
float item_val(item i) {
   if (is_tradeable(i) && historical_price(i) > max(100,2*autosell_price(i))) return historical_price(i);
   if (autosell_price(i) > 0) return autosell_price(i);
   return 50;      // don't allow non-tradeable, non-sellable items to have 0 value
}

My StashBot script uses this:

PHP:
int get_value(item which){
   if (!is_tradeable(which)) {
      print("'"+which+"' is not tradeable.","red");
      return 0;
   }
   if (ivals contains which) return ivals[which];
   if (mall_price(which) > max(100,2*autosell_price(which))) return mall_price(which);
   return (mall_price(which)*2 + autosell_price(which)*3)/5;
}

The ivals map contains things where I want to override the default mall_price, and presently contains things like meat paste/stacks, casino passes, and bowls of cottage cheese. I forget why I added the cottage cheese, but it was evidently overvalued at some point.

I have a consumption script which uses this:

PHP:
float item_expense(item it) {
   switch (it) {
     case $item["fortune cookie"]: if (get_counters("Fortune Cookie",0,250) == "") return -9999999; break;
     case $item["steel margarita"]:
     case $item["steel lasagna"]:
     case $item["steel-scented air freshener"]: if (item_amount(it) > 0) return -9999999; break;
     case $item["boris's key lime pie"]:
     case $item["sneaky pete's key lime pie"]:
     case $item["jarlsberg's key lime pie"]: if (!can_interact() && my_level() < 13 && item_amount(to_item(excise(to_string(it),""," lime"))) == 0) return -999999;
  }
  if (!is_tradeable(it) && is_displayable(it)) return 9999999;
  if (historical_price(it) < 100 || historical_age(it) > priceage) return mall_price(it);
  return historical_price(it);
}

And a zapping script which uses this:

PHP:
float it_val(item which) {
   if (historical_age(which) < 3 && historical_price(which) > 0) return historical_price(which);
   if (mall_price(which) > max(100,2*autosell_price(which))) return mall_price(which);
   return autosell_price(which);
}

So, the first never hits the server, the second usually does, and the last two do more like what you suggested above. Most of them value items which are mall priced at minimum to be actually worth less than that (and the third probably should). I'm thinking taking bits from all of these would give us a pretty nice universal function for ZLib, which I could use to replace or at least reduce all those functions. But I'd like to know up front whether returning autosell for minpriced items would somehow make the function unusable for you.

@Bale: That Stephen Fry thing was absolutely brilliant, thank you for sharing. It actually was so lovely I became ever so slightly lacrimose.
 

philmasterplus

Active member
Good idea, except I would suggest splitting them into several functions so that different scripts can use them. I prefer my utility functions simple and concrete. My utility script contains:

PHP:
# Returns minimum mall price (or 0 if untradeable)
int min_mall_price(item it) {
	if (!is_tradeable(it)) return 0;
	return max(100, autosell_price(it) * 2);
}

# Quick-and-dirty way of determining item value. If the item is untradeable, will simply return fallbackValue instead.
int value_quick(item it, int fallbackValue) {
	if (!is_tradeable(it)) return fallbackValue;
	if (autosell_price(it) > 0 && mall_price(it) == min_mall_price(it)) return autosell_price(it);
	return mall_price(it);
}

Also, the int expirydays should really be a float.
 

eegee

Member
Here's my 2c (pun intended on the method count):
Code:
boolean isMallPriceMinimum(item gameItem) {
	return (historical_price(gameItem) == 100) || (historical_price(gameItem) == (2 * autosell_price(gameItem)));
}

int recommendedSellingPrice(item gameItem) {
	return (isMallPriceMinimum(gameItem) ? autosell_price(gameItem) : historical_price(gameItem));
}
I must add that I do a check on "tradeables" before the above is called, but I also use a variation on the intended helper method(s). Now to find the least amount of methods that are generic enough to suit everyone's fancy. :)
 

Fluxxdog

Active member
Kind of expected with the recent work on floats:
Code:
> ash import <zlib.ash>; rnum(13.0/7.0,2)

Returned: 1.8600000143051147
I've made changes to my local copy of zlib. They're simple, but they work. Thought maybe they could help:
Code:
##Error compensation two posts down##
}
Code:
> ashtest rnum(13.0/7.0)

Returned: 1.86

> ashtest rnum(98024.0/7.0)

Returned: 14,003.43
 
Last edited:

Theraze

Active member
Amusingly, the 898 fix causes problems for the few floats that actually fully resolve, like so:
> ash to_float("1.5")

Returned: 1.5

> ash import <zlib.ash> rnum(1.5, 2)

End index 3 out of bounds (zlib.ash, line 122)
Returned: void
This usually shows up (for me) when BatBrain (in DAM or WHAM) or the BatRelay try to do their calculating work...

Edit: Not the prettiest code I've ever done, but this appears to work, including adding extra digits if needed:
Code:
string rnum(float n, int place) {
   if (to_float(round(n)) == n || place < 1) return rnum(round(n));
   # buffer res;
   # res.append(rnum(truncate(n))+".");
   # if (n < 0 && n > -1) res.insert(0,"-");
   # res.append(excise(to_string(round(n*10.0**place)/10.0**place),".",""));
   # return to_string(res);
   string res=rnum(to_int(excise(n,"",".")))+".";
   int decimal;
   if (length(substring(excise(n,".",""),0)) < place+1) {
      int extraplace = length(substring(excise(n,".",""),0));
      decimal = round(to_float(substring(excise(n,".",""),0,min(length(substring(excise(n,".",""), 0)), place+1))));
      res+=decimal;
      while (extraplace < place) {
         res+="0";
         extraplace+=1;
      }
      return res;
   }
   decimal=round(to_float(substring(excise(n,".",""),0,min(length(substring(excise(n,".",""), 0)), place+1)))/10);
   res+=decimal;
   return res;
}
> ash import <zlib.ash> rnum(1.5, 2)

Returned: 1.50

> ash import <zlib.ash> rnum(1.5, 1)

Returned: 1.5

> ash import <zlib.ash> rnum(1.5, 5)

Returned: 1.50000
 
Last edited:

Fluxxdog

Active member
Yeah, I just found that out after who knows how many thousands of calculations that were automated. I had gone through about 280 adventures using BatBrain. This compensates for it:
Code:
string rnum(float n, int place) {
   if (to_float(round(n)) == n || place < 1) return rnum(round(n));
   # buffer res;
   # res.append(rnum(truncate(n))+".");
   # if (n < 0 && n > -1) res.insert(0,"-");
   # res.append(excise(to_string(round(n*10.0**place)/10.0**place),".",""));
   # return to_string(res);
   string res=rnum(to_int(excise(n,"",".")))+".";
   string dec=excise(n,".","");
   while(length(dec)<place+1) dec+="0";
   string decimal=round(to_float(substring(dec,0,place+1))/10);
   while(length(decimal)<place) decimal="0"+decimal;
   res+=decimal;
   return res;
}
Code:
> ash import <zlib.ash>; rnum(1.5, 2);

Returned: 1.50
 
Last edited:
Top