SmartStasis -- a complex script for a simple CCS

zarqon

Well-known member
Haha, my point was simply that I am basically entirely unable to support the current released version.

But ok; I'll make a promise. A new, smarter SS will be uploaded by Jan 21 at the latest (palindromic date hehe). It will absorb FTF (thus obsoleting it) and require the new BatBrain.ash, keeping the grand total of required files the same. It will contain some features which are not fully developed, probably at least a few data file inaccuracies, and it will most likely inspire both awe and complaints. Be ready!
 

Bale

Minion
I'm marking 121 on my calendar. I'm eager to see it even if the juicy bits don't work yet. At least it is fully macrofied now so I'll use it again!
 

zarqon

Well-known member
Ok, here's something I would love help with.

I have the basic functions ready that will execute a chain of commands as a macro, but it needs to have some flexibility. I need to basically duplicate mafia's "mafiaround" concept for macro building (although restoring enough MP to do something would already be part of the macro and thus unnecessary here). For auto-macrofying to work sexily, I basically need to duplicate all the auto-responses that currently live in FTF's act() function. Things that are solely detections can be left out (they can still be detected by looking at the resulting page), but actual interventions need to be worked in:

  • Poison removal -- it's actually best here if the macro aborts if you become poisoned.
  • Rusty weapon getting slimed should abort the macro.
  • Throwing the molybdenum magnet when gremlins have a tool.
  • Attacking monsters that have the disc with the ruby rod.
  • Learn dance skills from DB nemesis monsters (actually, I think this is still broken in FTF).
  • Shooting your yellow ray at monsters in ftf_yellow.

Basically, most of act()'s "reactions" section needs to be duplicated here, but as conditionals within the macro. The act() function will also need to be modified, so that it knows whether or not the reaction has already been performed. This is an annoying thing for me to do (I would probably need to do hours of research), so I would appreciate if someone who knew macro syntax better than I would help me put this together. You'd need to modify this:

PHP:
string do_macro(string mac) {
   return act(visit_url("fight.php?action=macro&macrotext="+url_encode(mac)));
   // is that url_encode() necessary?
}

string do_macro(advevent[int] actionlist) {
   buffer res;
   matcher blar;
   foreach i,o in actionlist {
      blar = create_matcher("(.+) (.+)?(, )?(.+)?",o.id);
      if (i > 0) res.append("; ");
      if (blar.find()) switch (blar.group(1)) {
         case "runaway": res.append("mark r; runaway; goto r"); break;
         default: res.append(o.id);      // id's are macro-ready
      }
   }
   return macro(res);
}

as well as checking the page text in act() to make sure that the appropriate reactions were not already taken by a macro.
PHP:
  // reactions
   if (item_amount($item[molybdenum magnet]) > 0 && contains_text(to_string(last_monster()),"Gremlin") && contains_text(action,"whips") &&
       (contains_text(action,"a hammer") || contains_text(action,"a crescent wrench") ||      // gremlin has tool
        contains_text(action,"pliers") || contains_text(action,"a screwdriver")))
      return act(throw_item($item[molybdenum magnet]));
   if (have_equipped($item[ruby rod]) && my_location() == $location[seaside megalopolis] &&   // monster has disc
       (contains_text(action,"A mechanical hand emerges") || contains_text(action,"liquid nitrogen") || contains_text(action,"freaky alien thing") ||
        contains_text(action,"vile-smelling, milky-white") || contains_text(action,"spinning, whirring, vibrating, tubular")))
      return act(attack());
   if (my_class() == $class[disco bandit] && have_skill($skill[gothy handwave]) && my_mp() > 0) {
      switch (last_monster()) {                               // learn dance skills from DB nemesis enemies
         case $monster[breakdancing raver]: if (!have_skill($skill[break it on down]) && contains_text(action,"he raver drops "))
            return act(use_skill($skill[gothy handwave])); break;
         case $monster[pop-and-lock raver]: if (!have_skill($skill[pop and lock it]) && contains_text(action,"movements suddenly became spastic and jerky."))
            return act(use_skill($skill[gothy handwave])); break;
         case $monster[running man]: if (!have_skill($skill[run like the wind]) && contains_text(action,"The raver turns "))
            return act(use_skill($skill[gothy handwave]));
      }
   }
   if (my_familiar() == $familiar[he-boulder] && get_counters("Major Yellow Recharge",1,150) == "" &&
       contains_text(action," yellow eye") && contains_text(to_lower_case(vars["ftf_yellow"]),to_lower_case(last_monster().to_string())))
      return act(use_skill($skill[point at your opponent]));
 
Last edited:

slyz

Developer
(although restoring enough MP to do something would already be part of the macro and thus unnecessary here)
If you submit the macro yourself, from a consult script, I don't think Mafia will append anything. So you would need to reproduce the mafiamp sub too ^^
 

zarqon

Well-known member
Nope. BatMan already knows about your MP and would have already added restoration to your macro if needed. It doesn't need to be in the macro as a conditional.
 

StDoodle

