EatDrink.ash: Optimize your daily diet (and see how your old diet stacks up).

fronobulax

Developer
Staff member
Theraze's code posted above has several changes compared to the version I am maintaining. Reconciling them is on my "ToDo" list.
 

Ferdawoon

Member
I have not really checked how EatDrink work, how the script get the items it want me to eat and/or drink, and considering there seemed to be a lot of different settings I go all out and simply just ask, with the risk of looking silly.

How do EatDrink get the food and booze and spleen items for me? Is it only buying it from the mall? Do it get it from my inventory if I have the proper item? Will it craft the item if it can?

When it is searching to check prices, estimate values and decide what to consume, it seem to only search for the finished product. Would it make the script much slower (and as such an unwanted change) if it would check the price of the components as well and if cheaper, craft the item instead of buying the finished product from the Mall?
 

fronobulax

Developer
Staff member
I'm not sure how well this answers your question but..

EatDrink will create, buy or pull from clan stash based upon mafia settings. The script has its own logic for pulling from Hagnk's. In general the mafia settings will do whatever is cheapest. What confuses people is that there are times when it leaves more meat in your inventory to buy an item from the mall and sell the ingredients in your inventory than to craft it. There are times when, according to mall prices, the whole costs less than the sum of its parts and mafia will take that into account when making a craft or buy decision.

EatDrink also has some price flexibility. If it thinks something is a good deal at 1000 meat and the flexibility is 1.25 then it will be willing to acquire the item at 1250 or less rather than try something else.

OK?
 

Ferdawoon

Member
Yup, sounds like what I wanted it to do, just that it was not obvious from just glancing at the CLI printouts =)

Say it want me to eat a crimbo pie: Instead of just searching for Crimbo Pie in the mall and if it is there at the right price, get it, I want the script to check the price for Gnollish Pie Tin, Wad of dough, Pie crust, Plum and Crimbo Pie, to see what is cheapest to do, buy the parts (or use them from my inventory) and craft it from some step in the recipie or just get the finished item.
 

Theraze

Active member
It'll do that already... Currently, as I'm playing through BM ascensions, my usual early food-management step is making sure I get the bugbear outfit. Once I get that, it'll make bean burritos, pies, or whatever... until that, I'm basically stuck eating whatever finished items I get from drops, which means lots of days wasted eating just haunted kitchen or ballroom drops...

On my person sitting in aftercore due to Crimbo, they'd be getting significantly better stuff, including automatically using milk and ode. If I weren't being cheap and just doing milk/ode manually before using the cafeteria food. :)
 

fronobulax

Developer
Staff member
What Theraze said.

What you are asking for is a smart version of the CLI command acquire. EatDrink doesn't use it directly but does duplicate the functionality.
 

JohnDoe244

New member
There's a couple of questions I'm having trouble finding the answer for. I'm sure the answers are somewhere in this thread, but I'm hoping that someone knowledgeable will be able to save me from trawling all 60-odd pages.

1. When you set the value of adventure is the logic:

I am willing to spend "x" on getting one more adventure. Build a diet that gives me the most adventures in a day, spending upto "x" per adventure.

Or is it:

I can make "x" meat per adventure. Build a diet that makes me the most meat in a day.

2. Is the var that determines whether or not the script actually eats and drinks for you or just displays a diet for you to view "eatdrink_simConsume"? And if set to "true" does that mean the script will actually eat or does it mean that it's just simed?

3. What's the latest version of this script? Just cribbed Theraze's version back on page 60... but for some reason it's got me eating chow miens, which I don't think is optimal by any definition... could be though...
 

Winterbay

Active member
1) It sets the amount of meat you are willing to spend in order to gain 1 more adventure
2) If simConsume = true it will simulate only. So you need to set it to false for it to eat anything.
3) Not sure :)
 

fronobulax

Developer
Staff member
Maybe I'm saying the same thing as Winterbay or maybe I am just so mesmerized by the bunny and cookie that I cannot think.

EatDrink converts everything to meat. valueOfAdventure (or whatever the preference is) is used to convert the "yield" of food to something that can be compared to the cost of a food. EatDrink then looks at the cost and yield per fullness to make its choices. I could be confused but that doesn't seem to be quite as simple as saying "I will spend valueOfAdventure more meat to get one more adventure when comparing two candidate items". We may be getting off into economics (marginal utility) or calculus (derivative) when the question is phrased in terms of an increment which is why the answer is not obvious to me.

The latest version of EatDrink is here to the extent that my Unofficial support is official. Theraze's version has some changes I have not incorporated and there is a version by Bale with some changes as well. While updating EatDrink is on my personal ToDo list, so is writing a variation where it is much clearer what is going on. I really need to devote some cycles to one of those tasks :)
 

Theraze

Active member
Here's another update to EatDrink that should just remove its desire to add in zlib variables for every item consumed. Especially since zarqon said that every zlib variable is loaded and considered every time anything with zlib is called... As it stood, my vars_Theraze (and so on) file was bloating to almost double size due to all of the different items consumed throughout ascensions...
 

