Save items from pvp theft

I added a few embellishments:
Code:
int minimum_value = 1000; // Closet everything stealable worth more than this; 0 = closet everything stealable.
boolean verbose = true; // false = Only print the items that gonna be or woulda been closeted.


void main(string show_or_go)
{

    boolean go = (show_or_go.to_lower_case() == "go"); // Anything other than "go" = just show what woulda happened.
    if (minimum_value < 0) abort ("A minimum_value less than zero makes no sense at all.");
    int count_cheap, count_closet, count_total, count_unstealable;
    int [item] inv = get_inventory();
    boolean [item] pvp_unimportant = $items[tenderizing hammer, dramatic range, Queue Du Coq cocktailcrafting kit];
    boolean is_stealable(item it) { return is_tradeable(it) && autosell_price(it) > 0; }
    foreach it, qty in inv {
        int price = -1;
        if (is_stealable(it) && !(pvp_unimportant contains it)) price = historical_price(it);
        if (price < 0) {
            count_unstealable += 1;
            if (verbose) print_html("<span color=\"green\">Not closeting " + qty + " " + (qty == 1 ? to_string(it) + ", it's" : to_plural(it)  + ", they're") + " unstealable.</span>");
        } else if (price >= minimum_value) {
            count_closet += 1;
            print_html("<span color=\"teal\">" + (go ? "Gonna closet " : "Woulda closeted ") + qty + " " + (qty == 1 ? to_string(it) : to_plural(it)) + ".</span>");
            if (go) put_closet(qty, it);
        } else if (price < minimum_value) {
            count_cheap += 1;
            if (verbose) print_html("<span color=\"red\">Not worth closeting " + qty + " " + (qty == 1 ? to_string(it) : to_plural(it)) + ".</span>");
        }
    }
    count_total = count_closet + count_cheap + count_unstealable;
    if (count_closet > 0) print("+ " + count_closet + (go ? "" : " woulda been") + " closeted", "teal");
    if (count_cheap > 0) print("+ " + count_cheap + " worth less than " + minimum_value + " meat", "red");
    if (count_unstealable > 0) print("+ " + count_unstealable + " unstealable", "green");
    if (count_total > 0) print(" = " +  count_total + " of " + count(inv) + " items accounted for.");
    print_html("<b>Done<a href=\"http://kolmafia.us/showthread.php?10059\">!</a></b>");
}
The first time you run it, use any argument other than "go" and it'll do a dry run so you can see whether you like the verbosity and/or 1000 meat setting. Setting verbosity to false hides the unstealable and cheap items, but it will always show the closeted items and the brief report at the end.

I think it might be worth adding this functionality to an autoselling script, or vice versa.
 

Attachments

Last edited:
Nworbetan, I love you very, very much right now.

Being able to do a dry run - awesome
Having verbosity turned on for that first categorizing run - awesome and enlightening
Being able to turn off verbosity - awesome
Having including a link to the script that I could click and have it download because I still can't figure out how to make it a working script when someone just posts the code in their post - most awesome ever

Thank you very much, as well as thanks to the folks whose work you built on.

You folks make every day playing a little more amazing.

Edited to add a question and avoid nasty double posting:

Where would I add in that script an item that would normally be Closeted, because it meets all the conditions, but I would rather not have to take it out of the Closet each and every day so I'm okay with the script ignoring it? Item I'm specifically thinking of is a tiny plastic bitchin' meatcar?

~Aramada
 
