Removing an item from store

Is there a way, within a script to remove an item from your store in the mall?

I know there is functionality within the store manager to do it manually, but i didn't manage to find an Ash or CLI command for it.

Thanks.
 

StDoodle

Minion
To the best of my knowledge, there is no way to take items out, just to put them in (and reprice them). Would be nice to have take_shop(), I agree.
 

zarqon

Well-known member
I recently wanted to clear out a character's store. It took me 20 minutes of clicking the "remove items" buttons in mafia's store manager interface. I agree, this would be nice.
 

heeheehee

Developer
Staff member
You could always use these functions (add to ZLib? :) ):

Code:
take_shop(item i) {
   visit_url("managestore.php?action=take&whichitem="+i.to_int()+"&pwd");
}

Code:
take_shop_all(item i) {
   visit_url("managestore.php?action=takeall&whichitem="+i.to_int()+"&pwd");
}

Then the only problem is that there's no "get_store()" function that returns your mall store's inventory. I guess you could loop through the database of items, using something like
Code:
foreach i in $items[] {
   if(shop_amount(i)>0) take_shop_all(i);
}
 

Bale

Minion
Will that work? You're sure that mafia will not block that visit_url() for going to managestore.php?
 

fronobulax

Developer
Staff member
This particular project appeals to me because it is both helpful to the community and would help answer the question - how do I add a new ash function to mafia?. I make no promises or guarantees but it is pretty high on my "to do" list and might even get some time this weekend as long as I don't obsess about my mafia display case or get sucked into League of Legends in a futile effort to improve my play there.
 

Bale

Minion
Post the diff file as a proposed feature here, making sure to adhere to the same programming style as in the rest of kolMafia to maintain consistency. Don't forget comments.

One of the devs will eventually look it over and decide if they like it.
 

heeheehee

Developer
Staff member
Just tested it using ash foreach i in $items[] { if(shop_amount(i)>0) visit_url("managestore.php?action=takeall&whichitem="+i.to_int()+"&pwd"); }
and it emptied my mall store. Has there been a revision which allows this now, or was it never blocked in the first place?
 

StDoodle

Minion
FWIW, I figured put_shop() must allow you to remove items from your store by specifying a negative quantity, as it seemed odd that there was no take_shop() function. Alas, I was wrong.
 

jasonharper

Developer
I think the main reason there's no take_shop() function is that the game doesn't provide any interface for removing an arbitrary number of an item from your store - it's either one or all. Providing the usual (quantity, item) parameters for such a function would force it to be a lot less server-friendly than the other item transfer functions.
 

StDoodle

Minion
I think the main reason there's no take_shop() function is that the game doesn't provide any interface for removing an arbitrary number of an item from your store - it's either one or all. Providing the usual (quantity, item) parameters for such a function would force it to be a lot less server-friendly than the other item transfer functions.

Just to think outside the box a little, it would only require one additional hit; just cache the current price, qty & limit; remove all if not removing 1; put the difference back in the shop with the previous price & limit.
 

zarqon

Well-known member
Just tested it ... and it emptied my mall store.

Wow, that's unexpected -- I had thought managestore.php was blocked. This probably shouldn't be allowed -- or at least the min-price information should be stripped from the page in the return value of visit_url().

Hmmm... actually, I like this idea a great deal. Rather than block mall pages entirely, limit their uses by removing information that could be used to mallbot.

I also like StDoodle's idea for a smart ASH take_shop() to grant better handling than KoL's native handling while minimizing server hits. We could write one using ASH in its stead, but I'd rather see access to managestore.php disallowed (or filtered).
 

heeheehee