Attachments

  • EatDrink.ash
    60.1 KB · Views: 41

lostcalpolydude

Developer
Staff member
1. When you set the value of adventure is the logic:

I am willing to spend "x" on getting one more adventure. Build a diet that gives me the most adventures in a day, spending upto "x" per adventure.

Or is it:

I can make "x" meat per adventure. Build a diet that makes me the most meat in a day.

These are the same thing. If an adventure is worth X to you (being able to make X meat, having Y chance at a hobo nickel drop, whatever), then any amount less than X is worth spending on another adventure.
 

slyz

Developer
I had misread, I thought the choice was between "I am willing to spend x on getting one more adventure" and "I am spending on average X meat per adventure".
 

Theraze

Active member
Both are the same. If you are willing to spend 500 (default) to get 1 more adventure, you're spending on average (up to, but not over) 500 meat per adventure. Maybe less, but if there's an option that costs 500 per adventure and will get you 15 total more adventures, that's a good option if you're making ~600 per adventure... Note that it will take that much, or less... White Canadians are often pulled from the barrels, but EatDrink will usually skip them because the cost often hovers over the value per adventure, and since I'm in HC BM I still have inventory considerations taken into account...

According to the optimal diet lists site, in the 500 per adventure range you're looking at spooky lo meins as your food, so if that's what EatDrink pulled, you're getting exactly what you should. The 500 'per adventure cost' diet, at least when I looked today:
3x spooky lo mein [1466 meat]
1x Crimbo pie [399 meat]

4x rockin' wagon [1372.8 meat]
1x dusty bottle of {fantastic wine} [330 meat*]
1x can of Swiller [238 meat]
1x rockin' wagon [1372.8 meat]

15x twinkly wad [321 meat]
Should provide ~157.5 adventures, at a cost of 17k, at a profit of 35k-77k.
 

xKiv

Active member
These are the same thing. If an adventure is worth X to you (being able to make X meat, having Y chance at a hobo nickel drop, whatever), then any amount less than X is worth spending on another adventure.

Wrong. Consider this example:

value of adventure = 1000
choice of two consumables: one costs 100 meat and generates 1 adventure, the other costs 10000 meat and generates 10 adventures.
(and you can consume exactly 1 of eighter)

Under option 1 (get as many adventures as you can), you will choose the other, and get exactly zero profit (not counting the adventures you would get anyway: -10k to get the consumable, +10k from value of the generated adventures).
Under option 2 (maximize total profit), you will choose the first one, generate 1 adventure, pay 100 meat, get 1000 meat, profit = 900 meat which is better than option 1's zero.

The difference is that #1 basically disregards values of anything other than the adventures themselves (mpa per size), while #2 also considers cost of consumables.


