Buy Script Intended Use

Saklad5

Member
I’ve gathered that a buyScript script is meant to resolve to a boolean value, where “true” means “purchase” and “false” means “create”. However, I’m interested in creating a buyScript that can actually procure the items. If running the script changes the quantity of items you have, would KoLmafia recognize the change? I do not want KoLmafia to acquire more items than necessary.
 

Pazleysox

Member
I’ve gathered that a buyScript script is meant to resolve to a boolean value, where “true” means “purchase” and “false” means “create”. However, I’m interested in creating a buyScript that can actually procure the items. If running the script changes the quantity of items you have, would KoLmafia recognize the change? I do not want KoLmafia to acquire more items than necessary.

If I understand your question correctly, you want your script to check if you have Y items. If you have X, you want to purchase up to Y, then create Z.

In my experience Mafia does not over buy unless you tell it to. The eat drink portion of my daily script looks for the multiple items it needs to create the food it wants. If o already have some of the items, it only buys what it needs to make up the rest.

If needed, you can always refresh your inventory after each creation, but I'm not sure this is needed, because mafia will already know everything you have. (Does this cause a server hit?). I believe the only time this is needed is when someone sends you an item.
 

Saklad5

Member
I want to override the behavior of the retrieve_item() to use the Clan Stash for items that are min-priced in the mall, along with a few other conditions according to the rules of my clan.

The min-price bit isn’t technically a rule of my clan, but that should make it obvious what I’m going for here. If KoLmafia is planning to buy something, potentially use the Clan Stash instead.

The built-in behavior for using the Clan Stash is extremely clumsy, without even paying attention to my ability to take items. I’ve made a few feature requests for changing it, but there doesn’t seem to be much interest.
 
Last edited:

Pazleysox

Member
I'm not really sure what you're trying to do, but can't you run a check for stuff in your stash first?

I have a free fights script that pulls up to 3 items from the stash, and puts them back when it's done. It wouldn't be that hard to do.

Instead of using retrieve_item you could do this:
PHP:
if ($item[yellow pixel potion].available_amount() < 1) // I have 0 left.  Lets do something about it.
  {
   int ineed = 10; // need 10 pixels to make the potion
   int ihave = $item[yellow pixel].available_amount(); //this is how many I have on hand
   refresh_stash(); 
   int stashhas = stash_amount($item[yellow pixel]); // this is how many the clan stash has
   ineed = ihave - stashhas; // this will figure out how many I can grab from the stash up to what I need.
   take_stash(ineed, $item[yellow pixel]); // take what the stash has
   ineed = 10 - $item[yellow pixel].available_amount(); // I needed 10
      if ($item[yellow pixel].available_amount() < 10) // if I still don't have the 10 I need, I will buy just what I need to get me there.
         {
          buy(ineed, $item[yellow pixel]);
         }
   }
create (1, $item[yellow pixel potion]);

There's probably multiple ways of doing this. This is just the first one I came up with in a pinch. I tested this exact code, and it worked as expected.
 

heeheehee

Developer
Staff member
I’ve gathered that a buyScript script is meant to resolve to a boolean value, where “true” means “purchase” and “false” means “create”. However, I’m interested in creating a buyScript that can actually procure the items. If running the script changes the quantity of items you have, would KoLmafia recognize the change? I do not want KoLmafia to acquire more items than necessary.

While this should work as you intend (it looks like InventoryManager checks if target - inventory.getCount(item) <= 0 after all existing calls to invokeBuyScript), IMO this is an implementation detail that you shouldn't rely upon, as its behavior may change with a refactor.

I'm not really sure what you're trying to do, but can't you run a check for stuff in your stash first?

I have a free fights script that pulls up to 3 items from the stash, and puts them back when it's done. It wouldn't be that hard to do.

Instead of using retrieve_item you could do this:
PHP:
if ($item[yellow pixel potion].available_amount() < 1) // I have 0 left.  Lets do something about it.
  {
   int ineed = 10; // need 10 pixels to make the potion
   int ihave = $item[yellow pixel].available_amount(); //this is how many I have on hand
   refresh_stash(); 
   int stashhas = stash_amount($item[yellow pixel]); // this is how many the clan stash has
   ineed = ihave - stashhas; // this will figure out how many I can grab from the stash up to what I need.
   take_stash(ineed, $item[yellow pixel]); // take what the stash has
   ineed = 10 - $item[yellow pixel].available_amount(); // I needed 10
      if ($item[yellow pixel].available_amount() < 10) // if I still don't have the 10 I need, I will buy just what I need to get me there.
         {
          buy(ineed, $item[yellow pixel]);
         }
   }
create (1, $item[yellow pixel potion]);

There's probably multiple ways of doing this. This is just the first one I came up with in a pinch. I tested this exact code, and it worked as expected.

That doesn't look like it computes ineed correctly before taking from stash. Presumably you'd want ineed = ineed - ihave (which is basically just 10 - available_amount(YELLOW_PIXEL), then take_stash(min(ineed, stashhas), YELLOW_PIXEL).
 

Saklad5

Member
While this should work as you intend (it looks like InventoryManager checks if target - inventory.getCount(item) <= 0 after all existing calls to invokeBuyScript), IMO this is an implementation detail that you shouldn't rely upon, as its behavior may change with a refactor.

I saw that, and came to a similar conclusion. While I’m fairly sure this would work, I don’t want to do it unless it is actually supposed to work that way. Anything else is undefined behavior, and this is a very dangerous thing to mess up. That’s why this thread is titled “Buy Script Intended Use”.
 

heeheehee

Developer
Staff member
One oft-cited example for a buyScript is where Mafia doesn't truly account for the value of creation, e.g. in the case of a Sauceror crafting sauce potions in triplicate. Natively, Mafia simply compares the cost of a reagent + whatever material, then compares that to the cost of one item in the mall. There have been times in the past where the mall price has provided plenty of opportunity for Sauceror arbitrage (although one of my personal projects has been to drastically limit that inefficiency in the market).

example: glass of goat's milk costs 2000, scrumptious reagent costs 1000, milk of magnesium costs 1500. retrieveItem will by default always buy from the mall, even though buying the ingredients and making manually is more cost-effective (especially since it's a potion you _will_ use).
 

Saklad5

Member
In summary: Buy Scripts are implemented with the assumption that KoLmafia’s default behavior for creating or purchasing items is desired, and they are only meant to choose between the two. Anything beyond that is undefined behavior, and should not be relied upon.
 
Top