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

Too late for me to test today. Two comments. At least once I forgot to closet my enchanted bean or similar ingredients required for the Nemesis quest and ended up eating them. At some point it is diminishing returns for ED to protect me from myself especially if the need for protection is conditional but it is something to think about. Second, I am not totally certain what the various STEP_MEAT options are going to do for me, but from a control standpoint, I am much more concerned about the total amount that ED spends and less so on when it spends them. Is the limit per invocation of ED or is it per day? If the former then it is not especially helpful since I typically run ED twice per day, sometimes as often as four times per day and Ascend could theoretically run it 50 times per day. My solution was the preference _Ascend_EatDrinkSpentToday and a variable that was the daily budget. YMMV.
 
1) Enchanted bean burritos were my major food pre-HC-perming pasta. Since you only need one and it's well over a 50% chance of success to collect per adventure, I think I'll leave protecting that on the user and not as the default. They can closet it, add as an avoid, or whatever. If you have strong feelings on this, I can add it defaulted to false, but... eh.

2a) Problem with trying to protect based on total is that we run type by type. If you try to limit based on total, then you just end up not using anything for drink/spleen at all, since you've spent it all on awesome food. Want to set STEP_MEAT based on total? Divide your total max by 3.
2b) It runs per execution, per step. If you go to 13 fullness to leave room for 2 fortune cookies, with 10k as your SM value, it will aim for the best value for your meat not going over 10k total for those 13 points of fullness. If you end up running ED again after only 1 fortune cookie, you will probably have it skip getting a milk since 1 adventure for 900 meat with a 500 VoA isn't cost effective, but it will get you the best value based on cost... with 500 VoA, the highest possible current item is the tempuramancy veggies at 6 adventures for your 1 fullness, so you're looking at 3000 'value' minus however much it costs you to get them. I don't think you're likely though to end up spending more than 1-2k max for that.
If for some reason you run ED every 10 adventures and use up 2 fullness every time... yes, it will keep buying milk. But that's because you're trying to waste as much milk as possible.
Part of the benefit of running by step is that it doesn't matter if we have 1 step or 4 to calculate... each step is its own "group" of meat. Run ED no-fullness at the start of the day to get your 150 adventures or so and burn off to fortune cookie, do your 170 adventures and run ED on the 14 fullness left after your fortune cookie... it should buy the same stuff as it would have if you had called it 170 adventures ago for 14 fullness, 19 drunk. Well, unless you got exciting new craftable food. But otherwise... the only way this should cause problems is if people do stupid things like set VoA at 10,000, autoBuyPriceLimit at 100,000, and STEP_MEAT at 10,000-20,000. The SM will protect them as long as they're eating a full stack, but it will spend up to limit on every execution. I maintain that's the user's fault for trying to break the system. :D

But yeah, want to set your daily budget at 20000? Either set SM at 5000 or 7500, depending on how much you want it to allow for your nightcap. If your VoA is below 2000, 7500 as SM should be fine and not go over 20k too often. Remember that this is the maximum amount that it will calculate below... it doesn't mean that it will always use that much. Setting it at 5000 will always use less than 20k, since it would allocate 5k for food, 5k for drink, 5k for spleen, and 5k for the nightcap...
 
Last edited:
OK on the bean.

Not OK on the "The SM will protect them as long as they're eating a full stack, but it will spend up to limit on every execution. I maintain that's the user's fault for trying to break the system." as a philosophy although it might be a compromise that has to be accepted. You are pretty much breaking ED for Ascend when you say that. Basically what happens is that Ascend will call ED every time it has zero adventures and unused fullness. Thus if it does not max out on the first call, it will be called again. This is beneficial and desired in low level and hardcore characters since the second call might be able to eat something better or something that just dropped. Not every character can afford or obtain milk so wasting turns of something that cannot be obtained is not a factor.

That said, the net effect on Ascend of allowing your change to propagate, will probably be nothing more than having to fiddle with a whole bunch of parameters so that the desired results are obtained.

However...

Consider separate preferences for each type of consumption: Food, Drink (including overdrink), Spleen and NoneOfTheAbove. (It might be acceptable to derive the last one from VOA instead). There are values for total budget and spent today. Your STEP value gets replaced by the budget minus spent for each type of consumption. You track spending as appropriate. That seems to address the concerns noted so far ;-)
 
