An alternate between-battle buff caster...

c_wraith

New member
Well, this is my first time working with ASH. It's not horrible, but some of its limitations are a real pain in the ass. My variable naming reflects that...

[red]( To subsequent readers: This above is apologized for below, but better would not to have written something like it in the first place. To c_wraith: You apologized after Veracity pointed it out - I'm putting this note for subsequent readers, as I said. :) -Daychilde )[/red]

Anyway, this script is designed for the situation where you're earning MP each fight, whether by stasis or by equipment, and you want a way to burn that mp between battles. This script just tends to all the buffs you currently have running, casting whatever is lowest on turns. It ignores all effects that don't come from skills you can cast, so those will need to be maintained separately. It was designed to require no configuring, though it'll still need updating every time a buff/self-buff is added to the game. (Once again... Some limitations are a pain in the ass.)

It's not generically suitable for post-stasis use when you have a bunch of skills you want to run sometimes, and not other times... I might make some improvements in that direction, but it would involve working around even more painful ASH limitations, and it's not a high priority. However, for burning Pith Helmet mp or the like, it works pretty well.

There's a bit of funny business going on in the code involving JEW hats, but that's just to compensate for mafia's funny business involving JEW hats. Instead of having two equip calls per buff cast, it reduces it to two equip calls per script invocation, and only if mafia would equip it anyway.

Oh... One further note: This won't do anything if you're over 900,000 turns of all the buffs you can cast. Sorry. I don't think you need any more turns of your buffs at that point.
 

Attachments

  • tendbuffs.ash
    3.9 KB · Views: 146

Veracity

Developer
Staff member
[quote author=c_wraith link=topic=636.msg2986#msg2986 date=1166217129]
Well, this is my first time working with ASH.  It's not horrible, but some of its limitations are a real pain in the ass.  My variable naming reflects that...[/quote]
You're welcome.

Perhaps if you start a thread in the appropriate place describing how you feel ASH could be better, we might pay attention. Although, if you phrase your suggestions as "gripes" or "pains in the ass" then, perhaps not.

I looked at your script. You could simplify it in a number of ways. For example, you might want to consider using the "break" statement to control your loop exits. And perhaps if you maintained a map indexed by skill to hold the current set of buffs, that might simplify your control flow as well; you could just use foreach and the keyvar would be the skill, rather than needing an extra integer variable to increment and use as the index.

But, even though you are limiting yourself to a subset of ASH, this was not a bad effort. It's easy to read!
 

c_wraith

New member
I am sorry about my attitude there. I was really frustrated when typing that post up... Hopefully, I've managed a much better attitude in my feature request thread in the discussion forum. I had a chance to calm down and reflect a bit more sanely on everything while I was typing that up.

There's a "break" statement? Good to know... That'll simplify the loops a lot. Ack. I see it now. I seem to have completely missed the control flow section of the main documentation, so I was being very conservative on my assumptions on what ASH supports. My mistake, and a rather large one.

As for your suggestion involving simplifying the running buffs list... You have a good point involving changing it to use foreach, but I don't see much benefit in having the values actually *mean* anything. If they were the turns remaining of a given buff, I'd have to update it every time I used a skill, which seems silly. I really just want to use foreach to iterate over the keys, and not have *anything* in the values, I think...


Edit:

Attached a new version of the script based on Veracity's feedback. Definitely easier to read, though it may be a bit mysterious why I'm setting everything to 0 in the getRunningSkills result. :)
 

Attachments

  • tendbuffs.ash
    3.7 KB · Views: 115

BDrag0n

Member
As mentioned elsewhere, this script is intended for maintenance with a reasonable MP pool. This version has a few modifications (currently untested, drunk for the day).

- maxcast lowest option (user-configurable) as an alternative to iterating over all the buffs and casting one at a time.
- skips buffs you don't have the MP available for, printing a warning to the gCLI that it has skipped the buff.
- if it's skipped a buff because you have enough maxMP to cast (allowing for MP needed for the next fight) but don't have enough to cast right now, it will do 1 cast of your 2nd lowest other buff then break.

I expect I've messed something up, so double-check the code before you run it :)

Edit: Yup, something wrong and no time to fix just now. Minor bugfixes done, but the "cast 2nd lowest buff" (cast_one) doesn't work at all.
 

Attachments

  • tendbuffs.ash
    5.1 KB · Views: 121
This is a great script that I've been using to simplify keeping my buffs active, but I ran into an annoying bug while using it. The script sets a minimum amount of MP to be kept at the start of the script, and will attempt to burn off any additional MP by casting your lowest turn remaining buffs.

The problem is that after it casts the first buff and moves on to cast the others (say you were casting leash, and you're left over with 9 MP left, enough to cast some jalapeno), it doesn't recalculate the amount of MP you need to burn off, and ends up using a lot of MP restorers in the process of casting your second and third choice buffs. I changed a line to always check how much MP you have remaining at the present moment.

The line I changed is:
Code:
int to_cast=floor(spare_mp)/mp_cost(toUse));
to
Code:
int to_cast=floor((my_mp()-mp_keep)/mp_cost(toUse));

Code:
// tendbuffs.ash  by c_wraith, modified by BDrag0n and QuantumNightmare

##How much MP to keep for the next fight  - this shows up a few times in the script
int mp_keep=12;
int spare_mp=my_mp()-mp_keep;

## Do you want to maxcast the lowest, or cast 1 at a time?
boolean maxcasting=true;

## Don't worry about this one
boolean cast_one=false;

// Frustrating to have to do it this way...
boolean [skill] is_buff;
is_buff[$skill[Aloysius' Antiphon of Aptitude]]         = true;
is_buff[$skill[Astral Shell]]                           = true;
is_buff[$skill[Brawnee's Anthem of Absorption]]         = true;
is_buff[$skill[Carlweather's Cantata of Confrontation]] = true;
is_buff[$skill[Cletus's Canticle of Celerity]]          = true;
is_buff[$skill[Dirge of Dreadfulness]]                  = true;
is_buff[$skill[Disco Aerobics]]                         = false;
is_buff[$skill[Elemental Saucesphere]]                  = true;
is_buff[$skill[Empathy of the Newt]]                    = true;
is_buff[$skill[Fat Leon's Phat Loot Lyric]]             = true;
is_buff[$skill[Ghostly Shell]]                          = true;
is_buff[$skill[Jabanero Saucesphere]]                   = true;
is_buff[$skill[Jalapeno Saucesphere]]                   = true;
is_buff[$skill[Jackasses' Symphony of Destruction]]     = true;
is_buff[$skill[Leash of Linguini]]                      = false;
is_buff[$skill[Manicotti Meditation]]                   = false;
is_buff[$skill[Moxie of the Mariachi]]                  = false;
is_buff[$skill[Musk of the Moose]]                      = false;
is_buff[$skill[Patience of the Tortoise]]               = false;
is_buff[$skill[Rage of the Reindeer]]                   = false;
is_buff[$skill[Reptilian Fortitude]]                    = true;
is_buff[$skill[Sauce Contemplation]]                    = false;
is_buff[$skill[Scarysauce]]                             = true;
is_buff[$skill[Seal Clubbing Frenzy]]                   = false;
//is_buff[$skill[Smooth Movement]]                        = false;
is_buff[$skill[Snarl of the Timberwolf]]                = false;
is_buff[$skill[Springy Fusilli]]                        = false;
is_buff[$skill[Stevedave's Shanty of Superiority]]      = true;
is_buff[$skill[Tenacity of the Snapper]]                = true;
is_buff[$skill[The Magical Mojomuscular Melody]]        = true;
is_buff[$skill[The Moxious Madrigal]]                   = true;
is_buff[$skill[The Ode to Booze]]                       = true;
is_buff[$skill[The Polka of Plenty]]                    = true;
is_buff[$skill[The Power Ballad of the Arrowsmith]]     = true;
is_buff[$skill[The Psalm of Pointiness]]                = true;
is_buff[$skill[The Sonata of Sneakiness]]               = true;
is_buff[$skill[Ur-Kel's Aria of Annoyance]]             = true;


##modified to skip skills you don't have spare max MP to cast
int [skill] getRunningSkills()
{
    int [skill] result;
    foreach s in is_buff
    {   
        if (have_skill(s) && have_effect(skill_to_effect(s)) > 0)
        {

##This prints a warning if you've not enough MP to maintain the buff and still have MP for the next fight
         if(mp_cost(s) > my_maxMP()-mp_keep)
         {
          print("Not enough max spare MP to run "+skill_to_string(s), "red");
          }
         else
          {
            result[s] = 0;
          }
         }
        }
    return result;
}

skill getSkillToCast(int [skill] buffs)
{
    skill best = $skill[none];
    int turnsleft = 900000;

    foreach s in buffs
    {
        int t = have_effect(skill_to_effect(s));
        if (t < turnsleft)
        {
//           if(mp_cost(s) < my_mp()-mp_keep)
//           {
            best = s;
            turnsleft = t;
//           }
//           else {
//           print("Not enough spare to run "+skill_to_string(s), "red");
//           cast_one=true;
//           }
        }
    }
    print("Best skill is" +skill_to_string(best));
    return best;
}

void tendBuffs()
{
    int [skill] toMaintain = getRunningSkills();
    item oldHat = current_equipment($slot[hat]);
    item jhat = $item[jewel-eyed wizard hat];

    boolean switchable = item_amount(jhat) > 0 && oldHat != jhat;
    boolean switched = false;

    while (true)
    {
        skill toUse = getSkillToCast(toMaintain);
        if (toUse == $skill[none] || mp_cost(toUse) > my_mp() - mp_keep)
        {
        print("not enough MP to cast anything");
            break;
        }
        else
        {
            if (switchable && !switched && is_buff[toUse])
            {
                switched = true;
                equip(jhat);
            }
##Add in the maxcasting option
            if(!maxcasting)
            {
            use_skill(1, toUse);
            }
            if(cast_one)
            {
            use_skill(1, toUse);
            print("casting one");
            break;
            }
            else{
            print("using skill");
            int to_cast=floor((my_mp()-mp_keep)/mp_cost(toUse));
            print (to_cast);
            use_skill(to_cast, toUse);
            }
        }
    }

    if (switched)
    {
        equip(oldHat);
    }
    else
    {
        print("leaving your hat alone");
    }
}

void main()
{
    tendBuffs();
}

Otherwise, what is the proper etiquette to follow when doing a bug fix to someone else's file?
 
Top