# NeoStasis
# v1.4
# by Illarion, Mar 2007
# A KoL Stasis script for the post-noodle world.
# formulae courtesy of HCO forums
# Many thanks to Holatuwol and Veracity, without whom this never would have been possible
# Thanks to dirkdiggler for leatherback formula
# Change history
# v1.4 - better cocoon support, better handling of situations when mob or player cannot hit,
# fixed panic noodling, included Gemelli's workaround for undefined monsters
# v1.3 - fixed entangling noodle bug?, FinishNOW implemented, aware of physical-resistant monsters,
# sanity check when monster can't hit player.
# v1.2- fixed shield/hero test bug, tidied display messages, used antidote
# v1.1 - Location checking for dictionary, pickpocket, fixed mp_cost check
# v1.0 - Forked from ASHStasis v1.4
Here it is guys and gals, my latest stasis script attempt. Sadly, I was a lot happier with it before I trashed my hard drive and had to rewrite it, but isn't that always the way?
As always, I'd greatly appreciate comments, criticisms and advice, especially on the new, post-noodle combat logic:
Current rules are, in order of precedence:
If round = 28+, try to kill enemy (TS, LTS, Stream)
WIP - If we expect the enemy to kill us next hit:
- cast noodles if we have it (and haven't already), otherwise:
- heal up to safety level while the enemy remains noodled, or kill as quickly as possible when noodles break
Heal up to safety level
Do nothing
No handling for delevellers at all yet - I'll wait until it's been spaded out whether Boogaloo/Shieldbutt are worth it.
Given the complete rewrite, and the noodle change, it hardly needs saying that this is way back into beta - please don't complain to me if it messes up your leaderboard attempt!
Testing feedback would be most helpful though - just save it for your prep runs at first.
# v1.4
# by Illarion, Mar 2007
# A KoL Stasis script for the post-noodle world.
# formulae courtesy of HCO forums
# Many thanks to Holatuwol and Veracity, without whom this never would have been possible
# Thanks to dirkdiggler for leatherback formula
# Change history
# v1.4 - better cocoon support, better handling of situations when mob or player cannot hit,
# fixed panic noodling, included Gemelli's workaround for undefined monsters
# v1.3 - fixed entangling noodle bug?, FinishNOW implemented, aware of physical-resistant monsters,
# sanity check when monster can't hit player.
# v1.2- fixed shield/hero test bug, tidied display messages, used antidote
# v1.1 - Location checking for dictionary, pickpocket, fixed mp_cost check
# v1.0 - Forked from ASHStasis v1.4
Here it is guys and gals, my latest stasis script attempt. Sadly, I was a lot happier with it before I trashed my hard drive and had to rewrite it, but isn't that always the way?

As always, I'd greatly appreciate comments, criticisms and advice, especially on the new, post-noodle combat logic:
Current rules are, in order of precedence:
If round = 28+, try to kill enemy (TS, LTS, Stream)
WIP - If we expect the enemy to kill us next hit:
- cast noodles if we have it (and haven't already), otherwise:
- heal up to safety level while the enemy remains noodled, or kill as quickly as possible when noodles break
Heal up to safety level
Do nothing
No handling for delevellers at all yet - I'll wait until it's been spaded out whether Boogaloo/Shieldbutt are worth it.
Given the complete rewrite, and the noodle change, it hardly needs saying that this is way back into beta - please don't complain to me if it messes up your leaderboard attempt!

Testing feedback would be most helpful though - just save it for your prep runs at first.
Code:
# NeoStasis.ash
# v1.4
# by Illarion, Mar 2007
# A KoL Stasis script for the post-noodle world.
# formulae courtesy of HCO forums
# Many thanks to Holatuwol and Veracity, without whom this never would have been possible
# Thanks to dirkdiggler for leatherback formula
# Change history
# v1.4 - better cocoon support, better handling of situations when mob or player cannot hit,
# fixed panic noodling, included Gemelli's workaround for undefined monsters
# v1.3 - fixed entangling noodle bug?, FinishNOW implemented, aware of physical-resistant monsters,
# sanity check when monster can't hit player.
# v1.2- fixed shield/hero test bug, tidied display messages, used antidote
# v1.1 - Location checking for dictionary, pickpocket, fixed mp_cost check
# v1.0 - Forked from ASHStasis v1.4
#TODO
#Monster variance
#abort on specific monsters
#*** Begin user-configurable variables ***#
//Change to false if antidote is changed!
boolean USE_ANTIDOTE = true;
//boolean USE_ANTIDOTE = false;
#Default values:
int DAM_THRESHOLD = 20;
//Script will Salve to keep health above this percentage.
//Set low to use with Coccoon, eg 20, or high without, eg 80-90.
int HEALTH_PCT = 60;
if (have_skill($skill[Cannelloni Cocoon]) && my_maxhp()>100)
{
HEALTH_PCT = 20;
}
//if your moxie exceeds monster attack by this much, don't bother trying to stasis (as mob can't hit)
int OVERMOXIE_LEVEL = 8;
#print debug messages. These go to the Mafia status bar, and the gCLI. Turn them off if
#you're happy with the performance, and don't care about tweaking/understanding what's going on.
boolean dbug = true;
//Use to show more detailed output
boolean bVerbose = true;
#*** End of user-configurable variables ***#
#Used for status messages
int giRound;
int giCurDelevel;
boolean gbEnemyNoodled;
boolean gbInValley;
stat gDefenceStat;
monster zilch=$monster[];
string MSG_NOODLEBREAK = "Your opponent struggles free of your entangling noodles.";
int max(int a, int b)
{
int iRetVal;
if (a > b)
{
iRetVal = a;
}
else
{
iRetVal = b;
}
return iRetVal;
}
int min(int a, int b)
{
int iRetVal;
if (a < b)
{
iRetVal = a;
}
else
{
iRetVal = b;
}
return iRetVal;
}
int LeatherBackDR()
{
//DR from Leatherback, as dirkdiggler's formula:
//Leatherback DR = Clamp[ 1 < ceil( (level-3)/2 ) ]
int iResult;
if (have_skill($skill[skin of the leatherback]))
{
iResult = (max(1, ceil( (my_level()-3)/2 )));
}
else
{
iResult = 0;
}
return iResult;
}
void ShowStatusMsg(string Msg)
{
print( "Round: " + giRound + " " +
"(MP Change=" + (my_mp()-string_to_int(get_property("IllStasis_StartMP"))) + ", HP Change=" + (my_hp()-string_to_int(get_property("IllStasis_StartHP"))) + ") --> " + Msg );
}
boolean ShieldEquipped()
{
boolean bFoundShield = false;
string sItem;
sItem = item_to_string(current_equipment($slot[off-hand]));
bFoundShield = bFoundShield || (index_of(sItem, "buckler" )>=0);
bFoundShield = bFoundShield || (index_of(sItem, "shield" )>=0);
bFoundShield = bFoundShield || (index_of(sItem, "hors d'oeuvre tray" )>=0);
bFoundShield = bFoundShield || (index_of(sItem, "box turtle" )>=0);
bFoundShield = bFoundShield || (index_of(sItem, "coffin lid" )>=0);
bFoundShield = bFoundShield || (index_of(sItem, "sewer turtle" )>=0);
if (bVerbose) { Print("Offhand=" + sItem + "-> Shield=" + boolean_to_string(bFoundShield)); }
return bFoundShield;
}
int CheckSkill(skill myskill)
//return 0=success, 1=insufficient mana, 2=do not have skill
{
if (!have_skill(myskill))
{
return 2;
}
else
{
if (my_mp() < mp_cost(myskill) )
{
return 1;
}
}
return 0;
}
boolean CheckPhysicalResistance(monster eek)
{
if (eek == $monster[chalkdust wraith])
return true;
if (eek == $monster[Ghost Miner])
return true;
if (eek == $monster[Snow Queen])
return true;
return false;
}
int ExpectedMonsterDamage(monster eek)
//BaseMonsterDmg = (20% to 25%)*Atk + (Atk-Mox)
//Dam = (Base - DR) * DA * ER
{
int iDam;
int iAtk;
int iMoxPenalty;
int iDR;
iAtk = monster_base_attack(eek)+ monster_level_adjustment() - giCurDelevel;
iMoxPenalty = max(iAtk - my_buffedstat(gDefenceStat),0);
iDam = 0.25*iAtk + iMoxPenalty;
iDam = iDam - damage_reduction()-LeatherbackDR();
iDam = iDam - (iDam * damage_absorption_percent()/100);
//TODO elemental resistance
if (bVerbose) { Print("Expected: (25% of " + iAtk + "+" + iMoxPenalty + "-(" + damage_reduction() + "+" + LeatherBackDR() + ")DR) * " + damage_absorption_percent() + "%DA = " + iDam); }
if(eek==zilch)
{
if (dbug) { Print("Monster undefined ... assuming a reasonable range."); }
iDam=10;
}
return iDam;
}
boolean MonsterCannotHit(monster eek)
//Test if mob can hit us
{
int iAtk;
iAtk = monster_base_attack(eek)+ monster_level_adjustment() - giCurDelevel;
return ((iAtk + OVERMOXIE_LEVEL) <= my_buffedstat($stat[moxie]) );
}
boolean PlayerCannotHit(monster eek)
//Test if we can hit the mob
{
int iDef;
iDef = monster_base_defense(eek)+ monster_level_adjustment() - giCurDelevel;
return (my_buffedstat(current_hit_stat()) < (iDef + 7)); //TODO check the 7
}
void PickPocket()
{
print("Picking pocket...");
visit_url("fight.php?action=steal");
}
boolean ThrowJunkItem()
{
item JunkItem;
JunkItem = $item[scroll of turtle summoning];
if (bVerbose) { Print("Trying to throw junk..."); }
if (item_amount(JunkItem)>0)
{
throw_item(JunkItem);
return true;
}
JunkItem = $item[seal tooth];
if (item_amount(JunkItem)>0)
{
throw_item(JunkItem);
return true;
}
JunkItem = $item[spices];
if (item_amount(JunkItem)>0)
{
throw_item(JunkItem);
return true;
}
if (bVerbose) { Print("Failed to throw junk."); }
return false;
}
void FinishHim(monster eek)
{
if (dbug) { print("Finish Him!"); }
if (gbInValley)
//Best to use a dictionary if we can - free
{
if (item_amount($item[dictionary])>0)
{
if (bVerbose) { Print("Finish with dictionary"); }
throw_item($item[dictionary]);
}
else
{
if (item_amount($item[facsimile dictionary])>0)
{
if (bVerbose) { Print("Finish with dictionary"); }
throw_item($item[facsimile dictionary]);
}
}
}
else
{
if (CheckPhysicalResistance(eek) && have_skill($skill[immaculate seasoning]) && CheckSkill($skill[stream of sauce])==0 )
{
if (bVerbose) { Print("Physical Resistant - Finish with Stream"); }
use_skill($skill[stream of sauce]);
}
else
{
#check for melee weapon
if (current_hit_stat() == $stat[muscle] && CheckSkill($skill[thrust-smack])==0)
{
if (bVerbose) { Print("Finish with TS"); }
use_skill($skill[thrust-smack]);
}
else
{
if (have_skill($skill[immaculate seasoning]) && CheckSkill($skill[stream of sauce])==0 )
{
if (bVerbose) { Print("Finish with Stream"); }
use_skill($skill[stream of sauce]);
}
else
{
if (current_hit_stat() == $stat[muscle] && CheckSkill($skill[lunging thrust-smack])==0)
{
if (bVerbose) { Print("Finish with LTS"); }
use_skill($skill[lunging thrust-smack]);
}
else
{
if (!ThrowJunkItem())
{
if (dbug) { print("Aborting - you must finish. Two rounds left!"); }
cli_execute("abort");
}
}
}
}
}
}
}
void FinishHimNow(monster eek)
//Finish ASAP, but using stream if enemy is noodled, and LTS in preference to TS
{
if (have_skill($skill[immaculate seasoning]) && CheckSkill($skill[stream of sauce])==0)
{
if (gbEnemyNoodled)
{
if (bVerbose) { Print("Enemy Noodled - finish with Stream"); }
use_skill($skill[stream of sauce]);
}
else
{
if (CheckPhysicalResistance(eek))
{
if (bVerbose) { Print("Physical Resistant - Finish with Stream"); }
use_skill($skill[stream of sauce]);
}
}
}
else
{
#check for melee weapon
if (current_hit_stat() == $stat[muscle] && CheckSkill($skill[lunging thrust-smack])==0)
{
if (bVerbose) { Print("Finish with LTS"); }
use_skill($skill[lunging thrust-smack]);
}
else
{
if (have_skill($skill[immaculate seasoning]) && CheckSkill($skill[stream of sauce])==0 )
{
if (bVerbose) { Print("Finish with Stream"); }
use_skill($skill[stream of sauce]);
}
else
{
if (current_hit_stat() == $stat[muscle] && CheckSkill($skill[thrust-smack])==0)
{
if (bVerbose) { Print("Finish with TS"); }
use_skill($skill[thrust-smack]);
}
else
{
if (!ThrowJunkItem())
{
if (dbug) { print("Aborting - you must finish!"); }
cli_execute("abort");
}
}
}
}
}
}
void DontHurtHim(monster eek)
{
if (bVerbose) { Print("Attack and miss"); }
if (item_amount($item[anti-anti-antidote])>0 && USE_ANTIDOTE)
{
throw_item($item[anti-anti-antidote]);
}
else
{
if (item_amount($item[dictionary])>0 && !gbInValley)
{
throw_item($item[dictionary]);
}
else
{
if (item_amount($item[facsimile dictionary])>0 && !gbInValley)
{
throw_item($item[facsimile dictionary]);
}
else
{
if (have_skill($skill[shake hands]) )
{
use_skill($skill[shake hands]);
}
else
{
if (buffed_hit_stat() - (monster_base_attack(eek)+ monster_level_adjustment()
- giCurDelevel) < -5)
{
#attack and miss
attack();
}
else
//nothing we can do except throw junk, or attack and hit
{
if (!ThrowJunkItem())
attack();
}
}
}
}
}
}
void main(int iRound, monster eek, string sText)
{
int iDamTaken=0;
string sTemp;
string sName;
int iStart=0;
int iEnd=0;
boolean bUsedNoodles;
string sAction;
if(eek==zilch)
{
// Try to figure out what we're fighting ... gets around relay browser bug
iStart = index_of(sText, "You're fighting " )+1;
if (iStart > 0)
{
iEnd = index_of(sText, "</span>", iStart);
}
if (iStart > 0 && iEnd > 0)
{
sTemp = substring(sText,iStart+34,iEnd );
if (dbug) { print("PARSED MONSTER NAME: " + sTemp); }
int iCutoff = index_of(sTemp," ");
sName = substring(sTemp,iCutoff+1);
}
eek = string_to_monster(sName);
}
giRound = iRound;
print ("********************************");
print("Round " + iRound + " vs " + eek);
#print(sText);
print ("++++++++++++++++++++++++++++++++");
gbInValley = (my_location() == $location[valley beyond orc chasm]);
if (dbug) { print("Valley=" + boolean_to_string(gbInValley)); }
if (ShieldEquipped() && have_skill($skill[hero of the half-shell]) &&
( my_buffedstat($stat[muscle]) > my_buffedstat($stat[moxie]) ) )
{
gDefenceStat = $stat[muscle];
if (dbug) { print("Hero!"); }
}
else
{
gDefenceStat = $stat[moxie];
if (dbug) { print("Zero :("); }
}
if (iRound == 1)
{
giCurDelevel = 0;
set_property("IllStasis_Delevel", "0");
set_property("IllStasis_StartMP", my_mp());
set_property("IllStasis_StartHP", my_hp());
bUsedNoodles = false;
set_property("IllNeoStasis_UsedNoodles", "false");
gbEnemyNoodled = false;
set_property("IllNeoStasis_EnemyNoodled", "false");
}
else
{
giCurDelevel = string_to_int(get_property("IllStasis_Delevel"));
//if (dbug) { print("giCurDelevel=" + giCurDelevel); }
bUsedNoodles = string_to_boolean(get_property("IllNeoStasis_UsedNoodles"));
gbEnemyNoodled = string_to_boolean(get_property("IllNeoStasis_EnemyNoodled"));
}
//Check the combat state, eg Noodles, damage taken etc
//if (dbug) { print("Parsing damage"); }
iStart = index_of(sText, "You lose " );
if (iStart > 0)
{
iEnd = index_of(sText, " hit point", iStart );
}
if (dbug) { print("iStart = " + iStart + "iEnd = " + iEnd); }
if (iStart > 0 && iEnd > 0)
{
sTemp = substring(sText,iStart+9,iEnd );
iDamTaken = string_to_int(sTemp);
#if (dbug) { print("<color=\"red\">Took Dam: " + iDamTaken + "</color>"); }
if (dbug) { print("Took Dam: " + iDamTaken); }
}
iStart = 0;
iStart = index_of(sText, MSG_NOODLEBREAK);
if (iStart > 0)
{
bUsedNoodles = false;
set_property("IllNeoStasis_UsedNoodles", "false");
}
//Decide on our action, in reverse priority order (ie panic=last)
sAction = "Miss"; //Default
if (MonsterCannotHit(eek))
{
if (dbug) { print("Monster cannot hit..."); }
if (PlayerCannotHit(eek))
{
if (dbug) { print("We cannot hit either...finish"); }
sAction = "Finish";
}
else
{
sAction = "Attack";
}
}
int iHPPct;
iHPPct = 100*my_hp()/my_maxhp();
if (dbug) { print("HP = " + iHPPct + "% (HP=" + my_hp() + "/" + my_maxhp() + ")"); }
if (iHPPct <= HEALTH_PCT)
{
//We're hurting, heal if no higher priority action
if (CheckSkill($skill[saucy salve]) == 0)
{
sAction = "Salve";
}
}
if (giRound == 1 && my_primestat()==$stat[moxie] && index_of(sText, "You get the jump") >= 0)
{
sAction = "Pickpocket";
}
if (iDamTaken >= DAM_THRESHOLD)
//TODO
//Too painful! End fight quickly
{
sAction = "Finish";
}
//else
//{
//}
if (ExpectedMonsterDamage(eek) > (my_hp() + 10))
//danger of death - panic
//TODO
{
if (dbug) { print("PANIC! : Noodled=" + gbEnemyNoodled + ", UsedNoodles=" + bUsedNoodles); }
if (gbEnemyNoodled)
{
if (iHPPct <= HEALTH_PCT)
{
//heal back to safety level
if (CheckSkill($skill[saucy salve]) == 0)
{
sAction = "Salve";
}
}
else
{
sAction = "FinishNOW";
}
}
else
{
if (CheckSkill($skill[entangling noodles])==0 && !bUsedNoodles)
{
sAction = "Noodle";
}
else
{
sAction = "FinishNOW";
}
}
}
if (iRound >= 29)
{
#long enough!
sAction = "Finish";
}
ShowStatusMsg("Action = " + sAction);
//And finally, perform our action
if (sAction == "Attack") attack();
if (sAction == "FinishNOW") FinishHimNOW(eek);
if (sAction == "Finish") FinishHim(eek);
if (sAction == "Salve") use_skill($skill[saucy salve]);
if (sAction == "Miss") DontHurtHim(eek);
if (sAction == "Pickpocket") Pickpocket();
if (sAction == "Noodle")
{
set_property("IllNeoStasis_UsedNoodles", "true");
set_property("IllNeoStasis_EnemyNoodled", "true");
use_skill($skill[entangling noodles]);
}
}