Best Between Battle Script Ever -- formerly AutoMCD

Ok, I excised the code for Flavour from my mood script. Granted, I wrote this a year or so back (I obviously didn't care about wasting 1MP here and there, which was one of several reasons my mood script was not shareable), but it has served me well. It skips Flavour if you have no Pastamancer or Sauceror spells. After that, it chooses the element to which the majority of the monsters in the zone are vulnerable, with some weight also given to the element you already have the most bonus spell damage in. It skips elements if any monsters in the zone are immune to that element, so for zones where all elements have an immune monster, it defaults to spirit of nothing.

At least, I think that's how it works. Haha.

PHP:
// returns the element to which attacks would be best tuned for this zone
int[element] get_vulns() {
   int[element] vulns, res;
   foreach i,m in my_location().get_monsters() {
      switch (m.defense_element) {
         case $element[none]: continue;
         case $element[hot]: vulns[$element[sleaze]] += 1; vulns[$element[stench]] += 1; break;
         case $element[spooky]: vulns[$element[hot]] += 1; vulns[$element[stench]] += 1; break;
         case $element[cold]:   vulns[$element[hot]] += 1; vulns[$element[spooky]] += 1; break;
         case $element[sleaze]: vulns[$element[cold]] += 1; vulns[$element[spooky]] += 1; break;
         case $element[stench]: vulns[$element[cold]] += 1; vulns[$element[sleaze]] += 1; break;
      }
      res[m.defense_element] += 1;
   }
   foreach e in vulns if (res contains e) remove vulns[e];
   if (count(vulns) == 0) foreach el in $elements[] if (!(res contains el)) vulns[el] += 1;  // all elements are cool if none are
   return vulns;
}
skill get_flavour(element e) {
   switch (e) {
      case $element[cold]: return $skill[spirit of peppermint];
      case $element[hot]: return $skill[spirit of cayenne];
      case $element[spooky]: return $skill[spirit of wormwood];
      case $element[sleaze]: return $skill[spirit of bacon grease];
      case $element[stench]: return $skill[spirit of garlic];
      default: return $skill[spirit of nothing];
   }
}
void intrinsics(){
  // flavour of magic
   boolean have_spells() { foreach s in $skills[] if (have_skill(s) && s.combat && $classes[pastamancer,sauceror] contains s.class) return true; return false; }
   if (!have_skill($skill[flavour of magic]) || !have_spells()) return;
   boolean have_spirit() { for i from 167 to 171 if (have_effect(to_effect(i)) > 0) return true; return false; }
   int[element] vulns = get_vulns();
   element[int] sorte;
   foreach v in vulns sorte[count(sorte)] = v;
   sort sorte by -(vulns[value] + numeric_modifier(value+" Spell Damage"));
   if (count(sorte) > 0) {
      if (have_effect(to_effect(get_flavour(sorte[0]))) == 0) use_skill(1,get_flavour(sorte[0]));
   } else if (have_spirit()) use_skill(1,$skill[spirit of nothing]);
}

Have fun!
 
So I'm guessing that line in your mood looks something like this?
Code:
Always, ashq import <flavourScript.ash> intrinsics()
 
Last edited:
You'd be guessing poorly. He's just extracted this bit of code from the larger script. I'm sure there was a main which called intrinsics() so the import isn't necessary.



I'm a little bit puzzled by one line:

PHP:
sort sorte by -(vulns[value] + numeric_modifier(value+" Spell Damage"));

If I understand that properly, it is sorting vulrnable elements by elemental spell damage with a teeeeeeny-tiny bit of weighting by number of vulnerabilities. Spell Damage bonuses are usually +10 or higher. If I am running Song of Sauce that will be +50 Hot Spell Damage. However it is unlikely that the number of monsters vulnerable to a specific element will exceed 5. Would multiplication be more appropriate than addition? I'm not sure...

Also, foreach to make all elements vulnerabilities if none are, could cause the code to consider supercold or slime elements.


Edit: Just noticed it doesn't check appearance rates. So, if you are checking for the Top Floor of the Castle, it will include the Burning Snake of Fire as a possible elemental monster. I'm not sure if this is good or bad.
 
Last edited:
Yeah you requested some old code (I think it predates supercold as a thing). Alter as you see fit.

My mood looks like this: Always, M*******.ash

(?!)
 
I've been playing with that code. I'm currently using the following version:

PHP:
void flavour() {
	boolean have_spirit() {
		for i from 167 to 171
			if(have_effect(to_effect(i)) > 0) return true; 
		return false;
	}
	// Convert Element to Spirit
	skill get_flavour(element e) {
		switch (e) {
		case $element[cold]: return $skill[spirit of peppermint];
		case $element[hot]: return $skill[spirit of cayenne];
		case $element[spooky]: return $skill[spirit of wormwood];
		case $element[sleaze]: return $skill[spirit of bacon grease];
		case $element[stench]: return $skill[spirit of garlic];
		}
		return $skill[spirit of nothing];
	}
	if(have_skill($skill[flavour of magic])) {
		switch(my_location()) {
		case $location[The Ancient Hobo Burial Ground]: // Everything here is immune to elemental dmg
			if(have_spirit())
				use_skill(1, $skill[spirit of nothing]);
		case $location[Hobopolis Town Square]: // Don't interfere with Scarehobos
			return;
		}
		// Find the element to which attacks would be best tuned for this zone
		int [element] vulns, res;
		foreach i,m in my_location().get_monsters() {
			switch (m.defense_element) {
			case $element[none]: continue;
			case $element[hot]:    vulns[$element[sleaze]] += 1; vulns[$element[stench]] += 1; break;
			case $element[spooky]: vulns[$element[hot]] += 1;    vulns[$element[stench]] += 1; break;
			case $element[cold]:   vulns[$element[hot]] += 1;    vulns[$element[spooky]] += 1; break;
			case $element[sleaze]: vulns[$element[cold]] += 1;   vulns[$element[spooky]] += 1; break;
			case $element[stench]: vulns[$element[cold]] += 1;   vulns[$element[sleaze]] += 1; break;
			}
			res[m.defense_element] += 1;
		}
		foreach e in vulns
			if(res contains e)
				remove vulns[e];
		if(count(vulns) == 0)   // If there are no vulns, then any non res elements is good
			foreach el in $elements[cold, hot, sleaze, spooky, stench]
				if(!(res contains el)) vulns[el] = 1;
		// Now, sort them
		element [int] sorted;
		foreach v in vulns
			sorted[ count(sorted) ] = v;
		if(count(sorted) > 0) {
			sort sorted by -(vulns[value] * (numeric_modifier(value+" Spell Damage") + 1)); 
			if(have_effect(to_effect(get_flavour(sorted[0]))) == 0)
				use_skill(1, get_flavour(sorted[0]));
		}  else if (have_spirit()) use_skill(1,$skill[spirit of nothing]); 
	}
}
 
First of all, thank you Zarqon for this great script. I am just starting to use it, and it is very helpful. I had a couple questions/comments, though.

First, could there be an option to default to skipping all noncombats in the Crypt (except the whelps of course)? I like the option to skip the items, and it isn't hard to just delete the "else if" lines in the code, but I personally don't even like to take the mainstat option, and others might feel the same way.

Second, and maybe I'm missing something, but are the choice options in the Haunted Bedroom currently supported? Would it be possible for the script to auto-choose the camera, the spectacles, and the gown?

Thanks so much!

Edit: Fixed up the choice adventures for the Haunted Bedroom. Only tested it so far with a mysticality class, but it gets all the quest items at least.

Code:
case $location[the haunted bedroom]:
         if (have_item($item[Lady Spookyraven's Finest Gown]) == 0) friendlyset(880,"1","Gown.");
	 else friendlyset(880,"2","Stick.");
	 if (have_item($item[Lord Spookyraven's Spectacles])== 0) friendlyset(878,"3","Spooky's specs.");
         else if(have_item($item[disposable instant camera])==0) friendlyset(878,"4","Disposable instant camera.");
         else friendlyset(878,"2","Mysticality.");
	 friendlyset(877,"1","Coin purse.");
	 if (is_goal($stat[muscle])) friendlyset(876,"2","Strength.");
	 else friendlyset(876,"1","Money.");
	 friendlyset(879,"1","Moxie.");	  
return;
 
Last edited:
Threw together some support for grabbing the beehive if we haven't liberated the king yet. Basically, if item_amount on the beehive is 0, and we haven't broken the prism, and we are adventuring in the black forest, set the proper choiceadvs to start the bee series.
 

Attachments

Thanks Theraze. r19 includes those changes, as well as setting the choiceadv on the Ground Floor for getting the boning knife. A few other changes:

  • Haunted Billiards Room: Handle the ghost choiceadv. If cubes of billiards chalk are a goal or your pool skill is maxed, get those. Otherwise, increase your pool skill.
  • The Road to the White Citadel: If you haven't yet cleared enough burnouts, you have the ingredients for an opium grenade, and you don't already have one in inventory, create one. This combined with SS throwing them will facilitate speedier clearing of the zone.

Enjoy!

@stickyhippo: You're right that those stat choices need a way to be ignored. I can either remove them, or make ZLib's is_goal(stat) not automatically return true for primestat. I'm thinking the latter is the way to go.

I haven't looked through the new Bedroom choices in detail yet. The old bedroom had very few choices that were possible to automate setting without interfering with someone's playstyle. Some people want meat, some people want speed; some people are doing quests, some aren't; and so forth. But the new choices may have some that are possible to automate without causing trouble -- I'll look into it.
 
Apparently my copy of this script updated tonight, and now I'm getting:

Bad item value: "beehive" (BestBetweenBattle.ash, line 116)


​and not knowing much about how the code system works I'm not sure what to do about that. :(

So to add a little more information, I'm using this in conjunction with bumcheekascend, and was able to comment out two if statements that involve beehive, however given that the beehive IS an item I'll be needing, it'd be nice to resolve the issue rather than put a band aid on it. Any suggestions?
 
Last edited:
Hidden Temple wonkiness: BBB does great at the lead-up to Hidden Heart (pikach, as described in r11 on Sourceforge), as well as after it. What it fails horribly at is figuring out that, when you have the Nostril of the Serpent AND get to the Heart AND haven't set Unconfusing Buttons to pikach yet, that you should take the option that allows you to do so. Currently BBB thinks the top option (Muscle, if it hasn't been set otherwise) is the one to take in this situation.
 
Unfortunately KoL uses the same choice number for all of those, so you can't 'properly' automate those. Unless things have changed recently, it will loop forever, if you try to set it with current mafia 'choice' code.

Edit:
The possible mafia FReq would be to automate those as a chain... choosing Pik, Calendar, or whatever. The bad thing about the FReq is that it would potentially be +2 server hits to change the choice even if it's already been set. If we save the current status between choices as well as read the current status for people who have changed things outside mafia, we could not need the extra server hits.
 
Last edited:
Updated dropfam() function

For anyone who might find it useful, an updated dropfam() function which includes recent IotM/Ys.

  • Galloping Grill (untested)
  • Fist Turkey
  • Adventurous Spelunker
  • Golden Monkey

Code:
familiar dropfam() {
   if (my_location().zone == "The Sea" || $locations[none, the slime tube] contains my_location()) return my_familiar();
   boolean has_more_drop(familiar f, int soft) {
      boolean clim(string prop, int hard) { return to_int(get_property(prop)) < min(soft,hard); }
      switch(f) {
         case $familiar[adventurous spelunker]: return clim("_spelunkingTalesDrops",1);
         case $familiar[angry jung man]: return clim("_jungDrops",1);
         case $familiar[astral badger]: return clim("_astralDrops",5);
         case $familiar[baby sandworm]: return clim("_aguaDrops",5);
         case $familiar[blavious kloop]: return clim("_kloopDrops",5);
         case $familiar[bloovian groose]: return clim("_grooseDrops",5);
         case $familiar[fist turkey]: return clim("_turkeyBooze",5);
         case $familiar[galloping grill]: return clim("_hotAshesDrops",5);
         case $familiar[gelatinous cubeling]: return (available_amount($item[eleven-foot pole]) == 0 || 
            available_amount($item[ring of detect boring doors]) == 0 || available_amount($item[pick-o-matic lockpicks]) == 0);
         case $familiar[golden monkey]: return clim("_powderedGoldDrops",5);
         case $familiar[green pixie]: if (have_effect($effect[absinthe-minded]) > 0) return false; return clim("_absintheDrops",5);
         case $familiar[grim brother]: return clim("_grimFairyTaleDrops",5);
         case $familiar[grimstone golem]: return clim("_grimstoneMaskDrops",1);
         case $familiar[happy medium]: return clim("_mediumSiphons",20);
         case $familiar[knob goblin organ grinder]: return clim("_pieDrops",5);
         case $familiar[li'l xenomorph]: return clim("_transponderDrops",5);
         case $familiar[llama lama]: return clim("_gongDrops",5);
         case $familiar[artistic goth kid]: if (!hippy_stone_broken() && have_familiar($familiar[mini-hipster])) return false;
         case $familiar[mini-hipster]: if (!contains_text(to_url(my_location()),"adventure.php")) return false; return clim("_hipsterAdv",7);
         case $familiar[pair of stomping boots]: foreach i,m in get_monsters(my_location()) if (!($phyla[dude,none] contains m.phylum)) return clim("_pasteDrops",7); return false;
         case $familiar[rogue program]: return clim("_tokenDrops",5);
         case $familiar[unconscious collective]: return clim("_dreamJarDrops",5);
      } return false;
   }
   for i from 1 upto 10
    foreach f in $familiars[green pixie, li'l xenomorph, baby sandworm, grim brother, grimstone golem, astral badger, llama lama, mini-hipster, 
       bloovian groose, rogue program, blavious kloop, unconscious collective, angry jung man, happy medium, 
       knob goblin organ grinder, artistic goth kid, pair of stomping boots, gelatinous cubeling, adventurous spelunker, fist turkey, galloping grill, golden monkey]
      if (have_familiar(f) && has_more_drop(f,i)) return f;
   return my_familiar();
}
 
I'm experiencing an odd error with BestBetweenBattle. Sometimes, for no visible reason, the script will complain that there is a Spooky Putty monster in inventory when there isn't one. The complete explanation is in the main bug report thread.

Any ideas?
 
I think you need to do what Veracity said and try to figure out why mafia's inventory is getting out of sync. This is probably similar to the dolphin whistle issue where those get out of sync... but as to why it happens, or avoiding it? The only thing we can do here is throw in refresh inventory calls, which doesn't actually fix the issue and causes a LOT of wasted server hits.
 
Ed has a different number for the Zigguarat choice adventure:

Code:
	case $location[a massive ziggurat]:
		int choiceAdventure = my_path() == "Actually Ed the Undying"? 1002: 791;
		if(item_amount($item[stone triangle]) == 4)
			friendlyset(choiceAdventure,"1","Fight the final Protector Spectre.");
		else friendlyset(choiceAdventure,"6","Not enough triangles; skip the Protector Spectre.");
		return;
 
Back
Top