Page 1 of 23 1 2 3 11 ... LastLast
Results 1 to 10 of 229

Thread: PriceAdvisor: Maximize your profits

  1. #1
    Senior Member
    Join Date
    Feb 2009
    Posts
    182

    Default PriceAdvisor: Maximize your profits

    PriceAdvisor 1.62

    PriceAdvisor requires SmashLib and ZLib, and daily build 7915 or greater (13.8 will work).

    Have you ever looked at your inventory and wondered, What's the most meat I could make with this item? Are you chafing at the confines of comparing mallsell to autosell? Do you wish you could price out every possiblity -- crafting, smashing, using, etc. -- without searching for prices for all of the possible ingredients and results? Doesn't this seem like the sort of boring calculation that a script might excel at? (At which a script might excel?)

    That's what PriceAdvisor does. Taking your skills and the opportunity cost of other ingredients (plus chef/bartender uses, adventures, etc.) into account, it calculates the maximum profit you can make from an item. And it tells you exactly how to make it. Use an item? It tells you what to do with the results, too. And it gives you the profit and actions to take for any other action (even those that result in negative profit, if you have your ZLib verbosity at 4 or greater), in case you don't like the advice it thinks is best.

    For example, at the time of posting, this is the advice for a Penultimate Fantasy Chest:

    Code:
    Penultimate Fantasy chest:
    mallsell 1 Penultimate Fantasy chest: 1310.0 meat
    use Penultimate Fantasy chest; acquire 1 cocoa eggshell fragment; make 1 large cocoa eggshell fragment; 
    acquire 1 large cocoa eggshell fragment; make 1 cocoa egg; acquire 1 spooky wad; make 1 Spooky Surprise Egg; 
    mallsell 1 Spooky Surprise Egg; autosell 1 phonics down; mallsell 1 scroll of drastic healing; 
    autosell 1 soft green echo eyedrop antidote; autosell 1 super-spiky hair gel; autosell 1 tiny house: 1040.7269 meat
    autosell 1 Penultimate Fantasy chest: 108.0 meat
    PriceAdvisor considers autoselling, mallselling, pulverizing, untinkering, malusing, cooking, cocktailcrafting, smithing, stilling, jewelrycrafting, using, multi-using, stars, pixels, supertinkering, and sugar-folding. It does not currently consider zapping. Moreover, it will not consider anything you cannot currently do because you lack the skill or access to the equipment or are the wrong gender. Except pulverizing and malusing, because wadbot's pretty darn easy to use.

    PriceAdvisor has three settings which you can set via CLI after running PriceAdvisor at least once. They all default to false.
    zlib priceAdvisor_obeyPriceLimit = true : Forces PriceAdvisor to never recommend doing anything where an ingredient costs more than your Mafia autoBuyPriceLimit setting.
    zlib priceAdvisor_conservative = true : Is even more conservative -- PriceAdvisor will never recommend doing anything where an ingredient is not either a) available from an NPC or b) available for minimum price in the mall
    zlib priceAdvisor_CLIexecutable = true : Forces PriceAdvisor to only output advice that is executable in the CLI. You'll probably only want to use this if you're using PriceAdvisor in another script.

    For Scripters:
    PriceAdvisor uses historical prices to minimize server hits, and also caches its own decisions, so it is most efficient when used within a script. Its main purpose within a script is to serve as a more-sophisticated valuation than simple mallsell vs. autosell can be. (If only that comparison is desired, however, all relevant functions take a boolean consider_more that can be set to false to prevent considering anything more than mall or autosell.)

    The basic data structure is the price_advice record, which contains a string action and a float price.

    price_advice best_advice(item it, boolean consider_more) : Returns only the most profitable price_advice.

    price_advice [int] price_advisor(item it, boolean consider_more) : Returns all advice with > 0 profit, sorted from best to worst (keys 0 to count-1).

    price_advice max(price_advice a, price_advice b) : Returns a copy of the price_advice with higher price. Returns a copy of a if there's a tie.

    void clear_advice_cache() : resets the internal advice caches


    Both best_advice() and price_advisor() are overloaded to take multiple items:
    price_advice [item] best_advice(boolean [item] its, boolean consider_more)
    price_advice [item] [int] price_advisor(boolean [item] its, boolean consider_more)


    print() has been overloaded in a few handy ways:
    void print(price_advice advice)
    void print(price_advice [int] advice)


    PriceAdvisor also contains some maps of interest:
    float [item] meat_use : the expected value of using an item, in meat; you can also load this from use_for_meat.txt, available via MapManager.

    float [item] [item] item_use : the expected value of getting an item from using an item. This is mainly loaded from use_for_items.txt, available via MapManager, but some items with conditional results (Frat Army FGF, Hippy Army MPE, etc.) are only calculated and added within PriceAdvisor.

    string [item] [item] ingredients : map from ingredient to concoction and concoction type (see concoctions.txt in Mafia data files). This serves as a complement to Mafia's get_ingredients(), and like get_ingredients() it does not contain things that you can't do. Except for smashing and malusing, because you can always have wadbot do that.

    Scripts using PriceAdvisor extensively are encouraged to add the lines
    cli_execute("update prices https://zachbardon.com/mafiatools/updateprices.php?action=getmap");
    cli_execute("update prices https://nixietube.info/mallprices.txt");

    at the beginning of said script to use shared price data, and the line
    cli_execute("spade prices https://zachbardon.com/mafiatools/updateprices.php");
    at the end to share gathered price data.

    For Users:
    PriceAdvisor can be called by creating this handy alias:

    alias pa => ash import <PriceAdvisor.ash> print(price_advisor($items[%%], true))

    The alias allows you to list several items at once at get PriceAdvisor's advice for each. For example, pa spring, sprocket, cog is a valid use (although the advice is pretty boring).

    In response to the question "How can I get PA to tell me about a whole class of items", That FN Ninja came up with this alias:

    alias pam => ash import <PriceAdvisor.ash> foreach itm in $items[] if(contains_text(to_string(itm),"%%")) print(price_advisor(itm, true))

    It will report on all items which share the string you give it: pam tiny plastic will tell you about all tiny plastics.

    If you use PriceAdvisor extensively, I encourage you to add the lines
    cli_execute("update prices https://zachbardon.com/mafiatools/updateprices.php?action=getmap");
    cli_execute("update prices https://nixietube.info/mallprices.txt");

    to your breakfast/login script to use shared price data, and the line
    cli_execute("spade prices https://zachbardon.com/mafiatools/updateprices.php");
    to your pajamas/logout script to share gathered price data.


    Disclaimer: PriceAdvisor can't think for you. It can only do the math, and is limited by Mafia's customary mallprice == price of the fifth item available, which may be unrealistic for expensive or rarely-sold items. It's your responsibility to determine if its advice is realistic.

    Version history:
    1.62: cli-executable "trade gloomy for oily" (from heeheehee); updated to use awesome new load_current_map() from ZLib 14
    1.61: improved regex from xKiv, fixed bug where container-keys were being valued at negative opportunity cost
    1.6: added _obeyPriceLimit, _conservative, and _CLIexecutable vars; renamed best_advice cache -> best_cache, best_price() -> best_advice(), smashed_advice() -> smash_advice(); changed boolean parameter of smash_advice() to just be consider_more; now using currently_considering[] for all infinite recursion and circular op. cost prevention; fixed best_cache to cache based on consider_more; invalid sub-results now invalidate final result; fixed final == starting to recognize the first sell in an action; now using xKiv's regex in replace_with_multiple(); best_advice() returns newly-constructed price_advice so return value can't mess with cache. Whew.
    1.51: bug fixes: final product = starting item, trying again; added vodka as a fermenting powder booze; fixed some result-is-multiple issues
    1.5: really eliminated final product = starting item (I hope); switched to vprint() -- negative prices displayed only at verbosity 4+; switched to CLI-executable output
    1.42: eliminated recommendations where final product = starting item, cleaned up some artifacts resulting from item_use entries overlapping with SUSE entries
    1.41: clearer "do x times" advice for results dealing with multiples of an item
    1.4: added handling of usable-items-that-require-something-else-and-produce-more-than-one-thing; added better output for items that have no autosell value but sell for min mallprice (so aren't worth selling)
    1.3: changed fix for circular opportunity costs so it doesn't block legitimate further consideration; changed opportunity cost for autosell-valued items to be mallsell if you have to buy them; eliminated a few non-results from printing
    1.2: fixed bug in max(), added consideration of untinkering, added detection of clockwork servants; now displays actions with negative profit
    1.11: added trading gloomies for oily goldens, malusing elemental nuggets for wads (transmutation was interfering)
    Attached Files
    Last edited by aqualectrix; 01-23-2010 at 10:17 PM. Reason: 1.62

  2. #2
    Senior Member That FN Ninja's Avatar
    Join Date
    Jun 2009
    Location
    Right behind you!
    Posts
    372

    Default

    Very nice!
    TraFa - Training Familiars the Mafia way! queen_cookie.ash - Get your queen cookies.
    TurTa - Turtle Taming the Mafia way! hatter.ash - Mad Hatter buffs.
    DwaFa - Dwarven Factory puzzle solver.
    Miner - Automated ore mining.

  3. #3
    Developer
    Join Date
    Nov 2008
    Location
    Paris, France
    Posts
    4,510

    Default

    I was very impressed with your script, and tried it out with a gloomy black mushroom, hoping to see it output the gloomy mushroom wine.

    Code:
    > pa gloomy black mushroom
    
    Searching     for "chef-in-the-box"...
    Searching for "himalayan hidalgo     sauce"...
    Searching for "one-winged stab bat"...
    Searching     for "rewinged stab bat"...
    Searching for "twinkly nuggets"...
    Searching     for "frogade"...
    Searching for "squashed frog"...
    Searching     for "banana smoothie"...
    Searching for "oil of expertise"...
    Searching     for "cherry bomb"...
    Searching for "skewered cherry"...
    Searching     for "sangria del diablo"...
    Searching for "blatantly     canadian"...
    Searching for "twinkly powder"...
    Searching     for "frost™ brand sword"...
    Searching for "foon of     frigidity"...
    Searching for "basic meat foon"...
    Searching     for "foon of fearfulness"...
    Searching for "spooky powder"...
    Searching     for "phial of spookiness"...
    Searching for "foon of     fleshiness"...
    Searching for "glistening staff"...
    Searching     for "phial of sleaziness"...
    Searching for "dripping meat     staff"...
    Searching for "foon of foulness"...
    Searching     for "phial of stench"...
    Searching for "stench nuggets"...
    Searching     for "foon of fulmination"...
    Searching for "hot powder"...
    Searching     for "flaming cardboard sword"...
    Searching for "phial of     hotness"...
    Searching for "cardboard sword"...
    Searching     for "phial of coldness"...
    Searching for "styrofoam sword"...
    Searching     for "brine"...
    Searching for "briny vinegar"...
    Searching     for "ghostly pickling solution"...
    Searching for "ghost     pickle on a stick"...
    Searching for "vinegar"...
    Searching     for "grogtini"...
    Searching for "skewered lime"...
    Searching     for "bodyslam"...
    Searching for "digital key lime"...
    Searching     for "star key lime"...
    Searching for "cranberry cordial"...
    Searching     for "gnollish autoplunger"...
    Searching for "useless     powder"...
    Searching for "basic meat crossbow"...
    Searching     for "bubble bauble bow"...
    Searching for "basic meat     helmet"...
    Searching for "barskin tent"...
    Searching     for "spooky staff"...
    Searching for "basic meat fez"...
    Searching     for "fez of etymology"...
    Searching for "clown wig"...
    Searching     for "demon-horned hat"...
    Searching for "demonskin     trousers"...
    Searching for "tighty whiteys"...
    Searching     for "raspberry beret"...
    Searching for "cardboard staff"...
    Searching     for "flypaper staff"...
    Searching for "extreme meat staff"...
    Searching     for "extreme meat crossbow"...
    Searching for "balloon     helmet"...
    Searching for "balloon monkey"...
    Searching     for "balloon shield"...
    Searching for "balloon sword"...
    Searching     for "forest tears"...
    Searching for "pestoblade"...
    Searching     for "starchy staff"...
    Searching for "poutine pole"...
    Searching     for "styrofoam staff"...
    Searching for "starchy crossbow"...
    Searching     for "curdflinger"...
    Searching for "cottage"...
    Searching     for "fancy schmancy cheese sauce"...
    Searching for "giant     cheesestick"...
    Searching for "kentucky-fried meat staff"...
    Searching     for "rat appendix"...
    Searching for "secret blend of herbs     and spices"...
    Searching for "kentucky-fried meat crossbow"...
    Searching     for "potato pistol"...
    Searching for "dense meat crossbow"...
    Searching     for "savory crossbow"...
    Searching for "goulauncher"...
    Searching     for "dense meat sword"...
    Searching for "super magic power     sword x"...
    Searching for "wad of tofu"...
    Searching     for "soylent staff"...
    Searching for "savory staff"...
    Searching     for "meat face"...
    Searching for "lifeless meat doll"...
    Searching     for "wooden figurine"...
    Searching for "heavy hot sauce"...
    Searching     for "5-alarm saucepan"...
    Searching for "bjorn's hammer"...
    Searching     for "seal tooth"...
    Searching for "spaghetti with     rock-balls"...
    Searching for "pasta of peril"...
    Searching     for "petrified noodles"...
    Searching for "stone banjo"...
    Searching     for "disco banjo"...
    Searching for "banjo strings"...
    Searching     for "dueling turtle"...
    Searching for "stone turtle"...
    Searching     for "mace of the tortoise"...
    Searching for "chisel"...
    Searching     for "perfume of prejudice"...
    Searching for "ratgut"...
    Searching     for "vesper"...
    Searching for "skewered jumbo olive"...
    Searching     for "dirty martini"...
    Searching for "oil of slipperiness"...
    Searching     for "floaty rock"...
    Searching for "rock lobster"...
    Searching     for "wok lobster"...
    Searching for "enchanted eyepatch"...
    Searching     for "clockwork pirate skull"...
    Searching for "pirate zombie     head"...
    Searching for "pirate zombie robot head"...
    Searching     for "zombie pineal gland"...
    Searching for "clockwork     bartender head"...
    Searching for "clockwork     bartender-head-in-the-box"...
    Searching for "clockwork     bartender-in-the-box"...
    Searching for "4-d camera"...
    Searching     for "chef skull"...
    Searching for "chef-skull-in-the-box"...
    Searching     for "clockwork chef head"...
    Searching for "clockwork     chef-head-in-the-box"...
    Searching for "clockwork     chef-in-the-box"...
    Searching for "clockwork detective skull"...
    Searching     for "hemp string"...
    Searching for "beach glass bead"...
    Searching     for "peace-sign necklace"...
    Searching for "clay peace-sign     bead"...
    Searching for "phat turquoise bracelet"...
    Searching     for "phat turquoise bead"...
    Searching for "spooky pirate     skeleton"...
    Searching for "bone rattle"...
    Searching     for "nothing-in-the-box-in-the-box"...
    Searching for     "present"...
    Searching for "wrapping paper"...
    Searching     for "crimbo hat"...
    Searching for "crimbo pants"...
    Searching     for "crimbo sword"...
    Searching for "boxing glove"...
    Searching     for "banana spritzer"...
    Searching for "bitter pill"...
    Searching     for "cocoa egg"...
    Searching for "concoction of clumsiness"...
    Searching     for "cordial of concentration"...
    Searching for "eyedrops of     newt"...
    Searching for "eye of newt"...
    Searching for     "eyedrops of the ermine"...
    Searching for "libation of     liveliness"...
    Searching for "oil of oiliness"...
    Searching     for "decaying goldfish liver"...
    Searching for "ointment of     the occult"...
    Searching for "papotion of papower"...
    Searching     for "philter of phorce"...
    Searching for "potion of     potency"...
    Searching for "salamander slurry"...
    Searching     for "salamander spleen"...
    gloomy black mushroom:
    acquire     1 spooky fairy gravy; cook 1 gloomy black mushroom, 1 spooky fairy gravy;     autosell pregnant gloomy black mushroom: 83.333336 meat
    I understand the 'autosell pregnant gloomy black mushroom' (item isn't malleable).
    I don't really understand why it searched so many unrelated item prices...
    The gloomy mushroom wine is ~20k, and the fermenting solution is 12,5k, but it doesn't seem like mixing the mushroom was even considered (the alias points to price_advisor(), not the best_price()).

    I learned a lot reading the script, and I hope this output helps a little to get rid of special cases that weren't considered.

  4. #4
    Senior Member
    Join Date
    Feb 2009
    Posts
    182

    Default

    It searches for so many other items because of the way it handles opportunity costs. At least, so I hope. Let's take a look:

    It thinks about making the pregnant mushroom, that's why it looks for chef-in-the-box -- it takes into account the cost of cooking (price of chef / 90, the same way Mafia calculates it).

    As for everything else:
    pregnant gloomy = gloomy + spooky gravy, so it must calculate the opportunity cost of using spooky gravy.
    The only other thing that can be made from spooky gravy is the spooky glove.
    The spooky glove smashes into twinkly or spooky powder. Powders cause a massive cascade of opportunity costs, always. There are many things you can do with them and the other ingredients for those things also have many things you can do with them. It's a good things those prices cache, eh?

    I'm always alarmed when I see these searches too, but I've attempted to debug them and found them to be correct so many times that I just have to squash my impulse to shout "A balloon monkey is not related to this mushroom, dangit!" But it is:
    balloon monkey -> long skinny balloon
    long skinny balloon -> sword of static
    sword of static -> bubblewrap sword
    bubblewrap sword -> basic meat sword
    basic meat sword -> styrofoam sword
    styrofoam sword -> Frost brand sword
    Frost brand sword -> cold powder
    cold powder -> phial of coldness
    phial of coldness -> scrumptious reagent
    scrumptious reagent -> phial of spookiness
    phial of spookiness -> spooky powder
    spooky powder -> spooky glove
    spooky glove -> spooky fairy gravy
    spooky fairy gravy -> pregnant gloomy black mushroom
    pregnant gloomy black mushroom -> gloomy black mushroom
    Pretty insane!

    As for why it didn't tell you to make gloomy mushroom wine, it's simple: the opportunity cost for using the mushroom fermenting powder made the profit < 0, so it didn't mention it. Perhaps there is a more profitable mushroom wine it thinks you should be making instead.

    (At the moment, it is actually telling me to make the gloomy wine; I guess our cached prices differ.)

    One special case that it doesn't consider for the gloomies is trading them in for oily goldens. I think I could incorporate that corner case, even though it doesn't address your actual questions... But I hope I've answered them.
    Last edited by aqualectrix; 12-18-2009 at 01:44 AM.

  5. #5
    Developer
    Join Date
    Nov 2008
    Location
    Paris, France
    Posts
    4,510

    Default

    I guessed there's was some sort of link, but since the spooky glove wasn't an ingredient for anything else I didn't find it. I had forgotten about the smashing =)

    This script should keep the price list pretty much up to date by itself I guess.

    I should try rerunning the gloomy mushroom, but in the output I pasted, only one price-advice was posted (autoselling the pregnant gloomy black mushroom). It seemed like the mixing wasn't considered, or gave a negative profit.

  6. #6
    Senior Member
    Join Date
    Feb 2009
    Posts
    182

    Default

    Exactly. It considered the mixing, but for whatever selection of prices for mushroom wines and mushroom fermenting powder it currently had, decided that the gloomy wine would give you a negative profit.

    Would this sort of thing be more clear if it also displayed options that gave negative profit? That would be very easy.

  7. #7
    Developer
    Join Date
    Nov 2008
    Location
    Paris, France
    Posts
    4,510

    Default

    I thought about the negative profit afterwards, but it's true I was expecting to see 3 price_advices, (however bad). It's my fault for not reading your post carefully enough.

    Code:
    gloomy black mushroom:
    trade gloomy black mushroom to the Suspicious-Looking Guy;
    acquire 1 mushroom fermenting solution;
    mix 1 oily golden mushroom, 1 mushroom fermenting solution;
    mallsell oily mushroom wine: 290.0 meat
    There are now 18 oily mushroom wines in my store =)

    About the 290 meat profit, I now have a more economical question:

    oily mushroom wine: 17,950 meat (from historical_price())
    mushroom fermenting solution: 12,450 meat
    cost of using a bartender: 14,875/90 = 165 meat
    profit = 17,950 - (12,450 + 165) = 5,335 ?

    I'm thinking (guessing) the opportunity cost for making gloomy mushroom wine or a pregnant mushroom got counted in here, but I would have instinctively thought that the profit would be 5,335 meat. Is my vision of the whole concept of profit wrong ?

    Also, since you are very helpful, efficient and seem to enjoy improving your scripts, how about considering clockwork servants ?

  8. #8
    Senior Member
    Join Date
    Feb 2009
    Posts
    182

    Default

    Yeah, to see exactly what's driving the opportunity cost you'd want to do a "pa mushroom fermenting solution" to see how much it thinks it can make with it -- it uses the best_price instead of the mall price to calculate opportunity cost.

    I'd love to include clockwork servants too, but there's no built-in way to check for them. If they were permanent, I could just hit the server and look at your campsite once, then set a zlib setting "bartender_is_clockwork" or something. But innaboxen aren't permanent, and I can't have Mafia magically set that to false when the boxen blow up. So in order to know what sort of boxen you have I would have to hit the server and check every time the script loads.

    That might be acceptable if PriceAdvisor were only imported into other scripts -- it would hit the server only once and then that value could be used to give lots of advice (as long as the other script did no cooking or mixing). But since PriceAdvisor is also handy to use via alias, and is loaded from the start every time the alias is used, it would hit the server every time the alias was used. That seems like too many server hits to me.

    If someone has a clever way around this, or Mafia decides to track your boxen, I'd be more than happy to support clockwork servants!

    I think seeing price_advices come and go as market conditions change is sufficiently unintuitive that it may be worthwhile to list negative profits as well. I'll consider it for the next release.

  9. #9
    Developer jasonharper's Avatar
    Join Date
    Sep 2008
    Location
    Oklahoma
    Posts
    1,122

    Default

    You can tell whether a clockwork or normal servant is currently installed via get_campground(); no server hit required.

    This should always be accurate, except in the case that the servant has just blown up (or has never been installed this ascension), and the user's settings will cause it to be auto-repaired - I'm not sure how you'd predict which kind of servant it would be replaced with.
    In game: Seventh (#363053), originally a Seal clubber. I am the Ap'ostle of Ak'gyxoth! (Or is that Ap'ostrophe?)

  10. #10

    Default

    I'm impressed by the amount of checking the script does; I did a check on Spooky Stick and it checked 554 items before deciding what my best course of action was.

Similar Threads

  1. Replies: 0
    Last Post: 10-30-2013, 05:23 AM
  2. Replies: 1
    Last Post: 01-10-2013, 06:06 AM
  3. Bug - Cannot Reproduce Breakfast freezes at collecting hippy profits
    By Fred Nefler in forum Bug Reports
    Replies: 2
    Last Post: 11-14-2011, 08:19 PM
  4. Maximize.ash, maximize equipment in one command.
    By Paragon in forum Item Handling Scripts
    Replies: 118
    Last Post: 05-05-2009, 02:34 PM
  5. Hippy Produce Stand Profits?
    By Raven434 in forum Community Support
    Replies: 1
    Last Post: 02-16-2008, 10:38 PM

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •