quality of food and booze

fianor

Member
I know I can script

foreach it in $items[]
if (item_type(it)=="food") do something

to check my inventory for food, but is there a way to narrow it to the quality of food (i.e. Awesome, Epic) without manually looking up each item on the wiki and hard-coding each into the script?
 

matt.chugg

Moderator
I know I can script

foreach it in $items[]
if (item_type(it)=="food") do something

to check my inventory for food, but is there a way to narrow it to the quality of food (i.e. Awesome, Epic) without manually looking up each item on the wiki and hard-coding each into the script?

About to miss my train! something like this may help to tell you the quality of the food, although I could be miles wrong too!

i'll explain more if no-one else does, if I make it to the train and am not stranded ;)

Code:
int[item][int][int][string] food;
file_to_map("fullness.txt", food);
foreach item,fullness,level,adventures in food {
	
	int avgadventures = 0;
	if(contains_text(adventures,"-")) {
		string[int] advs = split_string(adventures,"-");
		avgadventures = (advs[0].to_int() + advs[1].to_int()) / 2;
	} else {
		avgadventures = adventures.to_int();
	}
	if(fullness != 0) {
		print(item.to_string() + " " + avgadventures/fullness);
	}
}
 

Theraze

Active member
I'd suggest turning avgadventures into a float, or at least trying to do a float at some point so you get the 1.5 adventures, 2.5, etc... but otherwise, that looks like a decent full listing of average food values. To combine that with your above items list, you'd probably want to do something like this:
PHP:
int[item][int][int][string] food;
file_to_map("fullness.txt", food);
foreach item,fullness,level,adventures in food {
 foreach it in $items[] {
  if (it == item) {
   float avgadventures = 0;
   if(contains_text(adventures,"-")) {
    string[int] advs = split_string(adventures,"-");
    avgadventures = (advs[0].to_float() + advs[1].to_float()) / 2;
   } else {
    avgadventures = adventures.to_float();
   }
   if(fullness != 0) {
    print(item.to_string() + " " + avgadventures/fullness);
   }
  }
 }
}
 

matt.chugg

Moderator
I'm confused about the second foreach loop! is it necesary?

You are looping through the whole inventory with every iteration of fullness.txt until you find the item again?

as a function to return a map of items and average adventures per fullness:

PHP:
float[item] foodbyquality(float minadvsperfull) {
	int[item][int][int][string] food;
	float[item] returnfood;
	file_to_map("fullness.txt", food);
	foreach item,fullness,level,adventures in food {
		if(fullness != 0) {
			float avgadventures = 0;
			if(contains_text(adventures,"-")) {
				string[int] advs = split_string(adventures,"-");
				avgadventures = (advs[0].to_float() + advs[1].to_float()) / 2;
			} else {
				avgadventures = adventures.to_float();
			}
			if (avgadventures >= minadvsperfull) {
				returnfood[item] = avgadventures;
			}
		}
	}
	return returnfood;
}

void main() {
	float[item] foodvalues = foodbyquality(20);
	foreach item in foodvalues {
		print(item.to_string() + " " + foodvalues[item]);
	}

}
 
Last edited:

Veracity

Developer
Staff member
Consider these feature requests:

proxy records for consumption data
consumable quality colors

We could easily enough add consumption data, but we don't currently have info about food/booze "quality" - in the crappy/good/EPIC sense. I wish we did, since I'd really like to do #2. I assume we'd add another field to fullness.txt/inebriety.txt/spleenhit.txt and make one pass (automated, hopefully) looking at all the item descs and filling it in.
 

matt.chugg

Moderator
I can't believe I never saw it, bump bump bump! excellent idea!

I'm doubly interested now after discovering that a the quality of the food isn't necesarily represented by its AVERAGE adventures. unless I got my script wrong?

PHP:
	int[item][int][int][string] food;
	file_to_map("fullness.txt", food);
	foreach it,fullness,level,adventures in food {
		if(fullness != 0) {
			float avgadventures = 0;
			if(contains_text(adventures,"-")) {
				string[int] advs = split_string(adventures,"-");
				avgadventures = (advs[0].to_float() + advs[1].to_float()) / 2;
			} else {
				avgadventures = adventures.to_float();
			}
				string desc = visit_url("desc_item.php?whichitem=" + it.to_item().descid);
				string type = "Unknown";
				if (contains_text(desc,"<font color=blueviolet>(EPIC)</font>")) {
					type = "EPIC";
				} else if (contains_text(desc,"<font color=blue>(awesome)</font>")) {
					type = "awesome";
				} else if (contains_text(desc,"<font color=green>(good)</font>")) {
					type = "good";
				}else if (contains_text(desc,"<b>food (decent)</b>")) {
					type = "decent";
				}else if (contains_text(desc,"<font color=#999999>(crappy)</font>")) {
					type = "crappy";
				}else if (contains_text(desc,"<font color=green>?</font><font color=red>?</font><font color=#999999>?</font>")) {
					type = "???";
				} else {

				}

				print(it.to_string() + " " + avgadventures/fullness + " " + type);
			}

	}

