KoLmafia Guide: Creating an Auto-adventuring Script

From Kolmafia
Revision as of 19:55, 12 July 2010 by imported>Bale
Jump to navigation Jump to search

Alright, here it is! This is a real live auto-adventuring, turn-burning script. This is my simple version of an automatic SlimeTube script for beginning slime players. There are more complex ones out there, but I wanted less complexity and more control.

a) Don't freak. This script is a big one! But we will break it down.

b) Note that I put my void main() statement IN THE MIDDLE. The reason is because I introduce Subroutines. I define my OWN functions that I call. As such, these must be defined before I use them in the main method!

c) Before that, I define a MAP. This variable is used to help me figure out slime damage that will be taken. Note that it is defined OUTSIDE any function!

d) Look at slime_damage. It figures out how much raw damage we will take based on being Covered in Slime for X turns. We use the standard 'figure out an effect', but this time we store off exactly HOW MANY TURNS of the effect I have. The Slime < 1 line is because if unslimed, you will get a new coat of Sliming. Then, I find the Slime Factor based on the turns of slime left. Basically, I have a number between 1 and 10. I feed it to the slime_percentage MAP and it returns a decimal number. I multiply it by my MAX HPs to determine the raw damage that will be taken.

e) Look at CleanupTime. It tries to use the Chamois bucket to clean me. It returns a boolean whether it worked or not.

f) Time for the main function. I have 3 inputs. How many turns to adventure, when I should use a Chamois(based on how much damage Ill take), and how low my HPs can get before I abort.

g) First, I tweak the # of adventures to reflect reality. They might type in 500 turns, but if they only have 150 then we will modify the number accordingly. Similarly, an input of 0 means to use all remaining adventures.

h) Now I have this giant While loop. I keep doing whats inside until we run out of adventures OR have executed how ever many cycles that they wanted done.

i) First, I check current HPs before adventuring. If they are too low, we abort.

j) Next, I call my own functions. First I figure out how much slime damage I am expected to take. (NOT including resistances!). If its more than Max HPs, I abort.

k) Same deal, except I compare slime damage vs the tolerence. I like this function. If you have 1800HPs, you probably don't want to eat 1700 on slime! It wont kill you, but that is expensive to recover from.

l) Now, I check slime damage vs current HP. If for some reason your Slime damage tolerence is high, but your HPs get too low and your abort-clause is too high, you need to be cleaned so you don't get killed.

m) In all cases, I call the cleanup() method that I made myself to try to use a chamois.

n) After all those checks, I go ahead and do 1 adventure in that location. Stuff to note: i.) It will use YOUR custom combat script to fight! Make sure it is set right.

ii.) It will use YOUR 'Adventure location Choices' for non-combat (tickle uvula, etc) adventures. Make sure the right choices are set for the slimeTube. (do this by selecting Slime Tube as your location under the 'Adventure' tab, and click the Choices tab.)

o) You see that some non-combat adventures might not actually consume an adventure. Therefore before doing the adventure I save off a temporary counter. After the adventure I compare the pre-adventure count with the post-adventure count, and that way I know whether to increment the main adventure counter or not.

 ## These indicate percent of damage taken by Covered in Slime, by turns-remaining.
 float[11] slime_percent;
 slime_percent[0] = 0;
 slime_percent[1] = 5.334167;
 slime_percent[2] = 4.001677;
 slime_percent[3] = 2.9025;
 slime_percent[4] = 2.016667;
 slime_percent[5] = 1.325;
 slime_percent[6] = .805833;
 slime_percent[7] = .4391667;
 slime_percent[8] = .200833;
 slime_percent[9] = .066667;
 slime_percent[10] = .01;

int slime_damage()
{
  int slimeTurns = have_effect($effect[Coated in Slime]);
  if (slimeTurns < 1)
  {
    slimeTurns = 10;
  }

  int slimeDmg = my_maxhp() * slime_percent[slimeTurns];
  print("Calculated slime dmg = " +slimeDmg);
  return slimeDmg;
}

boolean cleanupTime()
{
 visit_url( "clan_slimetube.php?action=chamois" );
 if ( have_effect( $effect[Coated in Slime] ) > 0 )
 {
   ## Something must have gone wrong.
   return false;
 }
 print ("Slime cleaned with Chamois");
 return true;
}

void main (int howManyTurnsToAdventure, int howManyHPsToLoseBeforeChamois,
int whatHPlevelToAbortScriptAt)
{
 ## Keep track of how many adventures we have done.
 int adventureCounter = 0;

 ## Adjust desired adventures:  If 0 OR not enough adv left, use them all.
 if( howManyTurnsToAdventure < 1 ) howManyTurnsToAdventure = my_adventures();
 if( howManyTurnsToAdventure > my_adventures() ) howManyTurnsToAdventure = my_adventures();

 ## The main loop.
 while( my_adventures() > 0 && (howManyTurnsToAdventure-adventureCounter) > 0 )
 {
   ## Check current HPs vs the script abort level.
   if (my_hp() <= whatHPlevelToAbortScriptAt)
   {
     print("Your HPs are below your whatHPlevelToAbortScriptAt");
     print("You might want to use a chamois to clean yourself!");
     abort();
   }

   ## This checks slime dmg vs your MAX HPs. (If you wanted to add auto-heal code.)
   if( slime_damage() >= my_maxhp() )
   {
     print ("Expected slime dmg is more than your MAX HP!");
     if (!cleanupTime())
     {
       abort("Couldn't clean. Check Chamois bucket");
     }
   }

   ## This checks slime dmg vs CURRENT HPs.
   ## Regardless of your tolerence, you need to stop the slime damage.
   if ( slime_damage() >= howManyHPsToLoseBeforeChamois)
   {
     print ("Expected slime dmg is more than your tolerence.");
     if (!cleanupTime())
     {
       abort("Couldn't clean. Check Chamois bucket");
     }
   }

   if ( slime_damage() >= my_hp() )
   {
     print ("Expected slime dmg is more than your current HPs");
     ## IF You want to add the ability for this script to heal yourself,
     ## This would be a great place for it.
     if (!cleanupTime())
     {
       abort("Couldn't clean. Check Chamois bucket");
     }
   }
   
   int temporaryAdvCounter = my_adventures();

   ## Use a single adventure. Note, non-combat MAY NOT use an actual adventure.
   adventure( 1 , $location[The Slime Tube] );

   ## See if that adventure actually took an adventure.
   if (temporaryAdvCounter > my_adventures())
   {
     ## Our adventures decreased. Therefore this did take an adventure.
     adventureCounter = adventureCounter + 1;
   }

   print ("Ok, done with adventure " +adventureCounter +" of " +howManyTurnsToAdventure);
 }
}

Continue to Post-Lesson 6: Commonly Used ASH Commands