Low level and HC characters without much stuff aren't going to be buying stuff from the mall anyways... I think the most I've ever spent as a HC character was under 5000 meat for all 4 steps. Your items in inventory aren't counted anyways against the budget. They're counted/eliminated based on your max budget so that you can say that anything worth above 2000 meat you're going to sell in your shop later... ED doesn't subtract 5790 meat from your budget if a gimlet is already in your inventory, only if you actually bought it and spent that 5790 meat. Same thing as if you closetted all but 2000 of your meat... it would still have been able to drink that gimlet if you already had it created and it was your best 'value'. Total spent? 0... unless you had to get ode.

The "user's fault for trying to break the system" only applies to softcore/aftercore people with tons of money. Not HC people with limited resources.
 
The problem with EatDrink that caused me to auto-closet meat before running involved buying from NPC stores, not the mall, and situations where I needed meat to buy Quest items.
 
True. :) Your method works for you. I'm just unlikely to try to make the system any more complicated than its current state, at the moment. The way it's working now, it can be used as an alternative to closetting meat if you like, or you can closet and set SM to -1 to use legacy style. Hey, your choice. :) But this means I don't need to worry about aftercore burning off 40000 meat and getting 5 more adventures than I would have for 10000 meat total, etc. Also, in general I don't have many meat-flow problems in run, especially since I have both tongue and cocoon permed on most characters, and I'm mostly running mana-familiars in 100 runs. The NPC purchases tend to be about 1000 meat a day or less, and that's mostly buying mana for ode on characters with less than 100 max. But once I run out of mana familiars... Or when I start to do WoSF runs... heh.
 
AFAIK the latest version.

It decided to try stale baguettes and failed. Then dire fudgesicle and failed, then failed for ancient frozen dinner and failing again started buying mugcakes. I did not want mugcakes so I aborted. I then noticed that there were baguettes, fudgesicles and frozen dinners in my inventory, although not enough of any single one to fill me up. I then ran ED again and it consumed three baguettes just fine, filling my stomach. (Note that some mugcakes were consumed before the abort was successful).

I think all of the items were in my inventory when I stated ED although that is hard to confirm after the fact. They definitely were not pulled or purchased since the character is Level 3, still in ronin, had 20 pulls left and doesn't have much meat. My guess is that ED decided it wanted N of something, could only get M, where M < N and recomputed throwing the item out of consideration rather than consider consuming M and filling up with something else.

In any event, since it did consume the baguettes it seems like it is EDs decision making that needs to be looked at and not it's ability to obtain what it wants. To jog my memory this was CafeBoob on 8/21 if we need to mine logs.
 
If this happens again, you probably need to run a refresh all... most likely you had one of those lovely inventory out of synch things, since this is the way it works:
1) Decide best item.
2) Try to get item. If item amount before/after this happens is the same, mark the item as a failure and skip in the future, otherwise leave our partial creation and recalculate giving the following message:
verbose("Something went wrong with getting "+item+" for "+price+". Recalculating.");
3) Find best item. If inventory had changed in step 2, this can still be the same best item, but hopefully a lower amount. If this happens, it means our inventory belief is inaccurate. If caught early enough, this is how bugs get found. If inventory had not changed, the item is eliminated and it's something else as best. This could be an inaccurate inventory belief, or caused by trying to set variables manually.

Basically, if this error message comes up and we were able to have our inventory to change at all, the item availability should be accurate. If it didn't, it means that your inventory is screwed up and can't be trusted. Due to that it checks all item areas, you might need to do a refresh all to actually get it to return to accuracy, if it was using an outfit to purchase some of the items. Also possible... you did something bad with variables, like trying to disable using your inventory, or enable using the closet, or something else like that. I warned about that back in post 1101, albeit obliquely, and asked if we wanted custom retrieval code or keep using retrieve_item. As long as we're using retrieve_item, if you try to set USE_INV outside of simulation, you WILL break things. These can still be used for simulation... but then your simulation and actual execution will not return the same results. The only way to avoid this is to:
a) Leave it like this. People breaking their system, counter to usage is something that can't be easily stopped.
b) Scrap the variables, read the preferences 50 times in the script. Inefficient, but almost impossible to break.
c) Try to do randomized variables. When the script begins its execution, generate a random 5-10 digit number that gets appended to the variable. This would break anyone using old aliases, but new people trying to break their system would just find the static name of the random addition and append that automatically to make their scripts break again. Ultimately a useless make-work.
d) Custom retrieval code instead of retrieve_item, as noted in 1101, 1099, 1095, 1093, 1091, 1089, and probably some more posts from earlier.
 