returned

Code:
3vi1 pr0n m4nic0tti 2.75 awesome
a dance upon the palate 3.0 crappy
abominable snowcone 1.75 decent
ancient frozen dinner 1.5 decent
ancient unspeakable fruitcake 1.5 decent
angel-food cake 1.0 crappy
antique packet of ketchup 1.0 crappy
asparagus lo mein 4.1666665 awesome
asparagus stir-fry 3.0 good
astral hot dog 2.0 ???
babycakes 1.0 crappy
badass pie 4.5 awesome
balaclava baklava 1.25 decent
ballroom blintz 1.8333334 decent
banana 1.0 crappy
banana cream pie 3.0 good
banana milkshake 3.5 awesome
banana-frosted king cake 1.0 crappy
Bash-Ōs cereal 1.0 crappy
bat haggis 2.25 decent
bat wing chow mein 5.0 awesome
bat wing kabob 1.75 decent
bat wing stir-fry 3.3333333 awesome
bat-shaped Crimboween cookie 4.5 awesome
bean burrito 1.8333334 decent
beautiful soup 3.0 good
beefy fish meat 2.5 good
beer basted brat 4.8333335 awesome
bell-shaped Crimbo cookie 4.5 awesome
KoLmafia declares world peace.

I don't know how accurate the values have been spaded, (and we know the wiki is so very very accurate [/sarcasm]), but it may be possible to extrapolate the food quality from the values based on

(crappy) Gives no more than 1 adventure per fullness
(decent) Gives more than 1 and at most 2 adventures per fullness
(good) Gives more than 2 and at most 3 adventures per fullness
(awesome) Gives more than 3 and at most 5 adventures per fullness
(EPIC) Gives more than 5 adventures per fullness

which seems to be based upon the lower and upper values of the adventures per fullness range as opposed to an average.
 

Theraze

Active member
I'm confused about the second foreach loop! is it necesary?

You are looping through the whole inventory with every iteration of fullness.txt until you find the item again?

Well, the initial question was using the $items[] and I was expecting it to be defined usefully somewhere, possibly with some actual specific items in the list. If you were wanting the values of specific items, you'd need to put them into those brackets and parse it as you're iterating through the file to see if the item you've loaded is one of the items you're interested in.

If, as you say, you're comparing the "whole inventory" for items currently carried by the player running the script, then yes... something like that would be proper.

But in the case of running the complete item list... as that script actually does... cut out the extra foreach and make it run that much faster. :) You're processing/displaying the whole list anyways, you're not gaining any benefit for checking if an item is an item.
 
Wouldn't it be more efficient then, to swap the foreaches (what a splendidly awful word), and do something like this:
Code:
 foreach it in $items[...] {
  foreach fullness, level, adventures in food[it] {
So that instead of going through the entire food list, you only pull the data for the foods you're concerned with.
 

Theraze

Active member
That would make a bizarre amount of sense. :D Or, as an alternate, wait until the proxy fields are eventually added and just use them then. :)
 

matt.chugg

Moderator
Build 9599

Code:
foreach it in $items[] {
	if((item_type(it) == "food") & (it.quality=="epic") ) {
		print(it);
	}
}
 
Last edited:

matt.chugg

Moderator
/me wonders if its still quicker to parse fullness.text and compare quality on those items that to iterate all possible items and check whether its food first?

unless theres a way of selecting all food items using $items[where item_type="food"] kind of linq style?!
 

Winterbay

Active member
Wouldn't this be better?
Code:
foreach it in $items[] {
	if((it.fullness > 0) & (it.quality=="epic") ) {
		print(it);
	}
}

(does not go around the problem that you're going through the entire item-database though)
 

matt.chugg

Moderator
Wouldn't this be better?
Code:
foreach it in $items[] {
	if((it.fullness > 0) & (it.quality=="epic") ) {
		print(it);
	}
}

(does not go around the problem that you're going through the entire item-database though)

is there a way of profiling various functions? could ash have an implimentation of GetTickCount?
 

Theraze

Active member
You could try to hype up the time function in bordemstirs time FReq of last halloween... specifically, the gametime_to_int patch made so he could check server time without needing to do a server hit. Examples of how to use it in the post 13 in that thread, but basically what it does is make gametime_to_int return the server time in MS, so you can use it for timing and all sorts of useful things as well.
 

matt.chugg

Moderator
You could try to hype up the time function in bordemstirs time FReq of last halloween... specifically, the gametime_to_int patch made so he could check server time without needing to do a server hit. Examples of how to use it in the post 13 in that thread, but basically what it does is make gametime_to_int return the server time in MS, so you can use it for timing and all sorts of useful things as well.

interesting, the patch has several conflicts i'll have to dig through, will look tomorrow!
 

Theraze

Active member
I'll spin a new version... It's one of the few patches from around that time I've kept reconciling in my source instead of reverting the files back. :)
 

matt.chugg

Moderator
You could try to hype up the time function in bordemstirs time FReq of last halloween... specifically, the gametime_to_int patch made so he could check server time without needing to do a server hit. Examples of how to use it in the post 13 in that thread, but basically what it does is make gametime_to_int return the server time in MS, so you can use it for timing and all sorts of useful things as well.

4 Test Cases:

Test1: 1000 iterations using full inventory, compaing item.fullness > 0
Test2: 1000 iterations using full inventory, compaing item_type ="food" > 0
Test3: 1000 iterations using fullness.txt (loaded each iteration)
Test4: 1000 iterations using fullness.txt (preloaded before loop)

Each test case incremented an integer each time it found epic food, but didn't print any thing to the cli and all tests repeated 3 times

script:

Code:
int starttime =0;


for a from 1 to 3 {


	print("Test 1");
	starttime = gametime_to_int();
	for i from 1 to 1000 {
		int epiccount = 0;
		foreach it in $items[] {
			if((item_type(it) == "food") & (it.quality=="epic") ) {
				epiccount +=1;
			}
		}
	}
	print("1000 Iterations full loop (type=\"food\" took " + (gametime_to_int() - starttime) + "ms");


	print("Test 2");
	starttime = gametime_to_int();
	for i from 1 to 1000 {
		int epiccount = 0;
		foreach it in $items[] {
			if((it.fullness > 0) & (it.quality=="epic") ) {
				epiccount +=1;
			}
		}
	}
	print("1000 Iterations (full loop, fullness > 0) took " + (gametime_to_int() - starttime) + "ms");



	print("Test 3");
	starttime = gametime_to_int();
	for i from 1 to 1000 {
		int epiccount = 0;
		int[item] food;
		file_to_map("fullness.txt", food);
		foreach it in food {
			if((it.fullness > 0) & (it.quality=="epic") ) {
				epiccount +=1;
			}
		}
	}
	print("1000 Iterations (fullness.text) took " + (gametime_to_int() - starttime) + "ms");

	
	print("Test 4");
	int[item] food;
	file_to_map("fullness.txt", food);
	starttime = gametime_to_int();
	
	for i from 1 to 1000 {
		int epiccount = 0;

		foreach it in food {
			if((it.fullness > 0) & (it.quality=="epic") ) {
				epiccount +=1;
			}
		}
	}
	print("1000 Iterations (fullness.text(pre loaded)) took " + (gametime_to_int() - starttime) + "ms");
	
	
}

output:

Test 1
1000 Iterations full loop (type="food" took 8073ms
Test 2
1000 Iterations (full loop, fullness > 0) took 12169ms
Test 3
1000 Iterations (fullness.text) took 4118ms
Test 4
1000 Iterations (fullness.text(pre loaded)) took 966ms
Test 1
1000 Iterations full loop (type="food" took 8137ms
Test 2
1000 Iterations (full loop, fullness > 0) took 12462ms
Test 3
1000 Iterations (fullness.text) took 4094ms
Test 4
1000 Iterations (fullness.text(pre loaded)) took 971ms
Test 1
1000 Iterations full loop (type="food" took 8198ms
Test 2
1000 Iterations (full loop, fullness > 0) took 12297ms
Test 3
1000 Iterations (fullness.text) took 3975ms
Test 4
1000 Iterations (fullness.text(pre loaded)) took 965ms

so if you are using it multiple times, using a pre-loaded fullness.text is MUCH faster, and even loading it 1000 times is way faster than looping the whole inventory.

and my version of item_type="food" seems quite a bit faster than item.fullness > 0 not sure why that comparison should be slower!
 

fianor

Member
I love you guys.

Code:
foreach it in $items[]
	if ((item_type(it)=="food") & (it.quality=="epic") & (item_amount(it) > 0)) 
            'DoStuff';
	else if ((item_type(it)=="booze") & (it.quality=="epic") & (item_amount(it) > 0)) 
            'DoStuff';

That is amazingly fast at finding my epic quality stuff. The reason for my question is that I'm trying to automate our clanbot to clear out the junk in the stash. So I can now let her leave good food/drink for my clannies to use, but pull the crap and just autosell it.

Thanks for this, it made my week.

[edit]
This works just as well with cleaner code

Code:
foreach it in $items[]
	if ((it.quality=="epic") & (item_amount(it) > 0))
           'DoStuff';
 
Last edited:
Top