ETA:
in other words:
#1 is: find a diet D that maximizes ( valueOfAdventure * adventures(D) ) while cost(D) <= valueOfAdventure * adventures(D)
#2 is: find a diet D that maximizes ( valueOfAdventure * adventures(D) - cost(D) ) while cost(D) <= valueOfAdventure * adventures(D)
(I can add that "while" condition in case #2 because it doesn't do anything there - it's equivalent to valueOfAdventure * adventures(D) - cost(D) >= 0, and since the empty diet has cost=0 and adventures=0, the maximizing diet will have at least as much)
EatDrink does #2, otherwise it would always tell me to eat knob pasty and drink the coffee (until they would shoot above 7500 ...).
 
Last edited:

fronobulax

Developer
Staff member
While the name "valuePerAdventure" suggests something to do with farming, as far as I can sort things out EatDrink does not actually take into account what might possibly be gained by spending an adventure. The whole construct is to reduce the value to the player of consuming something to a single number. Once the yield has been expressed as a single number (in meat) it is fairly easy to compare the yield of an item to the cost of an item and decide which items are better than others.

If valuePerAdventure is 500 then you, the player are saying that an item priced at x and yielding y adventures is the same to you as another item priced at x+500 and yielding y+1 adventures. That means EatDrink would choose between them based upon fullness and acquisition costs.

If you are the right kind of math geek you should be aware that EatDrink really is not optimizing your diet in the a strict sense. The problem of maximizing the number of adventures generated subject to constraints on fullness and available meat would be solved as a linear (integer) program and would simultaneously consider all foods to generate a real optimum. EatDrink merely orders items and then keeps trying to consume the best one which can come close but can be shown to be sub-optimal.
 

xKiv

Active member
If valuePerAdventure is 500 then you, the player are saying that an item priced at x and yielding y adventures is the same to you as another item priced at x+500 and yielding y+1 adventures. That means EatDrink would choose between them based upon fullness and acquisition costs.
It's also saying (in #2) that an item priced at x+100 and generating y+2 adventures is better than an item priced x+900 and generating y+3 adventures.
#1 would pick the second one, because it would consider +3 adventures (each costing less than 500) is more than +2 adventures (each costing less than 500).
#2 picks the first one because it would pay 800 meat to generate 500 meat, causing 300 meat loss.

I still maintain that EatDrink aims for #2, or it would have told me to eat much more expensively (with my valueOfAdventure=1000, it would always tell me to huff prismatic wads over twinkly wads, for example).

If you are the right kind of math geek you should be aware that EatDrink really is not optimizing your diet in the a strict sense.

It's using an approximation scheme, but the problem is still of the form "maximize { objective_function(x) where constraints(x) }"



BTW, neighter of these two approaches is what I would like for, say, limited content, where I want #3:
find diet D that maximizes { adventures(D) } where cost(D) <= given amount A

(you don't know what your valueOfAdventure for this is, because you don't already know how many adventures you can get for A meat ... if you pick too high, you may get a solution that costs too much; if you pick too low, you might miss an expensiver diet that would still fit inside A meat)

ETA: in a stict optimization, that could be probably handled by setting very high valueOfAdventure *and* futher constraining what a diet is (where it now checks for total fullness, it would have to check for total fulness and total cost). Would be more complicated (and possibly result in a solution futher away from optimum) in a greedy algorithm.
And bisecting is right out - far too slow.
 
Last edited:

fronobulax

Developer
Staff member
I still maintain that EatDrink aims for #2, or it would have told me to eat much more expensively (with my valueOfAdventure=1000, it would always tell me to huff prismatic wads over twinkly wads, for example).
Curiously, when I changed vOA from 500 to 1000 my diet changed dramatically and furthermore it varied with mall prices.
It's using an approximation scheme, but the problem is still of the form "maximize { objective_function(x) where constraints(x) }"
But I can prove that approximation is suboptimal. That should be clear if you just note that the approximation only considers one item at a time rather than solving the simultaneous system. Do I have to dig out an Operations Research textbook? ;-)
BTW, neighter of these two approaches is what I would like for, say, limited content, where I want #3:
find diet D that maximizes { adventures(D) } where cost(D) <= given amount A
Curiously I also find the problem formulation less useful when adventures are deemed convertible to meat. Maximizing the number of adventures generated subject to fullness and a meat budget is the formulation I am using in my EatDrink alternative. Since I am not going to embed a generalized linear program solver in KoLmafia or write one in Ash or extend Ash so that it can access an online solver I will use a "pick the best available item until a constraint is hit" algorithm and favor ease of implementation over mathematical optimality.
 

xKiv

Active member
Curiously, when I changed vOA from 500 to 1000 my diet changed dramatically and furthermore it varied with mall prices.
Yes, it will do that. It will still not pick consumables that cost 1000 meat per adventure generated, which is what it would have to if it was doing #1.
(come on; mine is telling me to eat spooky lo meins - that's not even 2k meat, for some 17.5 adventures; if it was really suggesting to spend 1k meat to generate 1 adventure, it would tell me to eat .. I don't know ... but it would definitely have to pick 4 knob pasties over that (still currently less than 1k meat/adv generated, but would generate over 30 adventures).

But I can prove that approximation is suboptimal. That should be clear if you just note that the approximation only considers one item at a time rather than solving the simultaneous system. Do I have to dig out an Operations Research textbook? ;-)

That's irrelevant to the underlying problem. (where that = difference between "getting an optimal solution" and "getting a solution that is just close enough").

Curiously I also find the problem formulation less useful when adventures are deemed convertible to meat. Maximizing the number of adventures generated subject to fullness and a meat budget is the formulation I am using in my EatDrink alternative. Since I am not going to embed a generalized linear program solver in KoLmafia or write one in Ash or extend Ash so that it can access an online solver I will use a "pick the best available item until a constraint is hit" algorithm and favor ease of implementation over mathematical optimality.

I still have no idea how "optimal/suboptimal solution" is relevant to the point I had (that "I am willing to spend up to X on a single adventure, get me the most adventures at that cost" is *not* the same as "the value of generating 1 adventure is X for me, get me the biggest daily profit").
 

lostcalpolydude

Developer
Staff member
I still have no idea how "optimal/suboptimal solution" is relevant to the point I had (that "I am willing to spend up to X on a single adventure, get me the most adventures at that cost" is *not* the same as "the value of generating 1 adventure is X for me, get me the biggest daily profit").

I guess this demonstrates the difference, and also the complete waste of server hits of the former. (Attempting to) optimize daily profit is the only useful thing a diet could do. Spending 30k on something that gives 30 turns when valueOfAdventure=1000 would be a waste of server hits consuming the item and spending adventures earned from it.
 

Theraze

Active member
For manually generating your food lists, you can always use the optimal diet list I linked above... According to this page, Knob Pasties aren't optimal until after you've passed 2.5k per adventure. The nice thing about the site is that it gives cost of adventure in meat (which, I'd assume, would be roughly the same as what EatDrink uses), how many total adventures, how much total it cost you to get there, and how much profit that should generate assuming your adventure value.

Anyways, unobfuscated link follows: http://www.houeland.com/kol/diets
 
Top