First ED was run twice. The first time it was called from Ascend and decided it wanted mugcakes and consumed five of them before I was able to abort the script. Immediately, I then proceeded to run ED from the menu and it found and consumed the other items. I am hard pressed to construct a failure mode where KoLmafia would screw up the inventory under those circumstances so I'm not sure I believe your hypothesis ;-) Furthermore, the parameters were most likely identical in both calls although I will confirm that since Ascend may be tweaking something I had not seen before. Indeed, the parameterss that ED echos to the gCLI were identical.

That being the case, before I aborted it bought 10 mugcake (why with a max fullness of 14?) and consumed 5 of them. Those five cost 100 meat and yielded 5 adventures. In contrast there were at least 3 stale baguettes in inventory. If I substituted one of those baguettes for 3 mugcakes I would have received 3-6 adventures at a cost of 28-33 meat (autosell plus meat loss) compared to 3 adventures at a cost of 60 meat. So, as long as there is a baguette in inventory I maintain ED is suboptimal and wrong to choose 3 mugcake over one baguette. If you believe otherwise then break things down into words of two syllables or less so I can understand and then tell me what parameter values have to be changed to make that so.

(While it is possible that the baguette is valued at 100 meat due to parameter settings, if that were really the case then ED should have not elected to consume them from inventory the second time it was run, correct?)

If you agree that one baguette should be better than 3 mugcakes under default conditions, then I am suggesting that the decision made in 2) or 3) above was incorrect. I would furthermore suggest that what I have seen suggests that step 2) as implemented marks the item as a failure and then throws away the partial creation when it should keep the partial. 4 stale baguettes may have failed but 3 stale baguettes are still the best choice for the first 9 fullness.

I'll run from the menu and in sim and comparing against the Old ED tomorrow and see if I can gain any more insight.

Unrelated to the above... Character has TPS and typically drinks cherry bombs or sangia de diablo. Lately ED has been reporting failures because the single item limit is 1000 but cherries are 1050. However the limit parameter that I am putting in is 25000. ED is clearly recalculating and using a lower value, which is all right, but what do I have to change so that cherries are reasonable at 1050?

Thanks for all your work, by the way. It may sound like we're driving each other crazy, but that is not at all the case, at least on my end.
 
When it fails to get any it does not use it since it can not go in you and you can not get any more of it.

There, that's the problem explained in single syllables. I don't think it's easier to understand, but hey... I wasn't the one who wanted the syllable limitation. :D

Here's the code in question:
Code:
boolean getone(item it, int price)
{
  if (SIM_CONSUME)
  {
    verbose("simulating retrieval of one "+it+".");
    return true;
  }
  int initialamount = item_amount(it);
  boolean gotit = true;
  int needed = 0;
  foreach i in position { if (position[i].it == it) needed += 1; }
  if (needed == 0) needed = 1;
  gotit = getitem(needed, it);
  if (!gotit)
  {
    if (!EAT_MALL)
      summarize("EatDrink encountered an error: You don't have "+needed+" "+it
                +" and you're not able to shop.");
    else if (price == 0)
      summarize("EatDrink encountered an error: You don't have "+needed+" "+it
                +" and it has a null price, so you can't buy it.");
    if (item_amount(it) == initialamount)
      fail[it] = true;
  }
  return gotit;
}
Specifically, this part:
PHP:
  int initialamount = item_amount(it);
and this part:
PHP:
    if (item_amount(it) == initialamount)
      fail[it] = true;
The only way it will eliminate an item is if item_amount is the same before and after retrieval. The only way that should happen is if it wants more than it can get for some reason... what could that reason be? No clue in your case. I'm not you, I don't execute it with any sort of wrapper, and I haven't had it screw up with any item retrieval problems (except for the one with needing to buy the oven) since I found what appears to be the last ingredient bug on August 1st... Since you had it happen repeatedly, it seems like something about the way you execute it is doing... something. It's quite likely that the Ascend wrapper is why it's trying to force using certain item locations in ways that don't work with the mafia retrieve_item system.

