ZapWizard - Automatically zaps for mall profit

ZapWizard 0.91

When called, ZapWizard determines the most profitable item for zapping. Pending your confirmation, it then acquires the item, zaps it, and places the transmogrified item into your mall store.

REQUIREMENTS
This script uses ZLib.ash
If you don't have it already you can get it from here: Zarqon's Useful Function Library

There's a few ZLib variables to play around with, shown here with their default values.
Change them from the Mafia CLI, like this:
Code:
zlib zapwizard_numberofrecommendations = 3
or use a Relay zlib editor like Heeheehee's one.

The variables are pretty self-explanatory, but I'll explain what each of them does anyway:

numberofrecommendations = 1
Can be increased up to 10 to show a greater number of recommendations, in order of profitability. ZapWizard will only offer to autozap its top recommendation.

volumechecking = true
minvolume = 700

This checks the amount sold of the most expensive group member over the last week, using data from http://kol.coldfront.net
The request to coldfront is only made after all other conditions for recommendation have been met.
If the amount sold over this period is less than minvolume then the group will not be recommended.

minmargin = .2
The minimum profit margin, set to 20% by default. If the margin is lower than this, then ZapWizard will not recommend it. To remove this limit, set to 0.

capitalthreshold = 10000
The maximum meat cost of the cheapest group member, set to 10k meat by default. If the cheapest item in a group is worth more than this amount, then ZapWizard will not recommend it. If you want to completely remove this limit, set to -1. You probably don't want to do that though.

autozap = true
If set to false then ZapWizard won't offer to autozap, and will only give recommendations.

confirmautozap = true
If set to false then zaps top recommendation without requiring user confirmation.

overheat = false
Set to true to stop ZapWizard aborting when your wand is warm.

blowupwand = false
If set to true then ZapWizard will keep zapping until your wand explodes, then automatically set this variable back to false.
This overrides your usual setting for overheat.

completeoutfits = true
If true, attempts to complete aftercore outfits - Hobopolis/SlimeTube/Cursed Pirate - before zapping for profit. Thanks to Zarqon/Sorguon for the help here :)

priceupdateperiod = 7
How many days to wait before rechecking item prices, by default only once every week.​


Version History
0.1 Added version checking, Use ZLib verbosity settings, Improved wand heat checking, Added volume check, Removed option to ignore equipment, Removed tiny plastic commons
0.2 Script was saving a junk zlib variable - "ZapWiz_dumpresults". Removed
0.3 Use "data\mallvolumes.txt" to save historical volumes, and only update if older than 3 days, Improved recommendation algorithm, Switch to using Zlib variables.
0.4 Automised mall pricing, Customisable price update period, Auto outfit completion.
0.5 Parse zapgroups and untradeable zappable outfits from kolmafia data files.
0.6 Option to run without user confirmation. Removed wierd message when zapping to complete outfits.
0.7 Easy wand exploding, better reporting when zapping untradeables.
0.8 Fix typo preventing confirmautozap from working properly
0.9 Fix error that would request multiple zaps even if blowupwand was false. New zapwizard() function for easier importing.


Finally, thank you to Bale - I stole/learnt a lot from your awesome scripts :)
 

Attachments

  • ZapWizard.ash
    14 KB · Views: 74
Last edited:

Bale

Minion
Finally, thank you to Bale - I stole/learnt a lot from your awesome scripts :)

You're very welcome. Take a look at this:

PHP:
zapgroups["Meins - Chow"].members[0]=$item[bat wing chow mein];
zapgroups["Meins - Lo"].members[0]=$item[asparagus lo mein];
zapgroups["Advanced Cocktailcrafting Base Drinks"].members[0]=$item[margarita];
zapgroups["Advanced Cocktailcrafting Final Drinks"].members[0]=$item[a little sump'm sump'm];
zapgroups["Superhuman Cocktailcrafting Base Drinks"].members[0]=$item[caipifruta];
zapgroups["Superhuman Cocktailcrafting Final Drinks"].members[0]=$item[Divine];
zapgroups["Letters"].members[0]=$item[heavy D];
zapgroups["Superhuman Cocktailcrafting Base Drinks"].members[0]=$item[caipifruta];


