Feature - Implemented Make free rests remaining visible to ASH

Cool12309

Member
I'm making a logout script that will burn MP on librams and it would be handy to have a function to see remaining free rests, e.g. my_remaining_free_rests() or my_free_rests() would be nice. I understand it's not too terribly difficult to add to a script but I imagine there are others who would find this useful, especially when mafia already keeps track of free rests remaining for the daily deed.
 
I just use this:

Code:
int free_rest() {
	return to_int(have_skill($skill[Disco Nap]))
		+ 2* to_int(have_skill($skill[Adventurer of Leisure]))
		+ to_int(have_skill($skill[Executive Narcolepsy]))
		+ 10* to_int(have_skill($skill[Food Coma]))
		+ 5* to_int(have_skill($skill[Dog Tired]));
}

Edit: Oh hell! I don't include my unconscious collective in that function! I have to fix it! I guess that's a good point in favor of this feature request. It would be a great thing if I didn't have to update my scripts since KoLmafia's update should fix it. Here's my fixed functions:

Code:
int free_rest() {
	return to_int(have_skill($skill[Disco Nap]))
		+ 2* to_int(have_skill($skill[Adventurer of Leisure]))
		+ to_int(have_skill($skill[Executive Narcolepsy]))
		+ 10* to_int(have_skill($skill[Food Coma]))
		+ 5* to_int(have_skill($skill[Dog Tired]))
		+ (my_class().to_int() < 7 && have_familiar($familiar[Unconscious Collective])? 3: 0);
}
 
Last edited:
An already-existing feature is the CLI command "rest free", which will only rest if you have a free rest remaining.

As a counter to this, Guide lists the number of free rests remaining. I'm sure it would be nice if Ez had one less thing to have to keep updated manually if mafia already keeps said thing up to date.
 
I'm tempted to expose CampgroundRequest.freeRestsAvailable() which gives the total free rests available to you, as "timesRested" is already available as a preference. Has the benefit of simplicity.
 
I have a script which does pretty much what you are trying to write, probably pretty clunky, and the weighting of the rares is probably off by a bit, but feel free to have a look:
Code:
import <clanhop.ash>;

int best_price(item it) {
    return ((historical_age(it) <= 1)? mall_price(it) : historical_price(it));
}

float average_price(int first_item_id, int last_item_id) {
    float[item] weightOfRares; item it;
    float total;
    
    weightOfRares[$item[divine champagne popper]] = 0.1;
    weightOfRares[$item[divine champagne flute]] = 0.1;
    weightOfRares[$item[divine cracker]] = 0.1;
    weightOfRares[$item[resolution: be kinder]] = 0.1;
    weightOfRares[$item[resolution: be luckier]] = 0.1;
    weightOfRares[$item[resolution: be more adventurous]] = 0.1;
    weightOfRares[$item[pulled indigo taffy]] = 0.1;
    weightOfRares[$item[pulled green taffy]] = 0.1;
    weightOfRares[$item[pulled yellow taffy]] = 0.1;
    
    for i from first_item_id to last_item_id {
        it = to_item(i);
        if (weightOfRares contains it) {
            total = total + (best_price(to_item(i)) * weightOfRares[it]);
        } else {
            total = total + best_price(to_item(i));
        }
    }
    
    return (total / (1 + last_item_id - first_item_id));
}

skill most_valuable_libram_skill() {
    float[skill] averageSummonValue; skill bestSkill; string s;
    
    averageSummonValue[$skill[Summon Candy Heart]] = (have_skill($skill[Summon Candy Heart]))? average_price(2304, 2309) : 0;
    averageSummonValue[$skill[Summon Party Favor]] = (have_skill($skill[Summon Party Favor]))? average_price(3118, 3123) : 0;
    averageSummonValue[$skill[Summon Love Song]] = (have_skill($skill[Summon Love Song]))? average_price(3754, 3759) : 0;
    averageSummonValue[$skill[Summon BRICKOs]] = (have_skill($skill[Summon BRICKOs]))? average_price(4469, 4470) : 0;
    averageSummonValue[$skill[Summon Dice]] = (have_skill($skill[Summon Dice]))? average_price(5285, 5290) : 0;
    averageSummonValue[$skill[Summon Resolutions]] = (have_skill($skill[Summon Resolutions]))? average_price(5464, 5472) : 0;
    averageSummonValue[$skill[Summon Taffy]] = (have_skill($skill[Summon Taffy]))? average_price(6361, 6367) : 0;
    
    #sort averageSummonValue by -value;
    
    foreach sk in averageSummonValue {
        if (averageSummonValue[sk] > averageSummonValue[bestSkill]) {
            bestSkill = sk;
        }
        if (averageSummonValue[sk] != 0) {
            s = substring(to_string(averageSummonValue[sk]), 0, last_index_of(to_string(averageSummonValue[sk]),".") + 2);
            print("Average mallprice for the items from " + to_string(sk) + " is: " + s + ".", "green");
        }
    }
    if (averageSummonValue[bestSkill] != 0) {
        s = substring(to_string(averageSummonValue[bestSkill]), 0, last_index_of(to_string(averageSummonValue[bestSkill]),".") + 2);
        print("The largest return on tome-summons is from " + to_string(bestSkill) + " which gives " + s + " meat on average.", "blue");
        return bestSkill;
    }
    return $skill[none];
}

