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

fronobulax

Developer
Staff member
Intermediate report. The function npc_price seems to be implicated in the stack overflow. I will look at that but it may be a mafia problem rather than an ED problem.

Point on programming style. In the ancient days when computers were powered by dinosaurs running on treadmills, calling a function was very expensive. Calling a function in a loop or other iteration was many times more expensive. Thus calling a function multiple times in a loop when the value of the function was not changing was a way to become the bait that ran on the treadmill to keep the dino moving.

There were at least three loops where npc_price(i) was called but i did not change. So calling it once, storing it and using the stored value is a more elegant practice even if we don't have enough data to see whether there is a noticeable time difference between the two implementations.

Code:
int npcp = 0;  
foreach i in working
  {
    npcp = npc_price(i);
    while ((working[i] < 0) && EAT_SHOP && (npcp > 0) && (get_meat(1) >= npcp))
    {
      working[i] = working[i] + 1;
      makeusedmeat = makeusedmeat + npcp;
    }
 

fronobulax

Developer
Staff member
Triple post. I think the implementation of npc_price was actually responsible for the stack overflow. Fixed, I hope, in r9395.
 

Theraze

Active member
True... I normally do that sort of thing in optimization, once I know that the base code works the way I want, since until then it's all in the air what's going to stick and what's going to go away. That's a tweak though that shouldn't cause any chaos, and eliminates anything from 0-3 checks per sequence for npc_price. Also did the same for effective_price in the looping during ingredient checks. Using npcprice and effective as the int names, so that should be fine since neither overlaps.

Uploading this untested, but should be faster since it doesn't keep checking for prices. Eliminating effective_price should be much more of a time saver than npc_price, since that's actually a more complicated function...

Edit: So yeah, the mafia change 9395 breaks NPC availability checking, making it think that anything that you can ever purchase from NPCs can always be purchased. Not good.
 

Attachments

  • EatDrink.ash
    81.9 KB · Views: 44
Last edited:

fronobulax

Developer
Staff member
You're right. I broke it. r9400 should restore the functionality and possible make it easier to trace the stack overflow.
 

xKiv

Active member
Code:
int npcp = 0;  
foreach i in working
  {
    npcp = npc_price(i);
    while ((working[i] < 0) && EAT_SHOP && (npcp > 0) && (get_meat(1) >= npcp))
    {
      working[i] = working[i] + 1;
      makeusedmeat = makeusedmeat + npcp;
    }

And since (I assume) EAT_SHOP doesn't change, you could probably ditch the cycle completely and just do
Code:
int npcp = 0;  
foreach i in working
  {
    npcp = npc_price(i);
    int T = min(-working[i], floor(get_meat(1)/npcp));
    if (T > 0)
    {
      working[i] = working[i] + T;
      makeusedmeat = makeusedmeat + T*npcp;
    }
 

fronobulax

Developer
Staff member
#923 and r9400 stack overflowed again.

Since I am someone who always says it is easier to make a working program fast than it is to make a fast program work, my suggestions were offered with an awareness that three identical functional calls in the same loop might be a factor in the stack overflow problem. Not sure that is the case however.
 

fronobulax

Developer
Staff member
Withe verbose2 enabled, I get pages and pages of
> HISTORICAL:flat dough = 100
> HISTORICAL:wad of dough = 100
> HISTORICAL:flat dough = 100
> HISTORICAL:wad of dough = 100
> HISTORICAL:flat dough = 100
> HISTORICAL:wad of dough = 100
> HISTORICAL:flat dough = 100

before the stack overflow. Not sure where to point the finger but it is pretty obvious that there is an infinite loop because the two items are logically equivalent.
 

Theraze

Active member
Hmm... try this? I changed count(get_ingredients()) > 0 to count(get_ingredients()) > 1, so it won't match flat dough anymore.

Since turning npc_price from 1 line to 4 didn't fix the problem, my copy of RuntimeLibrary uses the 1 line version. For now, at least. Just seems more 'clean' overall.
 

Attachments

  • EatDrink.ash
    81.9 KB · Views: 33

Veracity

Developer
Staff member
I think the implementation of npc_price was actually responsible for the stack overflow. Fixed, I hope, in r9395.
You "think" it was responsible? You didn't share the stack trace, but did you see npc_price calling itself recursively? Or is it the ASH code which calls that function that is calling itself recursively?

Can you explain exactly how the code you removed was responsible for a stack overflow? This was the line you removed (with a few line breaks thrown in for clarity).
Code:
		return new Value(
			NPCStoreDatabase.contains( ItemDatabase.getItemName( item.intValue() ), true ) ?
			NPCStoreDatabase.price( ItemDatabase.getItemName( item.intValue() ) ) :
			0 );
Now, let's refactor by only looking up the itemname in ItemDatabase once (since that allocates a new Integer and does a map lookup each time).
Code:
		String it = ItemDatabase.getItemName( item.intValue() );
		return new Value(
			NPCStoreDatabase.contains( it, true ) ?
			NPCStoreDatabase.price( it ) : 0 );
I am puzzled. What, exactly, is overflowing? Your patch which purported to fix the stack overflow removed the call to NPCStoreDatabase.contains(). It effectively made that code into:
Code:
		String it = ItemDatabase.getItemName( item.intValue() );
		return new Value( NPCStoreDatabase.price( it ) );
So, apparently, you believe that NPCStoreDatabase.contains( String, true ) infinitely recurses or something - even though that is used all over the place with no trouble.

If you really have a case of that function infinitely recursing, why not fix that function?
 

Theraze

Active member
And it wasn't actually that recursing of that function at all... it was that it was the script comparing get_ingredients($item[flat dough]) and get_ingredients($item[wad of dough]) infinitely. Since one generates the other, and back again, it caused looping for him. Not sure why it didn't for me, but...
 

nsd45

New member
Im in a rush so i apologize if it was already said but does EatDrink support bees hate you runs or am i on my own for drinking and eating
 

Theraze

Active member
The one that's being worked on (post 928) does support Bees Hate You. The release version does not.
 

fronobulax

Developer
Staff member
#928 and r9411 behave. I am more concerned with mechanics rather than the quality of the diet at this point and I note that TPS drinks were handled appropriately.

I'm not sure what Bee support is expected. #928 did ignore all of my b foods, as far as I noticed, but it still tried to make drinks with "bottle of ...". It failed gracefully and recovered and so I'm not sure why Bee support is needed unless it is an efficiency/elegance desire.

To close the loop, I was tired and since the stack overflow ceased when I tested r9395 and I (incorrectly, as we have since learned) linked cause and effect. Since that broke functionality (I said I was tired) it was undone in r9400 and the cause of the stack overflow correctly traced to an ED beta version prior to #928. The big lesson here is that there are some things I should not be doing when I am tired.
 

Winterbay

Active member
You can make drinks with "bottle of..." just fine in beecore as well, you just can't drink anythign with b in it.
 

Theraze

Active member
Yeah... what still needs testing is whether or not it still chooses to make pies, burritos, and other flat dough/wad of dough things. I think it will still buy them using npc_price, but am not certain that it will work the same regardless... however, both do have a price using that command, so it should work fine.

I did add a be_good check to have_ingredients in the latest version, so that should properly skip your 'bottle of' ingredients. I don't think this is right though... I removed the check again after this:
Getting 1 margarita in 0 seconds
autoBuyPriceLimit => 250.0
Verifying ingredients for margarita (1)...
Searching for "lemon"...
Search complete.
Purchasing lemon (1 @ 70)...
You acquire an item: lemon
You spent 70 Meat
Purchases complete.
Creating margarita (1)...
You acquire an item: margarita
Successfully created margarita (1)
autoBuyPriceLimit => 5000
It appears that 'bottle of' ingredients work just fine for crafting in bee-core, as margarita is "bottle of tequila" plus a lemon, and it did create it...
> inv margarita
Drinking 1 margarita...
You gain 9 Adventures
You gain 11 Muscleboundness
You gain 3 Drunkenness
You lose some of an effect: Ode to Booze
Finished drinking 1 margarita.
The inv margarita quote was from before I ran ED, to validate that I didn't have any completed margaritas yet, the quote from its consumption is to show that yes, the margarita that it believes it made was actually successfull in its construction.
 
Last edited:

fronobulax

Developer
Staff member
You can make drinks with "bottle of..." just fine in beecore as well, you just can't drink anythign with b in it.

Maybe I need to take naps before I post? :)

ED was complaining that it couldn't do something and "bottle of" was in the complaint message. There was probably something else going on that I didn't notice. I'll pay closer attention next time.
 

Theraze

Active member
Two possible issues: One, it wanted to make a base bottle-type and failed, either because you can't craft "bottles" during bee-core or because it tried to make an item that needs a recipe.

We might be able to fix the first issue... I'll need to validate that later in beecore, but I recall being able to craft the bean burrito for the nemesis without issues, so that's likely not a real issue.

Second issue... no fix for that unless we get access to concoctions somehow.
 
Eatdrink is apparently creating twinkly wads for me to consume but not telling me how it's doing so. I don't know if I had nuggets and powder I wasn't aware of or if it's smashing things and not telling me. Checking my log it is actually using nuggets I didn't recall having but can something be added so it notes what it's doing to make the wads instead of just telling me it's making them?
 

Theraze

Active member
It's just using retrieve_item to get them, so it's likely turning nuggets/powder into wads, since I (sincerely hope and) expect it's not auto-pulverizing your gear, even gear on the cleanup list. If you look above in the part where it says something like:
Getting 15 twinkly wads in 3 seconds.
The part immediately following that should tell you a bit about what mafia logs regarding their creation...
 
Top