foreach g,r in zapgroups
	foreach it in get_related(r.members[0], "zap")
		r.members[count(r.members)] = it;

That's just a demonstration of a quick way of filling out several zapgroups if you know a single item in the group.
 
Nice one, thanks. I like the multidimensional foreach, I didn't know you could do that. It makes the code a lot more readable.
I incorporated it into the script, and made a few other changes.

Notably it now checks Coldfront's market data to ensure that the volume sold of the most expensive group member is over a minimum amount. I'm not 100% sure if this is cool though? I've tried to keep the Coldfront spam to the minimum - the server hit is only performed once for each group, after the other conditions for recommendation have been met.
 

fronobulax

Developer
Very interesting idea. Will check it out.

Ethically I think you are all right by hitting Coldfront the minimum number of times possible. If that is too much I'm sure we'll find out. In comparison, I have a script that potentially hits JickenWings several thousand times (once per distinct item in a display case) and they were not concerned enough to discuss whether there was a need for a mitigation strategy.
 
Update to 0.2 - the script was saving a junk zlib var that I'd put in for debug purposes and forgot to remove.

If anyone wants to remove it manually then it's in
\data\vars_<character name>.txt >> "ZapWiz_dumpresults"
 
Update to 0.3 - the script now saves historical mall volumes in "\data\mallvolumes.txt", and only rechecks Coldfront after 3 days have passed. The recommendation algorithm makes better use of array sorting, which cuts out a few extra hits.

Also the variables have been made Zlib vars instead of being set directly in the ASH. There's a small explanation about how to change Zlib vars in the first post.

Also also, the default volume checking value is much stricter now, only recommending relatively high volume items that sell 100 per day or more.
 

fronobulax

Developer
I am having fun with this. I do note that the recommendation has been the same for several days. Since it makes a lot of price checks, I wonder about a mode where it uses historical prices that are younger than a specified age and only checks prices that are too old.

More work then you might want to do but you could also compute a recommendation based upon historical prices and then only look up the specific items involved in the recommendation. At that point all you would care about is whether the recommendation can still be executed within the budget and profit parameters. If this mode is supported then if no recommendation is made the user could just run the script again, knowing that some of the historical price data has been updated and so a different result might be possible.
 

zarqon

Active member
Haha, cool! I already had functionality similar to this in my logout script -- it first checks a priority list (specified per character), then tries to complete outfits, then zaps for highest profit from available items in inventory. Other than zapping for keys during a run, I almost never worry about zapping anymore.

But you've added whole new layers of tweakability to this than are dreamt of in my philosophy. Very cool, congrats!

Also my name has no 'u'. :)
 
fronobulax said:
I am having fun with this. I do note that the recommendation has been the same for several days. Since it makes a lot of price checks, I wonder about a mode where it uses historical prices that are younger than a specified age and only checks prices that are too old.
It does only check prices > 1 day old at the moment, but I hear you - the mall search takes a long time. Both of the changes you suggest would be good additions to the next update.

my name has no 'u'. :)
doh! fixed.
Sorry, I totally mixed you up with the Great Prophet Zarquon :)
 

fronobulax

Developer
Silly me. I just noticed the zapped items were all in my store with a price of 999,999,999. I had assumed that they would be priced at the value that allowed for the calculated profit. Script error or error in my expectations? If the latter, then consider this a feature request - to calculate and set the selling price.

Thanks.
 

zarqon