And yeah, I don't feel like we're driving each other crazy. It's the annoyance on both sides of trying to work at weird bugs that might be caused by this script, by Ascend, or possibly by other preferences fighting into things. It's aggravating, but that's because once you've eaten, finding the problem again...

But yeah, my guess is that it's probably the Ascend wrapper causing problems though. I'll remove the inventory check completely, because retrieve_item always uses inventory. While the official calls into eatdrink's preferences won't affect what locations it uses anymore, if the Ascend wrapper has USE_CLOSET or any of those in it, those WILL break the retrieval locations and make the script not work, unless we do custom get-item code.
 
The only way it will eliminate an item is if item_amount is the same before and after retrieval.

Since there were already three in inventory and it failed to get a fourth, item_amount will remain unchanged. But that does not mean the three in the inventory are unavailable for use or are still not a viable candidate for consumption. So my knee jerk reaction is that there may be a logic error in that two different cases are being treated the same. Case I is that there are zero on hand before and after the "get" attempt in which case the item should be eliminated from consideration. Case II is that there are "some" on hand and the get attempt fails to get any more, in which case the item should still be considered but only in limited quantities.
 
Well, the issue is that if it expects there to be 4 and there are only 3, and we re-run the consideration, it will re-consider at 4 and fail again... as long as the available amount changes, we have some hope of avoiding an infinite loop.

But if a loop exists... it's going to be a VERY long time before you get that 4th one. :)
 
Agreed. But since using the items on hand is both allowed (according to settings) and better than buying mugcakes, by failing to handle limited quantities EatDrink is no longer computing the best (or even better) diet possible.
 
A present for you. I logged in, messed with my outfits and then ran ED. I always ran 'interactively" so the parameters would be the same. I ran the Old version and then the New one. I used SIM and only worried about food. First two runs - old then new - gave the same results. I closeted the hell broth and then ran again. The old version thinks I can have as many stale baguettes as I want which is expected from the old version in sim mode. The new version decides I can have two stale baguettes, four dire fudgesicles and one mugcake. It is not clear from the log but there was only one baguette in inventory. I then let it run for real, it failed on the baguette and then dismissed it from consideration so I aborted.

So, while there may be room for a lot of discussion about what to do if the predicted amount desired cannot be obtained, it does seem as if in this case there is a more basic problem of predicting there is more available than there really is.
 

Attachments

Good to have validation that it's pulling incorrect base values. I made simulating consumption more spammy in this version... can you check it on cafeboob and see what it says next time you find it screwing up like that? Especially if it still thinks a baguette is available... This is the line that's odd in your quote:
> 4: <b>stale baguette</b> lev:1 gain:3.0 adv:4.5 musc:0.0 myst:0.0 mox:0.0 meat:100 own:2 value:716
The attached version should give something like this on each retrieval:
simulating retrieval of one peach pie.
We believe we have i0 c0 s0
Our grub says we have a1 npc=false mall=false
Basically, first we're using _amounts... item0, closet0, storage0. Then we go to the grub... a should equal i+c+s+creatable, so we're making our peach pie since i+c+s=0 and a>0. npc false means mustShop is false, mall false means mustMall is false. If this works as it should, we're getting our peach pie (all 5 of them, actually) from creating them. When you get screwed up baguettes or other stuff, please post that and hopefully it'll tell us where it's thinking the non-available baguettes are coming from...
 

Attachments

Double-posting because I think I found it... ascended someone softcore today and they had this same bug. It appears to happen when you have a softcore character, in ronin, with pulls remaining. If all of those are true, ED believes it can use your pulls at a 'cost' of 3000 meat. Unfortunately, retrieve_item doesn't want to pull items when they're limited, so it will never succeed... I've changed the pulls_remaining check to !get_ronin to check if storage is available. This means it won't try to pull ronin food automatically, but it also should stop the buggy requests.
 

Attachments

Alas. SIM mode.