Developer
Staff member
Actually... the min-price info is in manageprices.php, which I use for a relay-override script. Although I agree, that would be very mall-bot-exploitable (I've already pretty much set out the framework for getting and comparing the price of an item to the minimum mall price... Gah!)
 

Bale

Minion
There's definitely mall_bot applicable application in comparing the min-price in manageprices.php to mafia's mall_price().
 

heeheehee

Developer
Staff member
Yes, but let's not discuss it -- I think we're getting a bit off-topic, here. (This is supposed to be about taking stuff from the shop, after all...)
 

zarqon

Well-known member
Yeah, looks like managestore.php doesn't need to be blocked. I'd thought this discussion had exposed a greater weakness which made writing take_shop() in ASH irrelevant, but I guess it's still a reasonable thing do do in ASH. The only slightly tricky part is caching your store data for removing multiple items.
 

heeheehee

Developer
Staff member
Okay. Here's the final version of take_shop(), complete with error-checking and done completely without regular expressions (Just for you, zarqon):
Code:
boolean take_shop(int i, item it) {
   int qty = shop_amount(it);
   if(!have_shop()) {
      print("You don't have a shop, so you can't take stuff from it!","red");
      return false;
   }
   if(qty < 1) {
      print("You don't have any "+it.to_plural()+" in your store!","red");
      return false;
   }
   if(i > qty || i < 1) {
      print("You can't take that many "+it.to_plural()+" from your store!","red");
      return false;
   }
   if(i == 1) {
      visit_url("managestore.php?action=take&whichitem="+it.to_int());
      return true;
   }
   if(i == qty) {
      visit_url("managestore.php?action=takeall&whichitem="+it.to_int());
      return true;
   }
   buffer mall;
   mall.append(visit_url("managestore.php"));
   mall.delete(0, mall.index_of("Store Inventory:")+154);
   mall.delete(mall.index_of("</table>"), mall.length());
     string str = mall.substring(mall.index_of(it.to_string()),mall.length());
   str = str.substring(str.index_of("</td><td>")+9,str.index_of("</td></tr>"));
   string price = str.substring(0, str.index_of("</td><td>"));
   string lim = str.substring(str.index_of("</td><td>")+9, str.index_of("</td><td><a href="));
   if(lim=="<font size=1>(unlimited)</font>  ") lim = "0";
   visit_url("managestore.php?action=takeall&whichitem="+it.to_int());
   return put_shop( price.to_int(), lim.to_int(), qty-i, it );
}
 

zarqon

Well-known member
Nice!

I'd suggest that we don't call shop_amount() in this function, since that hits the server every time, and anyone removing an item from the shop would already pass shop_amount() for i. Instead, flag item_amount(), visit the URL to pull one or all, then return false if you didn't get enough, or put the difference back in if you got too many:

Code:
boolean take_shop(int i, item it) {
   if (!can_interact() || !have_shop() || i < 1) return false;
   print("Pulling "+i+" "+to_plural(it)+" from your shop...");
   int target = item_amount(it) + i;
   if (i == 1) {
      visit_url("managestore.php?action=take&whichitem="+it.to_int());
      return (item_amount(it) == target);
   }
   buffer mall;
   mall.append(visit_url("managestore.php"));
   mall.delete(0, mall.index_of("Store Inventory:")+154);
   mall.delete(mall.index_of("</table>"), mall.length());
     string str = mall.substring(mall.index_of(it.to_string()),mall.length());
   str = str.substring(str.index_of("</td><td>")+9,str.index_of("</td></tr>"));
   string price = str.substring(0, str.index_of("</td><td>"));
   string lim = str.substring(str.index_of("</td><td>")+9, str.index_of("</td><td><a href="));
   if(lim=="<font size=1>(unlimited)</font>  ") lim = "0";
   visit_url("managestore.php?action=takeall&whichitem="+it.to_int());
   if (item_amount(it) > target) 
      put_shop(price.to_int(), lim.to_int(), item_amount(it) - target), it);
   return (item_amount(it) == target);
}

I'm already adding this function to one of my scripts! Very handy.
 
Last edited:

heeheehee

Developer
Staff member
Interesting workaround -- so item_amount doesn't hit the server? Makes sense for inventory to be cached (get_inventory() would take much longer if it weren't, I'd think).

Might I ask which script now uses this function? I doubt that it'd be used often enough to warrant being included in ZLib, but it'd still be a nice addition.
 
Top