Active member
Presently, this seems to be slightly outside the scope of your script, but after considering the name ZapWizard, it seems to fall well within bounds. I've really enjoyed it in my zap script so you may be interested in adding some kind of notification or support for it. This function returns which item to zap to attempt to complete outfits or Daily Dungeon keys (only tries to balance keys if you're below level 13). For any zap group that you would like it to equalize, add one item from the group to the item list.

PHP:
item equalizezap() {    // zap to equalize hobopolis outfits & daily dungeon keys
   int[item] ts;
   vprint("Finding equalize zap...","blue",3);
   boolean lacking() { foreach i in ts if (!($items[Boris's ring, Jarlsberg's earring, Sneaky Pete breath spray] contains i) && available_amount(i) == 0)
      return vprint("Lacking zapgroup item: "+i,2); return false; }
   foreach t in $items[boris's key, Ol' Scratch's ash can, Frosty's carrot, Wand of Oscus, Zombo's shield, Chester's cutoffs,
      Hodgman bow tie, cursed eyepatch, hardened slime hat] {
      if (t == $item[boris key] && my_level() > 12) continue;
      ts = get_related(t,"zap");
      if (lacking()) foreach i in ts if (item_amount(i) > 1) return i;
   }
   return $item[none];
}


!!!

The 's' is new.
 

Bale

Minion
I was hoping the 'o' would be new also. Thank goodness I found something original to misspell you.
 
Cool! Thanks for the outfit completion code Zarqon. I've duct-taped it onto a new version - When the zlib variable "zapwizard_completeoutfits" is true, outfit completion will be recommended over zapping for profit.

I've left out DD key completion because the script isn't really intended for use before prism breaking. That involves a lot more tactical choice - tower items, hippy/frat/mining outfits, etc - and that's well outside the scope of the script as it stands.

Fronobulax - in terms of automatically pricing the items that are placed in the mall, I had intentionally left that out to allow for personal choice in setting prices. You're right that it would make sense to have it autoset a reasonable default though, so it now prices at mall_price (equal to fifth cheapest result in the mall).

Also, the new version updates mall prices at intervals set by the user. It only updates prices that are older than a week by default - customisable with the zlib variable "zapwizard_priceupdateperiod". This makes it a lot friendlier to run every day.
 

zarqon

Active member
Oops, there was a bug in my code, which I didn't find until now because I have two Necbromancer's shorts but no other outfit pieces yet. I was expecting it to zap the extra shorts but it didn't. This fixes it:

PHP:
item equalizezap() {    // zap to equalize hobopolis outfits & daily dungeon keys
   int[item] ts;
   vprint("Finding equalize zap...","blue",3);
   boolean lacking() { foreach i in ts if (!($items[Boris's ring, Jarlsberg's earring, Sneaky Pete breath spray] contains i) && available_amount(i) == 0)
      return vprint("Lacking zapgroup item: "+i,2); return false; }
   foreach t in $items[boris's key, Ol' Scratch's ash can, Frosty's carrot, Wand of Oscus, Zombo's shield, Chester's cutoffs,
      Hodgman bow tie, Necbromancer shorts, cursed eyepatch, hardened slime hat] {
      if (t == $item[boris key] && my_level() > 12) continue;
      ts = get_related(t,"zap");
      ts[t] = 1;
      if (lacking()) foreach i in ts { if (item_amount(i) > 1) return i; }
   }
   return $item[none];
}

The important bit is the ts[t] = 1; Without that it will ignore duplicate items in the item list.
 
Actually I noticed and fixed that in my implementation. Sorry, I should probably have pointed that out at the time.

Also, I've not been playing KoL for a couple of weeks, so your post made me go
What the hell are Necbromancer's Shorts? Meh probably some kind of crappy halloween contenOMG NEW CLAN DUNGEON!!! :O
 
Last edited:
So a year and a bit after writing this script I'm still getting the odd kmail from people using it, which is nice :)

The new update parses stuff that can be zapped (and non-tradeable outfits that can be zapped) from mafia's data files, so the script won't need updating as new stuff gets released.
 
Top