PriceAdvisor: Maximize your profits

I think your suggestions and requests are excellent ones. I was kinda thinking of changing the way things are represented anyway -- as you point out, the string + float record is very limited in what information it provides you. My current guess at the new record is something like this:
Code:
record pa_advice
{
	item it;
	int quantity;  // use 0 to signal "expected result" style
	
	int [item] required;
	pa_advice [item] result;
	
	string action;
	float profit;
};

This looks very much like you have proposed, but also accounts for quantity (playing into your first request), required items (other ingredients, keys, etc.), and resulting items.

I hope to get some serious work put into PA in the next few days which should make it much friendlier on the scripting and executing side.

Edit: In the spirit of _obeyBuyLimit and _conservative being "don't be so ridiculous" flags, I think they should rule out actions that require untradeable items, too. Any objections? A slightly more lax rule-out would allow recommendations of untradeable items that you actually have -- would this be better?
 
Last edited:

heeheehee

Developer
Staff member
Code:
record pa_advice
{
	item it;
	int quantity;  // use 0 to signal "expected result" style
	
	int [item] required;
	pa_advice [item] result;
	
	string action;
	float profit;
};
Recursion. Huh. Interesting. Would this be intended behavior? (I can see how it would be, and yet it just doesn't seem right.)

And, uhm, if you're overhauling the script, can you add a variable that allows the user to toggle between ASH output and CLI output? (If it's too much effort, don't bother.) It'd totally bypass this problem, and it'd probably help at least some scripters in using this resource.
 

zarqon

Well-known member
I foresee another issue now that quantity is a factor. The script should take into consideration items that can be multi-used to create other items.

For example, if you are getting advice for 7 bit of clingfilms, don't present "create 7 clingfilm slippers" as an option -- only "create 1 clingfilm slippers."

Just thought I'd throw that into the mix! :)

EDIT: I suppose if the quantity is higher, a good option might be to obtain the necessary parts to make one more of the multi-use item. For example with 11 clingfilms, you could buy 3 more clingfilms so that you could make 2 slippers. But creating one per item borders on mallbotting.
 
Last edited:
heeheehee: I haven't actually tested if recursive records work yet. It's entirely possible they don't.

It might make sense to have all executable-style output be ash, I suppose. I know your reasons for wanting ash output, if that were to be available, would there be any reason to have cli-executable style too?

zarqon: Excellent suggestion, much more efficient (and massively less ridiculous) than a naive approach would be.
 

mredge73

Member
Having the output formatted in a way an ash script can better make use of it would be much more desirable than the current way you are doing your cli executable.

For example if I have a large list of different items at varying quantities, processing them one at a time with each item having its own cli executable command will create a large amount of server hits and take a really long time. But with an output that an ash script can use, the scripter can group all mall sell items together and execute 11 different items at a time at whatever quantity that he desires. This can reduce server hits and speed 11 times as many as executing each item one at a time. This is very significant when you are executing this on every tradeable item in you inventory or in your clan stash. See Bales's OCD inventory control for this example.
 
I'm definitely interested in minimizing server hits. You're absolutely right that PA is very bad at that right now.

I really appreciate all this feedback and will do my best to incorporate it!
 

heeheehee

Developer
Staff member
Granted, the only reasons I can see for preserving CLI output are that 1) it won't break any pre-existing scripts, and that 2) CLI output has those nice negative numbers to indicate all but a certain number. The second one is largely useless when you take into account what ASH can do, but it's still nice.
 

slyz

Developer
test.ash:
Code:
record rec_test
{
	int a;
	int [item] b;
	rec_test [item] c;
	float d;
};

rec_test test1;
test1.a = 5;
test1.b["twinkly wad"] = 25;
test1.d = 23.4;

rec_test test2;
test2.a = 2;
test2.b["hot wad"] = 4;
test2.c["hot hi mein"] = test1;
test2.d = 13.9;


void main() {
	print("test2.c ="+test2.c["hot hi mein"]);
}

gCLI output:
Code:
> call test.ash

Type name expected (test.ash, line 5)

The recursive rec definition doesn't work. A challenge for Veracity?
 

jasonharper

Developer
ASH is fundamentally incapable of having a record type with a field of the same type. Since null values are never allowed, initializing such a record would immediately create another record for the recursive field, which in turn would create a record for its copy of the field, and so on until either the heap or stack space is exhausted.

Now, that's not exactly what you're trying to do here - your recursive record is actually a value in a map that's initially going to have no entries, so it wouldn't take an infinite amount of memory to initialize the record. However, I'm not sure there's any practical way to allow a recursive definition in this case, that wouldn't also allow it in the cases where it would cause a crash.
 
There's no real need for a recursive record definition here (and I'm not surprised it didn't work).

I've found a work-around (which is also a better way) -- pretty easily, really. I'm already keeping a pa_advice [item] cache (well, pa_advice [item][boolean], but whatever), so the "results" member can more-or-less be a list of items which I then use as indices into the cache.

There are issues there with making sure to cache a really representative version of the advice (with quantity 1, for example) and then changing it as necessary, but I'm confident they'll work out.
 

heeheehee

Developer
Staff member
I suppose if you were worried about how current the data was, you could add a string date to the record and store the current date when you create the cached data. Then, if cache[it].date is more than, say, 3 days old, you could replace cache[it] with more recent advice.

Naturally, I probably completely missed your point. Odds are, you'd do all the integer replacing at the end, so you'd just need to cache the data just before the replacement.