Minion
Harumph, this could easily be a result of my non-programmer mind, but without knowing the general structure of a "normal" macro generated by your script, it seems unlikely I could help with any of those, as I have no idea how to structure it to play well with the rest.

Edit to add:
Poison removal -- it's actually best here if the macro aborts if you become poisoned.
Code:
abort haseffect Hardly Poisoned at All || haseffect A Little Bit Poisoned || haseffect Somewhat Poisoned || haseffect Really Quite Poisoned || haseffect Majorly Poisoned
You can just put the above anywhere in your macro for poison-checking.
 
Last edited:

zarqon

Well-known member
BatMan's macro will be as utterly simple as possible. A series of actions, separated by semicolons. Since it would be generated predictively specifically for this combat, it won't even need to check for presence of items or skills before using them. Basically, if there are any conditionals that need to be added, it could check for those after every action.

Which might mean changing
if (i > 0) res.append("; ");
to
if (i > 0) res.append("; call batround; ");

And then inserting batround somewhere.
 

StDoodle

Minion
As far as checking to see what has already happened in a fight, the two simplest solutions are probably 1) Save info outside of the script (to a user pref or file); I'd go with saving a map that contained easy-to-check info, probably. (This would also be easier to add on to later.) or 2) Embed the info into the html of the page as a comment and / or hidden fields. I like 2 better in theory, but in practice a single page load failure would cause such a cascade of problems that 1 might be better.

Unless of course you're already saving previous page text, or submitting exactly one macro every time and never re-checking; but it seems 'better' to allow for two-stage macros in many cases, IMO (esp. for a check to see if a fight can be finished off with a 0 or 1mp skill vs. a more expensive one in the last round).
 

Theraze

Active member
It being a macro means KoL runs it until it's no longer valid, right...? You send the macro once, and it runs all 30 turns in one refresh. No page load failures possible, unless the script aborts for some reason...
 

StDoodle

Minion
Theraze; it's often quite wasteful to use the same high-damage attack over and over; using something like clobber or toss at the end is often desirable, as long as it will finish off the monster.

And trust me, it's quite possible to script a fight so that it sumbits a macro that handles most of the fight, and then loads and analyzes the page before submitting another macro. I've been working on my own fight script for that, actually (which hopefully won't be necessary eventually...) :)
 

Theraze

Active member
But that was the purpose of the call batround, wasn't it? To recalculate what the best action for that round would be (whether it's to do a low damage attack or high, all of that should be calculated throughout) and do that... if it's all internal to KoL's mafia system then it should be able to intelligently recalculate what it's doing but to have it load the entire fight without a problem...
 

slyz

Developer
Theraze: Batround would only detect a few things, and act accordingly:
  • Poison removal -- it's actually best here if the macro aborts if you become poisoned.
  • Rusty weapon getting slimed should abort the macro.
  • Throwing the molybdenum magnet when gremlins have a tool.
  • Attacking monsters that have the disc with the ruby rod.
  • Learn dance skills from DB nemesis monsters (actually, I think this is still broken in FTF).
  • Shooting your yellow ray at monsters in ftf_yellow.

The best action for each round would be calculated beforehand by the script and build into a macro. BatBrain will be a combat simulator that builds a straightforward list of actions, not a script that builds an intelligent macro that chooses the best action.
 

zarqon

Well-known member
Slyz has it exactly. A macro is simply a page submit that can handle more than one round. This changes little as far as parsing is concerned, BUT in the event that the page contains text which needs a response, the detection remains the same but we need to add a check to make sure that the macro didn't already handle it.

It would actually be easier to simply abort the macro for any of these reactions, allowing act() to work as normal, but it would result in more server hits.

Heck, it would actually be easier to submit even single actions as single-round macros, since action ID's in BatMan are all macro-ready commands. But that would give un-useful CLI output, so I stick to using the more specific ASH commands (or visit_url()'s) for that.

The actual macros BatMan submits will contain almost no logic. The macro is constructed predicitively, based on all available knowledge. For situations where combat options need to be drastically reconsidered, the macro should abort and allow BatMan to recalculate and submit a new macro.
 

Theraze

Active member
Hmm... but since health on mobs is a (somewhat) known (with the 5% margin of variance), and damage done by command would be considered while constructing the macro, it shouldn't be too difficult to do if health > 100 [do minattack > 100] else if health > 50 [do minattack > 50] else if health > 10 [do minattack > 10] else [do free attack]...

Right?
 

zarqon

Well-known member
You underestimate the power of BatMan. It will consider a lot more than just monster HP, and submit the sequence of actions that will kill the monster at the least cost to you.

But this is currently not a particularly relevant discussion, since 1) BatMan is still not ready for release, and b) the first incarnation of BatMan will not auto-macrofy.
 

Theraze

Active member
Well, I was originally referring to StDoodle's request to have it do the minimum cost item, which it will do if I understand the way you were describing the plan.

But all of that is actually irrelevant to SmartStasis. So I suppose I should stop the BatMan discussion, or wander it over to that thread if we really want to keep pondering the distant eventual future. :p
 
Top