food: At 0, consuming to 15 with 10 meat.
1: Hell broth lev:3 gain:4.0 adv:11.0 musc:-5.0 myst:0.0 mox:-5.0 meat:2150 own:0 value:822
2: stale baguette lev:1 gain:3.0 adv:4.5 musc:0.0 myst:0.0 mox:0.0 meat:100 own:2 value:716
3: stale baguette lev:1 gain:3.0 adv:4.5 musc:0.0 myst:0.0 mox:0.0 meat:100 own:2 value:716
4: stale baguette lev:1 gain:3.0 adv:4.5 musc:0.0 myst:0.0 mox:0.0 meat:100 own:2 value:716
5: dire fudgesicle lev:1 gain:2.0 adv:3.0 musc:0.0 myst:9.0 mox:0.0 meat:101 own:9 value:708

It thinks there is one too many baguette. Own 2, consume 3. I will merge the write from 1157 into 1158 and rerun.

Edit:
Adding the write was pretty simple.

simulating retrieval of one Hell broth.
We believe we have i1 c0 s0
Our grub says we have a1 npc=false mall=false
simulating retrieval of one stale baguette.
We believe we have i5 c0 s1
Our grub says we have a5 npc=false mall=false
simulating retrieval of one stale baguette.
We believe we have i5 c0 s1
Our grub says we have a5 npc=false mall=false
simulating retrieval of one stale baguette.
We believe we have i5 c0 s1
Our grub says we have a5 npc=false mall=false
simulating retrieval of one dire fudgesicle.
We believe we have i9 c0 s1
Our grub says we have a9 npc=false mall=false

I actually do have 5 baguettes in inventory ATM so it appears that what is after Own: is in error. I'm going to closet the broth, a couple of the baguettes and see what happens.

And again:
simulating retrieval of one stale baguette.
We believe we have i2 c3 s1
Our grub says we have a2 npc=false mall=false
simulating retrieval of one stale baguette.
We believe we have i2 c3 s1
Our grub says we have a2 npc=false mall=false
simulating retrieval of one dire fudgesicle.
We believe we have i9 c0 s1
Our grub says we have a9 npc=false mall=false
simulating retrieval of one dire fudgesicle.
We believe we have i9 c0 s1
Our grub says we have a9 npc=false mall=false
simulating retrieval of one dire fudgesicle.
We believe we have i9 c0 s1
Our grub says we have a9 npc=false mall=false
simulating retrieval of one dire fudgesicle.
We believe we have i9 c0 s1
Our grub says we have a9 npc=false mall=false
simulating retrieval of one stalk of asparagus.
We believe we have i1 c0 s1
Our grub says we have a1 npc=false mall=false

Simulating only; no purchases or food/drink/spleen consumption.
food: At 0, consuming to 15 with 10 meat.
1: stale baguette lev:1 gain:3.0 adv:4.5 musc:0.0 myst:0.0 mox:0.0 meat:100 own:0 value:716
2: stale baguette lev:1 gain:3.0 adv:4.5 musc:0.0 myst:0.0 mox:0.0 meat:100 own:0 value:716
3: dire fudgesicle lev:1 gain:2.0 adv:3.0 musc:0.0 myst:9.0 mox:0.0 meat:101 own:5 value:708
4: dire fudgesicle lev:1 gain:2.0 adv:3.0 musc:0.0 myst:9.0 mox:0.0 meat:101 own:5 value:708
5: dire fudgesicle lev:1 gain:2.0 adv:3.0 musc:0.0 myst:9.0 mox:0.0 meat:101 own:5 value:708
6: dire fudgesicle lev:1 gain:2.0 adv:3.0 musc:0.0 myst:9.0 mox:0.0 meat:101 own:5 value:708
7: stalk of asparagus lev:1 gain:1.0 adv:1.0 musc:0.0 myst:2.0 mox:0.0 meat:399 own:1 value:105

Own: is definitely wrong, but I am going to let it run for real.
 
Last edited:
Own is supposed to show the amount you have left after it's all done... so especially while simulating, 5(start)-3(used)=2 owned when done is right...

To be a bit more clear, own: shows you the amount that availability says you have... it's con.have, which is set by taking inventory amount plus storage (if outside ronin and enabled), closet (if enabled), and creatable amount (either accurate or fast) and subtracting the amount used in the stack and being used as ingredients. This means that own: can be negative, if the amount you own goes down to 0 and then you keep using more by buying them from NPC or mall stores, if enabled.
 
Last edited:
Back
Top