[[Totally missed this earlier, but zarqon -- clingfilm isn't tradeable. So "buy 3 more clingfilm" would be hilariously impossible advice. Naturally, the only tradeable items that can be multi-used to produce other items (that I can think of at the moment) are palm fronds and mummy wrappings.]]
 

Veracity

Developer
Staff member
long skinny balloons
handfuls (and bricks) of sand
lewd playing cards
turtlemail bits
interesting-looking twigs.
 

slyz

Developer
I don't think it's up to aqualectrix to make all of PA's advices script-executable and foolproof. After all, PA will always give some sort of dummy advice or other. We should be the ones making sure nothing stupid comes out of using PA's advice:

Code:
> pa imagin hamster

Hodgman's imaginary hamster:
smash 1 Hodgman's imaginary hamster; mallsell 1 epic wad: 99995.0 meat

Smashed hamster, anyone? Should aqua hard-code this in ? And all the other tiny exceptions?

I think it's up to script users to come up with a nice framework for PA that allows people to choose what to ask advice for, which advice not to follow, or which is absurd, and how to parse/execute PA's advices intelligently (like the multiusing advice).

On the other hand, aqualectrix seems to be a very able codstress (I feel about recursion the same way Zarqon feels about regex), and I have the feeling she will be delighted to implement anything we throw at her.
 
Last edited:

zarqon

Well-known member
I agree -- and that is the correct result for the hamster. Scripts that are importing this advice should have some logic for deciding when to actually follow it.

My point was that suggesting that you buy all the components of an item merely to assemble them and then sell the item is actually bad advice. Also, the solution could be programmatic -- using get_ingredients() -- not a bunch of exceptions. There are quite a few items besides multi-usables that require multiples (asshats, some of the tamed turtle gear, for example), and this would even apply if there were multiple ingredient types (i.e. star items).

Smashing results would not be solvable using get_ingredients(), so there would need to be similar handling added for the various powders and nuggets. If I get advice for 5 nuggets, buying 20 more nuggets to create 5 wads would be a bad result.
 

slyz

Developer
My point was that suggesting that you buy all the components of an item merely to assemble them and then sell the item is actually bad advice.

I don't really agree: for a given multi-useable item, acquiring enough of that item to make something that yields profit is good advice. Buying 23 bum cheeks to apply the advice to the 23 bum cheeks in your inventory isn't an intelligent way of dealing with that advice, though. My point was that it should be dealt with in the container script, not in PA.

A price_advice structured as a sequence of operations on a given quantity of different items (instead of a CLI or ash executable string) would make using the advice easier to deal with, although the current CLI output can be reversed engineered already.

Code:
rec price_advice {
	item it;
	
	int [item] required; // list and quantities of items needed
	string [int] steps; // steps[0] = acquire this, steps[1] make that etc ...
	
	string action;  // still useful, to show to users if you want them
                           //to decide if that advice is good
	float profit;
}

It would be possible to construct something like this by parsing the current CLI ouput, although it wouldn't deal with the 'sell 1.5 knob pasty' problem. I haven't put any thought into this though, since aqua seems to be well on track to deal with all this =)
 

zarqon

Well-known member
I don't really agree: for a given multi-useable item, acquiring enough of that item to make something that yields profit is good advice.

I think we do agree, actually. Purchasing ingredients to create items out of your advice items is not a problem; the problem is purchasing enough ingredients to make extra items in excess of what you need to use all of the advice items. It is a problem not because it is unprofitable (which it isn't) but because it borders on mallbotting and it is counterintuitive behavior (imagine getting advice for 50 lewd playing cards only to have it suggest buying 2550 more cards and creating 50 decks! Rather than just buying two cards and creating one deck!).

If you are getting advice for a single bum cheek, it may be that the best option is to buy another bum cheek so you can make an asshat. But if you are getting advice for 21 bum cheeks, the advice should be to buy a single bum cheek and then make 11 asshats. NOT buy 21 bum cheeks to make 21 asshats -- in that case the script would be buying, assembling, and then reselling components beyond the target amount, rather than buying missing ingredients to make things from the target amount.

This is only an issue now that a quantity can be specified. But it is an issue that this script should address.
 

slyz

Developer
I see PA as giving generic advice for one of a given item, generic advice that then has to be treated by the user (or the user script), intelligently (or not). The advice for 23 bum cheeks isn't fundamentally different from the advice for only 1 (the profit comes from smashing an asshat). It just need to be applied smartly.
 

heeheehee

Developer
Staff member
At this point, does it become less of an advisor and more of a counselor? (Disclaimer did say "PriceAdvisor can't think for you", but with the future update it very well may.)

In the case of the lewd playing cards, since you would now supply a quantity, it should probably tell you to buy(52-qty,$item[lewd],PriceLimit). The larger problem would probably be the case of bum cheeks -- that'd be noticeably more code than the simple one-line workaround. (Incidentally, would PA even suggest making the deck? It's non-tradeable, and so the only things that you could then do with it to make some meat would be to smash it. Not a great idea, eh?)

The simplest workaround I can think of for bum cheeks and other similar items would be to hardcode an exception. Or maybe if(ingredient[concoct].it1==ingredient[concoct].it2) int create_qty[concoct] = floor(qty/2);, but there'd have to be more comprehensive checking for really odd cases where a repeated ingredient is somewhere not in the first two keys (Corrupt club of corrupt corruption? But I'm fairly sure that's nontradeable).

But yeah, I want to see aqualectricis implementation of quantities! Exciting stuff!
 

zarqon

Well-known member
Simply put, the script should attempt to create ceil(quantity / get_ingredients[item]) of the target item, acquiring ceil(quantity / get_ingredients[item])*get_ingredients[item] - item_amount(item) for each ingredient. No special cases necessary! But, there would need to be separate handling for powder/nugget upgrades.
 
Top