Okay, you've already taken care of four of my proposals (in_hardcore, item_to_slot, have_outfit, and skill_to_effect -- I was only using has_equipped as an example of something that we could do with item_to_slot, but I sure don't mind it being added to ASH!), but while I was coming up with all of my code samples three new ideas came into my mind. Enjoy!
int pulls_remaining() - The number of pulls that I have remaining from Hagnk's today. I suppose that if I'm in softcore but not in ronin it would return a very large number and if I'm in hardcore but haven't rescured the king it would return 0.
Code:
void pull_for_feng_shui()
{
if (pulls_remaining() < 3)
{
print("Sorry, you don't have enough pulls to get all the pieces");
return;
}
take_storage(1, $item[decorative fountain]);
take_storage(1, $item[Feng Shui for Big Dumb Idiots]);
take_storage(1, $item[windchimes]);
use(1, $item[Feng Shui for Big Dumb Idiots]);
}
Note that without the pre-check, I'd have wasted a pull or two that I might have used for something productive.
int ronin_remaining() - The number of adventures of ronin left. This seems like the opposite of pulls_remaining, returning -1 if I'm out of ronin and a very very large number if I'm in hardcore.
This sample is going to miss twenty different levels of subtlety, but let's assume for the moment that it's a fighter character who has already eaten and doesn't have Ode to Booze but would want to save as much drinking as possible for a post-ronin buffbot visit.
Code:
[...]
while (my_adventures() < ronin_remaining() && my_inebriation() + 4 <= drunkenness_limit())
{
drink(1, $item[fuzzbump]);
}
[...]
int drunkenness_limit() - returns either 15 or 20 depending on whether you have Liver of Steel. See the code sample above.
int still_lights() - It would be a nice part of a bedtime script to just make enough tonic waters to clear out the still. Maybe you're not catching this one at the moment.
Code:
[...]
buy(still_lights(), $item[soda water]);
create(still_lights(), $item[tonic water]);
[...]
boolean can_equip(item it) - Do I satisfy the stat requirements to equip this item?
This code sample is from the adventure-boosting portion of my bedtime script, specifically the part where you pick what weapon to wear.
Code:
boolean wear_if_can_and_have(item it, boolean worth_a_pull)
{
if (!can_equip(it)) return false;
if (item_amount(it) == 0)
{
if (!worth_a_pull || storage_amount(it) == 0 || pulls_left() == 0) return false;
take_storage(1, it);
}
equip(it);
return true;
}
boolean new_manage_arms()
{
if (wear_if_can_and_have($item[time sword], true)
{
if (have_skill($skill[Double-Fisted Skull Smashing]))
pull_to_wear($slot[off-hand], $item[time sword]);
return true;
}
item sword = $item[chrome sword];
item xbow = $item[chrome crossbow];
item staff = $item[chrome staff];
if (wear_if_can_and_have(sword, false) return true;
if (wear_if_can_and_have(staff, false) return true;
if (wear_if_can_and_have(xbow, false) return true;
if (wear_if_can_and_have(sword, true) return true;
if (wear_if_can_and_have(staff, true) return true;
if (wear_if_can_and_have(xbow, true) return true;
return false;
}
At the moment, manage_arms() is much longer because I have to query for moxie and muscle for each weapon instead of being able to pass it to the helper function. (Note also the use of pulls_left() so that I wouldn't have to check after the pull to make sure that it succeeded.)
item familiar_equipment(familiar pet) - I suppose that there is at least one familiar with more than one piece of specific equipment, but knowing the general one and having the new ones being added as quickly as they are supported in KoLmafia would be great.
This might be a little trickier, so I'll show you part of the code as it exists at this moment and you'll see the dilemma. This is something that I would run just out of ronin that would put all of the familiars in their gear. I've got a map elsewhere that contains the data except that it falls out of date more regularly than your data does.
Code:
boolean dress_pet(familiar pet)
{
item it = Mfam_equipment[pet];
if (item_amount(it)==0) return false;
if (!equip_familiar(pet)) return false;
if (!equip(it)) return false;
if (item_amount(it)>0) sell_item(item_amount(it), it);
return true;
}
void main()
{
familiar at_start = my_familiar();
foreach pet in Mfam_equipment dress_pet(pet);
equip_familiar(at_start);
}
The hitch is that I am using Mfam_equipment both for its associative qualities and as an iterator through the familiars. I suppose that exposing some data as an immutable map instead of a function might be more an offer than you had in mind, but you might be able to come up with a way around the problem.
boolean is_song(skill sk) and
int song_count() - I'm glad that you implemented the skill to effect function. If part of your mood overhaul is a greater attention to AT buffs and their limitations, then this would be another useful thing to expose to scripts.
Here is part of my working code, in which this is implemented with a set (by which I mean a map in which the values are irrelevant) and another function.
Code:
boolean skill_upkeep(skill sk)
{
if (!have_skill(sk)) return false;
if (have_effect(Mskill_to_effect[sk]) > 0) return true;
if (Ssong contains sk && active_songs() == 3) return false;
use_skill(1, sk);
return (have_effect(skill_to_effect(sk)) > 0);
}
void main()
{
[...]
if (my_maxmp() >= 15) skill_upkeep($skill[empathy]);
if (my_maxmp() >= 12) skill_upkeep($skill[leash of linguini]);
if (my_maxmp() >= 40 && my_level() < 11) skill_upkeep($skill[aloysius' antiphon of aptitude]);
if (my_maxmp() >= 7) skill_upkeep($skill[polka of plenty]);
[...]
}
boolean can_adventure(location spot) - I know that there are a few spots where you determine if a location is legal for adventuring before visiting. It would be similarly useful for us to not have to calculate if the Icy Peak or Valley was unlocked. Ideally, this functionality could eventually be strengthened to cover most of the locations and checking stat values and/or zodiac signs or whatever else would be necessary to pre-determine if an adventure would be legal. In the mean time, I would accept that this function would throw an error message and abort if it was queried about a location that you didn't have a test for.
I'm not sure exactly how pervasive the current functionality would be, but as I'm pretty sure you check the Valley at the moment, we could check to make sure that they don't accidentally try to get the abridged dictionary twice:
Code:
{
[...]
if (can_adventure($location[valley beyond orc chasm]))
{
print("You have already finished the dictionary subquest!");
return true;
}
[...]
}