Last edited:
You can add items to the line:
Code:
[LEFT][COLOR=#333333]boolean [item] pvp_unimportant = $items[tenderizing hammer, dramatic range, Queue Du Coq cocktailcrafting kit, tiny plastic bitchin' meatcar];[/COLOR][/LEFT]

And that will stop them from being closeted. Capitalization isn't important, but spelling kind of is. Fuzzy matching can be kind of a double-edged sword sometimes if you're not expecting it.
 
So I've been using Nworbetan's Protection script pretty much daily for the past 4 months. Today, it failed. As in, I ran it and this popped up: Unknown variable 'than' (protection.ash, line 6)

I deleted my copy from my scripts file, and redownloaded the one from this thread...ran it, and got the exact same message.

I have no idea what changed, why "than" is suddenly an unknown variable, but I love, love, love this script and would very much like it if it could be made to work again. Is there something I can do to fix it?

~Aramada
 
Just downloaded it from post 21, changed the line breaks, and ran it without problems...
+ 25 woulda been closeted
+ 263 worth less than 1000 meat
+ 68 unstealable
= 356 of 356 items accounted for.
Done!
Attaching the version I just ran. Maybe your system just decided it doesn't like *nix line breaks?
 

Attachments

Maybe your system just decided it doesn't like *nix line breaks?

Apparently that was it. Downloaded the one you attached and it was perfectly fine with it. WHY it just decided it doesn't like *nix line breaks? Hell if I know.

Thanks for your lightning fast trouble shooting, Theraze!

~Aramada
 
I added a few embellishments:
Code:
int minimum_value = 1000; // Closet everything stealable worth more than this; 0 = closet everything stealable.
boolean verbose = true; // false = Only print the items that gonna be or woulda been closeted.


void main(string show_or_go)
{

    boolean go = (show_or_go.to_lower_case() == "go"); // Anything other than "go" = just show what woulda happened.
    if (minimum_value < 0) abort ("A minimum_value less than zero makes no sense at all.");
    int count_cheap, count_closet, count_total, count_unstealable;
    int [item] inv = get_inventory();
    boolean [item] pvp_unimportant = $items[tenderizing hammer, dramatic range, Queue Du Coq cocktailcrafting kit];
    boolean is_stealable(item it) { return is_tradeable(it) && autosell_price(it) > 0; }
    foreach it, qty in inv {
        int price = -1;
        if (is_stealable(it) && !(pvp_unimportant contains it)) price = historical_price(it);
        if (price < 0) {
            count_unstealable += 1;
            if (verbose) print_html("<span color=\"green\">Not closeting " + qty + " " + (qty == 1 ? to_string(it) + ", it's" : to_plural(it)  + ", they're") + " unstealable.</span>");
        } else if (price >= minimum_value) {
            count_closet += 1;
            print_html("<span color=\"teal\">" + (go ? "Gonna closet " : "Woulda closeted ") + qty + " " + (qty == 1 ? to_string(it) : to_plural(it)) + ".</span>");
            if (go) put_closet(qty, it);
        } else if (price < minimum_value) {
            count_cheap += 1;
            if (verbose) print_html("<span color=\"red\">Not worth closeting " + qty + " " + (qty == 1 ? to_string(it) : to_plural(it)) + ".</span>");
        }
    }
    count_total = count_closet + count_cheap + count_unstealable;
    if (count_closet > 0) print("+ " + count_closet + (go ? "" : " woulda been") + " closeted", "teal");
    if (count_cheap > 0) print("+ " + count_cheap + " worth less than " + minimum_value + " meat", "red");
    if (count_unstealable > 0) print("+ " + count_unstealable + " unstealable", "green");
    if (count_total > 0) print(" = " +  count_total + " of " + count(inv) + " items accounted for.");
    print_html("<b>Done<a href=\"http://kolmafia.us/showthread.php?10059\">!</a></b>");
}
The first time you run it, use any argument other than "go" and it'll do a dry run so you can see whether you like the verbosity and/or 1000 meat setting. Setting verbosity to false hides the unstealable and cheap items, but it will always show the closeted items and the brief report at the end.

I think it might be worth adding this functionality to an autoselling script, or vice versa.


I think a recent change to mafia finally broke this script.. anyone know how to fix it? Fixing the name of the dramatic range wasn't enough. Looks like the mall refactoring in
r14295 broke it.
 
Last edited:
If you have 14295, try grabbing 14296. Otherwise, describe the problem in more detail.

Also
Code:
boolean is_stealable(item it) { return is_tradeable(it) && autosell_price(it) > 0; }
is wrong in that script, since there are items with an autosell value that cannot be discarded anyway (silver shrimp fork is an example). I don't know if there's any way to actually autosell those items, but mafia has the autosell value for min mallprice purposes.
 
If you have 14295, try grabbing 14296. Otherwise, describe the problem in more detail.

Also
Code:
boolean is_stealable(item it) { return is_tradeable(it) && autosell_price(it) > 0; }
is wrong in that script, since there are items with an autosell value that cannot be discarded anyway (silver shrimp fork is an example). I don't know if there's any way to actually autosell those items, but mafia has the autosell value for min mallprice purposes.

Well, turns out I had an even older version of this script ... the newer one seemed to work better. How would you fix that line?
 
My script uses
Code:
boolean is_pvpable( item thing )
{
	return thing == $item[amulet of yendor] || ( thing.tradeable && thing.discardable && !thing.gift && !thing.quest );
}
I think the quest check at the end is unnecessary, but it doesn't hurt anything. And I guess the gift check is also unnecessary.
 
So the final line would be: ?

boolean is_stealable(item it) { return is_tradeable(it) && is_discardable(it) && ! is_giftable(it); }

Edit: the ! is_giftable(it) seemed to screw it up.
 
Last edited:
More like (based on the lost line):
Code:
boolean is_stealable(item it) { return it.tradeable && it.discardable && !it.gift; }

Your giftable problem is probably that you shouldn't have a space between the ! and the is_giftable. But if you have proxy values that can run directly on the item without needing additional functions, why not use them?
 
Your giftable problem is probably that you shouldn't have a space between the ! and the is_giftable.
It is trivial to confirm that your conjecture is false.

> ashq print( is_giftable( $item[ potted cactus ] ) )

true

> ashq print( ! is_giftable( $item[ potted cactus ] ) )

false

But if you have proxy values that can run directly on the item without needing additional functions, why not use them?
It's a matter of taste.

Both a call to library function and fetching a proxy field end up getting a Method and calling invoke() on it. In the case of the library function, the method was looked up at compile time. In the case of the proxy field, we use Java's object introspection to find the method anew, every time. Which is to say, it's actually (slightly) less efficient. We could optimize that by building a method table once, I suppose.
 
Regarding the "! function" thing, that's why I like to be able to actually run mafia when I offer advice. I generally get burned when I can't verify. :( Any ideas why giftable would have messed him up then?

Interesting. So... suggest the functions rather than proxies currently. Got it. :)
 
is_giftable(item) is not the same as item.gift. is_giftable returns true if the item can be kmailed, i.e. if it is either tradeable or a gift item.

> ash is_giftable($item[pail])

Returned: true
 
Hi all,

it's my first post and my first script for KolMafia, so please be nice if I'm doing something wrong. :)

