PDA

View Full Version : Best sushi for profit



Winterbay
01-25-2011, 10:12 AM
Sushi 2.1

A while ago I bought dj_d's ascencion scripts in order to get to the farm-script (because I was too lazy to make one myself) and it states in the script that it does not yet handle Underwater adventuring.

I made some slight changes to it in order to make it actually take the sea into consideration if available and in this process realised that a good way of predicting what sushi to eat while farming would be a good thing to have. I thus started working on a script that has been working nicely for me for a while.

Requires zlib (http://kolmafia.us/showthread.php?2072-ZLib-Zarqon-s-useful-function-library).

Features:

Given a value_of_adventure, goes through all potential sushis (including simple fish meat) with and without the two sake versions and sorts by potential profit.
Can use this information to eat that same sushi. It then eats as many of it as possible.
Given a name of a sushi, or part of a name, returns the total cost for it.
Sets two boolean zlib-variables at first run, sushi_debug for some debug-printing and sushi_askme which if set to true will pop a question if you try to call it to eat without having a sushi rolling mat.
Also sets an integer zlib-variable, sushi_fish_juice_multiplier, which controls the relative value of fish juice boxes, defaults to 8


How to use:

sushi -1
Prints out a pretty list of all sushis, their total cost, turns of fishy given and average adventures gained from it.


sushi value_of_adventure
Fills you up with the best sushi (up to your max fullness). Yay for userfriendliness!
If you set sushi_onhand to true this will only eat things you can make from your inventory.


ash import <sushi.ash>; cost_of_sushi(string name)
Returns the cost of all sushis that contains name. Can also be called with an added boolean if you just want the one name (must be exact then).
A useful alias for this is:


sushicost => ash import <sushi.ash>; cost_of_sushi($string[%%]);



ash import <sushi.ash>; test_sushi(int value_of_adventure)
Returns a record containing the sushi that gives the highest profit together with turns of fishy gained and which type of booze (if any) to drink it with.


ash import <sushi.ash>; eat_sushi(int amount, int value_of_adventure, string booze)
Eats amount of sushi and drinks booze first. Booze can be:

infused sake
sake
no booze (or basically any other string)


This function is overloaded for easier use:


eat_sushi(int amount,int value_of_adventure) //Eats the specified amount of the best kind of sushi
eat_sushi(int value_of_adventure) //Fills you up with the best kind of sushi


I think that's it. Comments and bug reports are more than welcome :)

Version history:
v1.0 - First release
v1.2 - Added two overloaded functions for eat_sushi so that you do not need to specify all information unless so wanted (Thanks bale!). Also added a prettier output of the table of results (Shamelessly stolen from one of the TP-scripts and adapted).
v1.3 - Fixed a bug that would stop you from eating sushi if you were at maximum inebriety
v1.4 - Fixed a very small bug in the version check, it pointed to the wrong thread (and also borrowed some code form zlib).
v1.5 - Fixed (for real) the bug with eating at full inebriety. Also circumvented potential prolems with CLI-execute returning false while it should've returned true (I hope).
v1.6 - Include zlib, change check-version to zlib's version, add two zlib settings (sushi_debug for debug printing and sushi_askme for asking to stop if you have no mat). Only include anything above basic meat if you have a mat.
v1.7 - Include basic support for fish juice boxes, fix printing of stuff if you have no mat,fix sorting of sushi to use the correct sorted sushi and not the latest one, also refactor some code to be more pleasing and add a new zlib setting, sushi_fish_juice_multiplier, indicating how to value a fish juice box, default 8
v1.8: - Make sure that eat_sushi fills you up and make main take an integer. If this integer is -1 print out costs of all sushis, otherwise fill you up on the best possible sushi.
v1.9: - Incorporate Garbled's (Thanks!) code for only eating things you have on hand. This is controlled by a new zlib-setting, sushi_onhand which if set to true will make you only eat things you can make from inventory
v2.0: - Fix for upcoming changes to script parsing, i.e. sloppy code...
v2.1: - to_item($item) is a completely useless conversion. Don't use that...

Bale
03-25-2011, 06:35 AM
Finally found an excuse to try this out today. The script could be easier to use, but not more effective.

Winterbay
03-25-2011, 07:20 AM
Any ideas on how to improve ease of use would be very welcome. I'm especially unsatisfied with the output of the cost of all sushis and so on. I feel that would be much better as a table but I suck at html and the scripts I've looked at that uses that sort of output have not helped unfortunately :(

Bale
03-25-2011, 07:32 AM
Tables are pretty easy.

Just start with <table>
Then start and end each row with <tr> and </tr>
In each row you need to bracket each data cell with <td> and </td>
Finally end with </table>

For example:
<table>
<tr><td>Row one, cell one</td> <td> Row one, cell two </td> </tr>
<tr> <td>Row two, cell one</td> </tr>
</table>

Winterbay
03-25-2011, 09:29 AM
Hmm... I may have a rough outline now. How do you get one cell to take the place of four cells? I'd like to have the type of sushi in the table but at the moment it puts that name in cell 1 and leaves the rest of that row empty (no cell, no nothing) until the next row.

Edit: Never mind, I found it.

Bale
03-25-2011, 09:49 AM
I assume that what you found is <td colspan='4'>

Also, if you want to have a blank cell, use <td>&nbsp;</td>. Without the non-breaking space it will skip the cell instead of leaving it empty.

I just remembered to tell you that there's one important addendum to printing a table in KoLmafia. You need to do it with a single print_html() or else it won't work. I suggest defining output as a buffer or a string and build it up as you iterate. Then use a single print_html(output).

Winterbay
03-25-2011, 10:05 AM
Yeah. I managed to find and mangle part of one of the TP-scripts which used a lot of appends and then finally did a print html.

Bale
03-26-2011, 07:27 AM
To make this a little simpler to use I added the following 2 functions to my copy.


boolean eat_sushi(int amount,int value_of_adventure)
{
sorted_sushis test = test_sushi(value_of_adventure);
return eat_sushi(amount, value_of_adventure, test.booze);
}

boolean eat_sushi(int value_of_adventure)
{
return eat_sushi((fullness_limit() - my_fullness())/3, value_of_adventure);
}

That way I don't have to worry about things the script can calculate for me.

Winterbay
03-26-2011, 09:52 AM
That is a good idea. I think I have similar calls but in the script that calls it instead :)
Merging those two functions into the script is probably a better idea.

Winterbay
03-30-2011, 10:59 AM
Version 1.2 has been posted with Bale's functions added, a new prettier output and a version check.

Winterbay
05-10-2011, 08:59 AM
Version 1.3 has been uploaded and fixes a bug that would stop you from eating sushi if your inebriety was above what a sake needs.

Bale
05-10-2011, 09:08 AM
Since I'm in aftercore until the current world event ends I'm making good use of this script farming the sea. Such awesome meat to be made down there.

Thanks again for this script. It makes my sushi eating so much easier.


alias eatsushi => ashq import "sushi"; eat_sushi((fullness_limit() - my_fullness() -2)/ 3, 3500)

Winterbay
05-16-2011, 08:59 PM
Version 1.4 is live with a better version checking (it now correctly points to this thread and not to BCCascend... and is clickable!).

Winterbay
05-20-2011, 08:13 PM
Version 1.5 has been posted and should fix any potential problems with Mafia's CLI-execute not reporting the actual success or not of the command it is given.

Winterbay
10-22-2011, 09:26 PM
Version 1.6 has been uploaded and the script now requires zlib since it uses two zlib-variables.

* Setting "sushi_debug" to true (default is false) will create a "sushi.txt" with a dump of the scripts information in your datafolder.
* Setting "sushi_askme" to true (default is false) will prompt you as soon as you call a function that would eat anything if you do not have a mat.

The script now won't suggest any sushi above basic fish meat if you do not have a mat. I will probably add fish juice boxes as well in the near future but I don't have time at the moment.

Winterbay
10-24-2011, 11:56 AM
Version 1.7 uploaded with the following change log:

* Include basic support for fish juice boxes
* Fix printing of stuff if you have no mat
* Fix sorting of sushi to use the correct sorted sushi and not the latest sorted one
* Refactor some code to be more pleasing
* Add a new zlib setting, sushi_fish_juice_multiplier, indicating how to value a fish juice box, default 8

Currently (tested on an account without sushi mat) the breakpoint where the juice boxes appears to be better than basic fish-meat is a factor between 100 and 110. If anyone has any suggestions on how to weight the fish juice box better I'm all for it (sushis are weighted based on how many you can actually eat, slightly harder to do that for the boxes).

Banana Lord
11-25-2011, 09:27 AM
Is there a way to have it not use caviar? Often it's much cheaper to buy fish juice boxes.

EDIT: It also seems to favour the more expensive kinds of sake. I haven't actually calculated it, but is that really more profitable than using pete's sake?

Winterbay
11-25-2011, 11:24 AM
If you can come up with a good way to calculate the worth of a fish juice box I would be all ears. Currently it does a calcualtion based on your value_of_adventure multiplied by turngen+turns of fishy which automatically puts the juice at a disadvantage. The zlib-variable sushi_fish_juice_multiplier is thought as a way to compensate for this based on user preference.
Also: The box costs 20k meat at the moment and gives 20 turns of fishy while a maki with dragonfish caviar costs ~24k and gives 50 turns of fishy which is roughly twice the amount of fishy.

The always drinking of improved sake may actually be a bug. I need to look at that code some more, but I sense an error from a cursory look based on a sorting that happens.

Banana Lord
11-25-2011, 11:37 AM
The value of the juice box is going to change depending on what the user is doing (which, as you say, makes things tricky). If it was me, I would add an option along the lines of "sushi_use_caviar" and let the user decide. That way you could leave juice box-fuctionality out of the script altogether. Or maybe you could change the hypothetical setting above to "sushi_turnsOfFishy" and have the script acquire at least that many turns of fishy as cheaply as possible. My current solution is to run this script before ED, and then run a mini-script of my own creation after ED to use juice boxes to make have_effect($effect[fishy]) >= my_adventures().

Ah but when we compare caviar with the juice box what we're really interested in is turns of fishy. Caviar gives 5 turns of fishy for ~8K, while the box gives 20 turns for ~20K.

slyz
11-25-2011, 11:44 AM
The "price" of the maki should include the opportunity cost of using up fullness, shouldn't it?
You would need an average adventure per fullness (a user setting, probably). The opportunity cost would be:

(user adv per full - maki's adv per full) * fullness * ValueOfAventure

Does this sound right?

Banana Lord
11-25-2011, 11:52 AM
I guess it depends how technical you want to get with it. On a complexity scale of 1 to EatDrink.ash I know which end I'd choose :P. When I run this script I expect to get a reliable number of turns of fishy for a good price. It's not going to worry me if the script isn't perfectly optimal, as long as I have more or less as many turns of fishy as I was expecting to get and as long as I didn't spend too much meat. Obviously that's just a personal insight, other people may use the script completely differently.

slyz
11-25-2011, 12:06 PM
Why do simple when you can do complicated!

Winterbay
11-25-2011, 01:18 PM
That sounds about right. I'll have to look at that some more when I get some time over (moving houses really eats up your time).
Also, on of my favorite quotes is: "There is nothing that is so simple, that you can't make it more complicated if you try"

garbled
01-16-2012, 04:50 PM
I played about with this a little today. It kept trying to make melon-infused sake, but I didn't have the ingredients to do so. I had berry-infused sake in my inventory, but it refused to drink that.

Banana Lord
01-16-2012, 07:21 PM
Could have been because it decided that melon-infused sake was better than berry-infused sake, as you might make more meat from buying the melon-infused and selling the berry-infused.

Winterbay
01-16-2012, 08:49 PM
The script currently ignores everything you have in your inventory and goes on mallprices only, so if one sake is cheaper in the mall than another it will use that even if you have another, of similar quality, in your inventory already.

garbled
01-17-2012, 06:33 PM
I'm also having trouble figuring out how to call it. If I want to eat to maximum fullness with it, at 1000mpa, how do I call it? When I just specify 1000mpa, it just eats one sushi.

Winterbay
01-17-2012, 08:44 PM
Something like this should work in a script that imports sushi.ash.


sorted_sushis best_sushi;
best_sushi = test_sushi(1000);
eat_sushi((fullness_limit()-current_fullness())/best_sushi.fullness, 1000);


or as a CLI-command:

ash import sushi.ash; sorted_sushis best_sushi; best_sushi = test_sushi(1000); eat_sushi((fullness_limit()-current_fullness())/best_sushi.fullness, 1000);

Bale
01-19-2012, 05:58 AM
I'm also having trouble figuring out how to call it. If I want to eat to maximum fullness with it, at 1000mpa, how do I call it? When I just specify 1000mpa, it just eats one sushi.

LoL! The script works great, but it is definitely not user friendly.

Winterbay
01-19-2012, 06:10 AM
I should perhaps make a friendly function that just fills you up with Sushi... Also, I should look into getting fish juice boxes supported properly as well.

Edit: It's been a while since I looked at the script. It should be enough to call:

ash import sushi.ash; eat_sushi(1000);

Which should eat as many sushis as you can (assuming that each sushi you eat has a 3-fullness). I've updated the script locally to do exactly what I posted above when calling that function in case 3 is not the fullness of your choosen sushi.

Winterbay
01-19-2012, 06:50 AM
Actually: Version 1.8 released which makes the script easier to use for casual usage. If you call the script and specify any other number than -1 it'll fill you right up. If you specify -1 it'll print the same list it did before when called without an argument. Also includes the abovementioned fix for eat_sushi().

garbled
01-20-2012, 02:39 PM
I was calling sushi from a script today, and had it fill me up, and it failed. It decided to make 5 slick maki I think, and I only had 4 white rice, so it punted and did nothing. I'm thinking maybe eat_sushi needs to happen in some kind of loop, where it re-evaluates your inventory after making each item?

Winterbay
01-20-2012, 05:48 PM
Hmmm... Do you have any cli-output or log-output that you can post? Also, is Mafia allowed to buy from the mall at will?

garbled
01-21-2012, 02:45 PM
Hrmm.. no.. I don't have mafia setup to allow mallbuying at will. I prefer to farm my daily food as part of my activities. So I guess that I would typically encounter a scenario where I only have X rice, Y seaweed, N salt, etc. What seems to happen, is it calculates that the best sushi it can make is, say, salty slick maki, but I only have enough ingredients for 1, then I call it to fill me up to max fullness with sorted_sushis.best, and it tries to make 5. In an ideal world, it would either calculate quantity in total up front, or loop, re-calculating best on each iteration.

Unfortunately, my logs don't really show anything.. If it happens again, I'll grab the cli output, but basically, it tried to make 5 of something, and I only had 4 rice on hand.

Winterbay
01-21-2012, 08:55 PM
Well, if you don't allow purchases from the mall then there's the problem :)
The script is currently designed around that presumption and will gladly fail trying to buy things it can't. It could perhaps detect if it's allowed to buy from the mall and if not see what it can do with what it has, but that is a whole new level of complexity I'm not sure my programming skills are up to.

Winterbay
02-14-2012, 06:44 AM
Version 1.9 released which incorporates Garbled's code for only eating things you can make from inventory. Enjoy :)

Winterbay
03-05-2012, 12:34 PM
Version 2.0 released that fixes the small compile warning that recently showed up due to a missing return value.

Winterbay
03-13-2012, 09:33 PM
Version 2.1 released to fix usage of to_item($item) which no longer works and which was a stupid thing to use from the beginning anyway...