void buff_mp() {
    string current_clan;
    // Ballpit
    if (item_amount($item[Clan VIP Lounge key]) > 0 && !to_boolean(get_property("_ballpit"))) {
        if (to_int(get_property("ballpitBonus")) < 100) {
            current_clan = get_clan_name();
            clanhop("Bonus Adventures From Hell");
            cli_execute("ballpit");
            clanhop(current_clan);
        } else {
            cli_execute("ballpit");
        }
    }
    
    // Telescope
    if (to_int(get_property("telescopeUpgrades")) > 0 && !to_boolean(get_property("telescopeLookedHigh"))) {
        cli_execute("telescope high");
    }
    
    // Maximize
    if (have_familiar($familiar[Disembodied Hand])) {
        maximize("mp, -tie, -current, switch Disembodied Hand", false);
    } else {
        maximize("mp, -tie, -current", false);
    }
}

boolean restore_without_overshooting() {
    int free_rests_available; int rest_mp; boolean return_value;
    
    return_value = false;
    
    // Nuns
    if (get_property("sidequestNunsCompleted") == "fratboy") {
        while (my_maxmp() - my_mp() >= 1000 && to_int(get_property("nunsVisits")) < 3) {
            cli_execute("nuns");
            return_value = true;
        }
    }
    // Shower mp
    if (!to_boolean(get_property("_aprilShower"))) {
        if (my_maxmp() - my_mp() >= 1000) {
            cli_execute("shower mp");
            return_value = true;
        }
    }
    // Oscus's neverending soda
    if (!to_boolean(get_property("oscusSodaUsed"))) {
        if (my_maxmp() - my_mp() >= 300) {
            use(1, $item[Oscus's neverending soda]);
            return_value = true;
        }
    }
    // Campground
    free_rests_available = to_int(have_skill($skill[Disco Nap])) + 2* to_int(have_skill($skill[Adventurer of Leisure]))    + to_int(have_skill($skill[Executive Narcolepsy])) + 10*to_int(have_skill($skill[Food Coma]))    + 5*to_int(have_skill($skill[Dog Tired]));
    if(my_class().to_int() < 7 && have_familiar($familiar[Unconscious Collective])) free_rests_available += 3;
    free_rests_available -= to_int(get_property("timesRested"));
    
    if (free_rests_available > 0) {
        if (item_amount($item[Pantsgiving]) > 0) {
            equip($slot[pants], $item[Pantsgiving]);
        }
        rest_mp = numeric_modifier("Base Resting MP") * (numeric_modifier("Resting MP Percent")+100) / 100 + numeric_modifier("Bonus Resting MP");
        while (my_maxmp() - my_mp() >= rest_mp && free_rests_available > 0) {
            cli_execute("rest");
            free_rests_available -= 1;
            return_value = true;
        }
    }
    return return_value;
}

boolean restore_with_overshooting() {
    int free_rests_available;
    
    // Nuns
    if (get_property("sidequestNunsCompleted") == "fratboy") {
        if (my_maxmp() > my_mp() && to_int(get_property("nunsVisits")) < 3) {
            cli_execute("nuns");
            return true;
        }
    }
    // Shower mp
    if (!to_boolean(get_property("_aprilShower"))) {
        if (my_maxmp() > my_mp()) {
            cli_execute("shower mp");
            return true;
        }
    }
    // Oscus's neverending soda
    if (!to_boolean(get_property("oscusSodaUsed"))) {
        if (my_maxmp() > my_mp()) {
            use(1, $item[Oscus's neverending soda]);
            return true;
        }
    }
    // Campground
    free_rests_available = to_int(have_skill($skill[Disco Nap])) + 2* to_int(have_skill($skill[Adventurer of Leisure]))    + to_int(have_skill($skill[Executive Narcolepsy])) + 10*to_int(have_skill($skill[Food Coma]))    + 5*to_int(have_skill($skill[Dog Tired]));
    if(my_class().to_int() < 7 && have_familiar($familiar[Unconscious Collective])) free_rests_available += 3;
    free_rests_available -= to_int(get_property("timesRested"));
    
    if (free_rests_available > 0) {
        if (item_amount($item[Pantsgiving]) > 0) {
            equip($slot[pants], $item[Pantsgiving]);
        }
        if (my_maxmp() > my_mp() && free_rests_available > 0) {
            cli_execute("rest");
            return true;
        }
    }
    return false;
}

void cast_while_affordable(skill skill_to_use) {
    while (mp_cost(skill_to_use) < my_mp()) {
        use_skill(1, skill_to_use);
    }
}

boolean use_pyec() {
    string pyec_taken_from; string property_value;
    // Check if PYEC is available
    if (!(item_amount($item[Platinum Yendorian Express Card]) > 0)) {
        if(display_amount($item[Platinum Yendorian Express Card]) > 0) {
            take_display(1, $item[Platinum Yendorian Express Card]);
            pyec_taken_from = "display";
        } else if (closet_amount($item[Platinum Yendorian Express Card]) > 0) {
            take_closet(1, $item[Platinum Yendorian Express Card]);
            pyec_taken_from = "closet";
        } else if (shop_amount($item[Platinum Yendorian Express Card]) > 0) {
            take_shop(1, $item[Platinum Yendorian Express Card]);
            pyec_taken_from = "shop";
        } else if (storage_amount($item[Platinum Yendorian Express Card]) > 0) {
            take_storage(1, $item[Platinum Yendorian Express Card]);
            pyec_taken_from = "storage";
        } else if (stash_amount($item[Platinum Yendorian Express Card]) > 0) {
            take_stash(1, $item[Platinum Yendorian Express Card]);
            pyec_taken_from = "stash";
        } else {
            return false;
        }
    }
    
    // Burn as much mp as possible, before using the card.
    // First mood.
    cli_execute("burn * mp");
    // Then leash.
    if (mp_cost($skill[Leash of Linguini]) < my_mp() && have_skill($skill[Leash of Linguini])) {
        use_skill(to_int(my_mp() / mp_cost($skill[Leash of Linguini])), $skill[Leash of Linguini]);
    }
    // Then extend buffs.
    property_value = get_property("allowNonMoodBurning"); 
    set_property("allowNonMoodBurning", "true"); 
    cli_execute("burn * mp");
    set_property("allowNonMoodBurning", property_value); 
    
    use(1, $item[Platinum Yendorian Express Card]);
    
    switch (pyec_taken_from) {
        case "display":
            put_display(1, $item[Platinum Yendorian Express Card]);
            break;
        case "closet":
            put_closet(1, $item[Platinum Yendorian Express Card]);
            break;
        case "shop":
            put_shop(0, 0, 1, $item[Platinum Yendorian Express Card]);
            break;
        case "stash":
            put_stash(1, $item[Platinum Yendorian Express Card]);
            break;
    }
    return true;
}

void manaburn() {
    string current_clan;
  
    skill skill_to_use = most_valuable_libram_skill();
    
    if (skill_to_use != $skill[none]) {
        buff_mp();
        
        // Run down current mp before using PYEC.
        // First libram skill
        cast_while_affordable(skill_to_use);
        
        // First try to restore mp without going over max mp
        while (restore_without_overshooting() && mp_cost(skill_to_use) <= my_maxmp()) {
            cast_while_affordable(skill_to_use);
        }
        
        // Then allow going over maz mp
        while (restore_with_overshooting() && mp_cost(skill_to_use) <= my_maxmp()) {
            cast_while_affordable(skill_to_use);
        }
        
        // Then use PYEC, if available
        if (!to_boolean(get_property("expressCardUsed"))) {
            use_pyec();
            cast_while_affordable(skill_to_use);
        }
        
        print("Done! The next libram summon will cost " + mp_cost(skill_to_use) + " mp.", "blue");
    } else {
        print("You don't have any libram skills.", "red");
    }
}

void main() {
    manaburn();
}
 
Back
Top