I took lostcalpolydude's script (many thanks for it!) and changed it a little bit. Instead of blacklisting items which are worthy to keep I whitelist stuff which I do not care if it's stolen and put all other stealable items in the closet. The following script could be written in a more elegant way, but I wanted to have it readable for non programmers, so it's longer than it could be. Change it if you like for your own usage.

Cheers,

Louis

Code:
# pvp_closet_put.ash

# These items only are okay for being picked.
boolean [item] whitelist;

# Food
whitelist[$item[bowl of cottage cheese]]            = true;
whitelist[$item[toast]]                             = true;

# Booze
whitelist[$item[Imp Ale]]                           = true;

# Misc
whitelist[$item[Doc Galaktik's Pungent Unguent]]    = true;

# Hats
whitelist[$item[disco mask]]                        = true;
whitelist[$item[helmet turtle]]                     = true;
whitelist[$item[Hollandaise helmet]]                = true;
whitelist[$item[mariachi hat]]                      = true;
whitelist[$item[ravioli hat]]                       = true;
whitelist[$item[seal-skull helmet]]                 = true;

# Melee
whitelist[$item[pasta spoon]]                       = true;
whitelist[$item[saucepan]]                          = true;
whitelist[$item[seal-clubbing club]]                = true;
whitelist[$item[turtle totem]]                      = true;

# Ranged
whitelist[$item[disco ball]]                        = true;
whitelist[$item[stolen accordion]]                  = true;

# Pants
whitelist[$item[old sweatpants]]                    = true;

# Accessories
whitelist[$item[dirty hobo gloves]]                 = true;

# Misc items
whitelist[$item[cog]]                               = true;
whitelist[$item[spring]]                            = true;
whitelist[$item[sprocket]]                          = true;
whitelist[$item[wad of dough]]                      = true;

# (Mostly) Potions
whitelist[$item[glittery mascara]]                  = true;
whitelist[$item[hair spray]]                        = true;

# (Mostly) Combat Items
whitelist[$item[Knob Goblin firecracker]]           = true;


# The following methods are taken from
# http://kolmafia.us/showthread.php?10059-Save-items-from-pvp-theft
# and a little bit changed to whitelist the stealable items.
# Many thanks to lostcalpolydude for his/her work!

boolean is_pvpable(item it) {
    return it.tradeable && it.discardable && !it.gift && !it.quest;
}

void main() {
    int[item] inventory = get_inventory();

    # batch used to minimize server hits.
    batch_open();
    foreach it in inventory {
        if (is_pvpable(it)) {
            if (whitelist contains it) {
                print_html("whitelisted: " + item_amount(it) + " " + it);
            }
            else {
                print_html("pvpable, to closet: " + item_amount(it) + " " + it);
                put_closet(item_amount(it), it);
            }
        }
    }
    batch_close();
}
 
I'm not sure why you want to base this off a white list instead of price. The more cheap crap you have, the less likely they'll get lucky and take something good, which you pulled from your closet to use and hadn't put back yet. I even use a script that buys cheap stuff. If keeping your inventory clean is another goal, then I highly recommend Bale's OCD script. I don't use it, but it is well loved and I believe has a white list.
 
Yeah. I just use a script which closets everything that sells for more than 100 Meat. You steal anything else? You are welcome to it!

Of course, I have another script which auto-baleets you on KoL and kolmafia.usa if you do so; I see no reason to listen to somebody who thinks its okay to steal from other people. I mean, it's not like you expect me to respond to your KoLmafia bug reports, right? If so, sucks to be you!
 
By the way - for the record, and I will never say this again - here is the message I send to people I auto-baleet:

I thought I'd give you the courtesy of this note.

I automatically baleet people who steal things from me via PVP. Since I closet anything that sells for more than 100 Meat, you are not hurting me in any meaningful way, but, since I understand that somebody who thinks it is OK to steal from people has nothing whatsoever of interest to say to me, I baleet you, and I will never again hear so much as a word you say. No gloating in your PVP win message. No PMs. No forum notes.

I sure hope you don't use KoLmafia, since I will never again see your bug reports. If you do, well, sucks to be you!

Take care.

Love, Veracity
I do have a "whitelist" for people that I know I need to talk to, even if they steal from me, but you have to be darned special to make it on to that list.
 
Back
Top