Universal Recovery Script


New member
As requested:
[COLOR=red]Calling Universal Recovery for type=HP, amount=0[/COLOR]
[COLOR=#66CC00]Restoring      HP! Currently at 118 of 206 HP, 22 of 22 MP, current meat: 33029 ...      Target HP = 196.[/COLOR]
[COLOR=#002080]Trying to fullheal[/COLOR]
_meatperhp      => 0.3106796116504854
[COLOR=red]You don't have a skill      uniquely matching "1 Devour Minions"[/COLOR]
_meatperhp => 0.4
Casting      Bite Minion 1 times...
You gain 20 hit points
Bite Minion was      successfully cast.
[COLOR=blue]Try to heal HP from inventory.[/COLOR]
[COLOR=#002080]Trying      to fullheal[/COLOR]
[COLOR=blue]Try to heal HP with skills.[/COLOR]
Casting      Bite Minion 2 times...
You gain 40 hit points
Bite Minion was      successfully cast.
Casting Bite Minion 1 times...
You gain 20 hit      points
Bite Minion was successfully cast.
[COLOR=red]Calling      Universal Recovery for type=MP, amount=0

Edit: I'm leaning towards something in Mafia not working as expected due to the following:
[COLOR=olive]> ash to_skill("devour")[/COLOR]

Returned:      Devour Minions
level => 6
traincost => 3500
class => Zombie      Master
libram => false
passive => false
buff => false
combat      => false
song => false
permable => true
dailylimit => -1
timescast      => 0

[COLOR=olive]> ash have_skill($skill[Devour Minions])[/COLOR]

Returned:      true

[COLOR=olive]> cast devour minions[/COLOR]

[COLOR=red]You      don't have a skill uniquely matching "devour minions"

Is it an effect due to the skill being marked as "7" (combat/noncombat) and that not being completely implemented?
Last edited:


Oh yeah I've noticed that too. Mafia doesn't recognize Devour Minions as a skill. "devour" and other fuzzy matching terms don't help either (for me at least)
Last edited:


Edit: I'm leaning towards something in Mafia not working as expected

Is it an effect due to the skill being marked as "7" (combat/noncombat) and that not being completely implemented?

Since that is likely the case, I'd recommend commenting out (or deleting) line 345. Do that and it won't try to recover HP with the skill.


New member
That would've been to admit defeat :)
I replaced all cast-calls with an if-statement that used a visit_url-call if the intended skill was Devour Minions and cast if not. Seemed to work for the last few turns I had left at that point.

Edit: Now that I'm at work where I had my change I can post it as well. Basically I replaced all occurrences of cast() with:
if(best_skill == $skill[Devour Minions])
   visit_url("skills.php?pwd&action=Skillz&whichskill=12006&skillform=Use+Skill&quantity=" + to_string(q_skill));
   cast(q_skill, best_skill);

Adapting q_skill and best_skill to whatever was used at that point in the script. Possibly it would've been better to change cast() but I didn't want to come up with a good return value to use when calling visit_url.
Last edited:


Winterbay, if that isn't fixed soon by a mafia dev, then I'll add your workaround into my script. Except that I'll add it to cast, so I only have to add it to a single location. Seriously, what were you thinking? Just fake the return value!

I had a thought about how best to implement Lure Minion. I wonder what folk will think of this implementation.

	if(have_skill($skill[Lure Minions])) {
		// Need to keep enough brains for today and half of tomorrow.
		int brains_needed = fullness_limit() * 1.5 - my_fullness();

		int check_brains(int brains) {
			if(brains <= brains_needed) {
				brains_needed -= brains;
				return 0;
			int temp = brains_needed;
			brains_needed = 0;
			return brains - temp;

		boolean exchanged = false;
		boolean lure(int x, int type) {  // Type is both choice and number of minions per brain.
			// How many times do I do this to reach target?
			x = min(ceil(to_float(target - my_mp()) / type), x);
			if(x > 0) {
				if(!exchanged) // Start choice adventure first time only
				visit_url("choice.php?pwd&whichchoice=599&option="+type+"&quantity="+ x);
				exchanged = true;
			return my_mp() >= target;

		// Finish choice adventure if started
		boolean done() {
			if(exchanged) visit_url("choice.php?pwd&whichchoice=599&option=5");
			return true;

		int spare_good = check_brains(item_amount($item[good brain]));
		int spare_decent = check_brains(item_amount($item[decent brain]));
		int spare_crappy = check_brains(item_amount($item[crappy brain]));
		// Reserve them in order from best to worst. Then trade them worst first.
		if(lure(spare_crappy, 1) || lure(spare_decent, 2) || lure(spare_good, 3))
			return done();
Last edited:


New member
Winterbay, if that isn't fixed soon by a mafia dev, then I'll add your workaround into my script. Except that I'll add it to cast, so I only have to add it to a single location. Seriously, what were you thinking? Just fake the return value!

I do most of my playing at work and so didn't want to waste more time than necessary to come up with a clever return value :)


I'd probably just return true since the better alternative is to check the returned page and see if it was cast successfully. And that sounds like too much work for a quick kludge while waiting for a bug to be fixed.


New member
I see that there is some zombie development going on with this script, but in the latest version there isn't an explicit option to allow bite minion and devour minions to heal HP, is this a setting somewhere?


New member
I'd love a fix for devour minion and I'd cast lure if I had over X meat (maybe 1k meat per level or something...since you need more meat for quest items later) and if I was under Y minions (probably 30 since I like to play it safe).

I know that's a little complicated...but that's my quick and dirty look at how I'd use it.


New member
I saw that but it doesn't have an option to not use up all my meat. I could go through and change it at various points in my ascension, but if something went *really* wrong and I wasn't paying attention, the recovery could blow through all my meat...not that I'm getting anywhere near low meat, but I'm also not using horde based combat skills or buffing my familiar (yet).


So put meat in your closet to ensure its safety? There aren't more options for protecting your meat than there are in a non-zombie ascension, so if that isn't a problem there, why is it a problem here?


Active member
I've never played any of the challenge paths but I've often found myself wishing the script had a settable "meat threshold" below which it would take no actions. It seems that often, when meat is low, the script will run you broke trying to meet recovery targets which it can't reach anyway. In some situations, I would rather preserve some meat than have my hp/mp targets met. For example, I have 100 meat, and some still uses remaining. The script spends 80 meat on seltzer and fails to meat the target anyway, when I could have spent 70 meat and created a tonic water for the script to use, if the script had stopped before spending that meat. But more often, I just want to preserve meat for some other purpose which I find more important at the moment than recovery of hp/mp. This is just an idea, not a complaint. I love the script.


I have often wanted various scripts - not just UR - to preserve meat and the only solution I have found, short of rewriting things myself, has been a wrapper function that closets meat before running and un-closets it afterwards. There is a closeting wrapper in EatDrink - if not remind me and I'll get it - as an example. Basically I closet according to budget, call the script I am trying to keep from using all my meat, and then update amounts used and uncloset. In the case of UR, the wrapped version is then set as my recovery script.


Active member
Nope, ED itself doesn't have the closet bits internally... though several wrappers have been written for it. If that's what you meant, then yes... there are wrappers that will closet your stuff. But there isn't one IN EatDrink. :)


OK. It was in Ascend and I never got around to imposing it on EatDrink.

//This is a wrapper for eatdrink.  It checks the daily budget against the amount spent
//by EatDrink.  It closets meat so that Eatdrink cannot exceed the budget, calls EatDrink
//and then restores the meat.  Daily limit will get hosed if, for whatever reason, EatDrink
//does not return here after being called.  Ignores SIM parameter and any parameters
//that might logically prevent EatDrink from spending

void eatdrinkWrapper (int foodMax, int drinkMax, int spleenMax, boolean overdrink,
	       boolean use_inv_p, boolean use_closet_p, boolean use_storage_p, 
	       boolean sim_consume_p, boolean supress_overdrink_p, 
	       boolean shop_p, int budget_p, float price_flexibility_p, 
	       boolean consider_cost_when_owned_p, int cost_of_pull_p, 
	       int value_of_adventure_p, 
	       int value_of_prime_stat_p, int value_of_nonprime_stat_p, 
	       boolean pie_priority_p, int price_of_nontradeables_p,
	       int price_of_unknowns_p, boolean sim_ronin_p, int sim_level_p)
	int spentToday = to_int(get_property("_Ascend_EatDrinkSpentToday"));
	int allowedThisCall = max(0, eatDrinkBudget - spentToday);
	int beginMeat = my_meat();
	int toCloset = max(0, beginMeat - allowedThisCall);
	if (toCloset > 0) {
	int startMeat = my_meat();
	debug("EDW Before "+spentToday+" "+eatDrinkBudget+" "+allowedThisCall+" "+beginMeat+" "+toCloset+" "+startMeat);
	eatdrink (foodMax, drinkMax, spleenMax, overdrink,
	       use_inv_p, use_closet_p, use_storage_p, 
	       sim_consume_p, supress_overdrink_p, 
	       shop_p, budget_p, price_flexibility_p, 
	       consider_cost_when_owned_p, cost_of_pull_p, 
	       value_of_prime_stat_p, value_of_nonprime_stat_p, 
	       pie_priority_p, price_of_nontradeables_p,
	       price_of_unknowns_p, sim_ronin_p, sim_level_p);
	int endMeat = my_meat();
	int deltaSpend = startMeat - endMeat;
	spentToday = spentToday + deltaSpend;
	if (toCloset > 0) {
	debug("EDW After "+endMeat+" "+deltaSpend+" "+spentToday);


Active member
As I recall, there was conversation as to whether or not the wrapper would be useful integrated into ED and the general result was to leave it out since it would break the few legacy users and there wasn't enough requirement for inclusion. But that was, I think, over a year back? Anyways... reminiscings. :)