Can we get access to more of mafia's data from ASH?

c_wraith

New member
So, I've just done some work on a simple buff-tending script. (http://kolmafia.us/index.php/board,6.0.html) Along the way, I found some frustrating limitations in the information that the ASH interpreter provides about known items/effects/skills. In my case, I wanted to do some testing with all skills, in order to determine which to use.

The first thing I ran into: There's no way to iterate across all skills. I had to include a list of all the relevant skills in my script. That seems quite silly, as it means that both my script and mafia need to be updated whenever new skills are added. It's also error-prone, as I forgot Springy Fusilli on my first pass, and had to discover it in testing. I'm still not certain I didn't miss something else... I'll only know after either a thorough review or testing in many more situations.

The next thing I found was an inability to get metadata about skills. I wanted to reduce the number of requests mafia was making by equipping my JEW hat if necessary, once per script invocation, instead of every time a buff is used. As it is fully possible that on some invocations of the script, no switching is necessary at all, I didn't want to switch hats unless it was. There isn't any way to query mafia's metadata to determine whether a given skill is a buff or not, so I also had include that information in my script as well.

One of the next revisions I'd like to make to the script is reducing the number of use_skill calls it makes, by basing the first argument of the call on how many turns the buff will be applied for. Mafia has that information already. For me to get at it, I need to add even more data into my script: How many turns a single cast lasts for by default, whether the R&R Legend affects it, and whether the JEW hat affects it.

It's possible to derive all this information from what ASH gets you... But it's quite a lot of unnecessary pain, as it requires extra required script maintenance, debugging, and size.

Is it possible to add more direct access to these values somehow in ASH?
 

holatuwol

Developer
Code:
// We declare a record type in order to hold
// all information related to buffs.

record buff
{
	int type;
	int base_cost;
	string name;
};

// Now we use a built-in feature to acquire
// all the data KoLmafia knows about.

buff [int] pita;
file_to_map( "classskills.dat", pita );

// Now, we use a limitation in KoLmafia's ASH
// to tell you what KoLmafia knows.

foreach s in pita
{
    if ( pita[s].type == 0 )
        print( s + ": " + pita[s].name + " is a passive skill." );

    if ( pita[s].type == 1 )
    {
        if ( skill_to_effect( int_to_skill( s ) ) == $effect[none] )
            print( s + ": " + pita[s].name + " is a self-cast skill that gives no effects." );
        else
            print( s + ": " + pita[s].name + " is a self-cast skill that gives effects." );
    }

    if ( pita[s].type == 2 )
        print( s + ": " + pita[s].name + " is a buff skill." );

    if ( pita[s].type == 3 )
        print( s + ": " + pita[s].name + " is a combat skill." );
}
 

c_wraith

New member
I really am sorry about my attitude there... And that does include enough information for what I'm currently doing. It doesn't include buff duration information, though, which I want for my next planned feature.

Would it be possible to get a snippet like that in either the main documentation or the wiki somewhere? It's not clear at all from the existing documentation what all functionality you can take advantage of with the map_to_file or file_to_map functions.
 

Veracity

Developer
Staff member
I have a few thoughts on this. holatuwol has pointed out how to read one of KoLmafia's built-in data files into a map and thereby gain the same data-driven access as the rest of KoLmafia to that info. Having done so, you can "foreach" over the map. As he pointed out, this gives you most of what you want right now, no changes needed to ASH.

That said, I had considered something similar myself late last summer, when I was finishing up my latest campaign of ASH enhancement, before I bowed out of "hard" KoLmafia development during the fall semester.

I added records and also - at holatuwol's request - the ability to read files formatted like KoLmafia's internal files into them, as holatuwol demonstrated above. I also made a bunch of internal efficiency improvements. One of the things I did was have a global function table that holds all the built-in ASH functions and have that populated exactly once: the first time you invoke an ASH script. I considered having a global variable table as well - and made it easy to add such - but didn't bother, because ASH didn't need any global variables at the time.

Were we to run with your suggestion, I'd do this:

1) Allow a variable to be read-only or read-write. All user-defined ones would be the latter - and there need not be any way in the ASH language itself to let the user define read-only variables. But a read-only variable could not be used on the left side of an assignment - and if it's a map or record, the contents could not be changed either.

2) Define some global variables. For example:

int [skill] SKILLS;

would be a map from skill to int, where int would be the internal skill #. The expectation would be that ASH scripts would just foreach over the map and use the keyvar.

3) And then define a few accessors:

boolean buff_skill( skill );
boolean passive_skill( skill );
boolean combat_skill( skill );

and so on.

Regarding your comment that "mafia has that data already" about how long buffs last...I don't think so. It depends on the skill (compare Rage vs. Tenacity vs. Spirit of Cayenne) and on your equipment (hat or not, accordion or Legend) and so on. If KoLmafia currently has that info available, it gets it programmatically, rather than via a data table. I don't think it does. I think it just refreshes your status after casting skills and reads the current duration from the result.

Not that having a function to calculate turns-per-cast of a skill prgrammatically is a bad idea. It's just not something that KoLmafia itself needs, and so it's not "easy" to provide to ASH.
 

c_wraith

New member
[quote author=Veracity link=topic=637.msg2993#msg2993 date=1166224042]Not that having a function to calculate turns-per-cast of a skill programmatically is a bad idea. It's just not something that KoLmafia itself needs, and so it's not "easy" to provide to ASH.
[/quote]

Hmm. I was going to say that just exposing whether something was an AT song would do the job, but that's not really true. There'd still be nothing to distinguish between the durations of Rage of the Reindeer and Leash of Linguini. I guess I never realized mafia never used that data... At the same time I didn't understand why the "cast" cli command didn't have an option to cast X turns of an effect. Seems I wasn't putting 2 and 2 together, there, duh.

Would you be interested in a patch to mafia itself that adds duration information for each skill that results in a buff, and allows a "cast 40 turns moxie of the mariachi" type of CLI command? This seems to be a weekend coming up, and it'd be a good time to get into mafia's source.
 

holatuwol

Developer
Well, I found a use for knowing the durations of effect you'd get, so I've gone ahead and modified the data table to include that information so I can actually use it (meaning the above script, as posted, won't show you the same information). It doesn't take opera masks into account when it's doing the calculations, but that's an edge case anyway. So, for v10.0:

int turns_per_cast( skill ): Added
 
I'm glad I read this thread. I was still using a modified version of that ancient icy peak meat meat farming script I wrote, and posted on this board. Now due to hard drive failure I am starting it all over again, and would have re-used the old method I had used before shown below:

Code:
int AdvPerCast(skill VarSkill)
{
 if(VarSkill == $skill[Seal Clubbing Frenzy] || VarSkill == $skill[Rage of the Reindeer] || VarSkill == $skill[Patience of the Tortoise] || VarSkill == $skill[Manicotti Meditation] || VarSkill == $skill[Sauce Contemplation] || VarSkill == $skill[Disco Aerobics] || VarSkill == $skill[Moxie of the Mariachi]) {return(5);}
 if(VarSkill == $skill[Musk of the Moose] || VarSkill == $skill[Ghostly Shell] || VarSkill == $skill[Reptilian Fortitude] || VarSkill == $skill[Empathy of the Newt] || VarSkill == $skill[Tenacity of the Snapper] || VarSkill == $skill[Astral Shell] || VarSkill == $skill[Leash of Linguini] || VarSkill == $skill[Springy Fusilli] || VarSkill == $skill[Elemental Saucesphere] || VarSkill == $skill[Jalapeño Saucesphere] || VarSkill == $skill[Jabañero Saucesphere]){return(10);}
 if(VarSkill == $skill[Flavour of Magic]){return(40);}
 if(VarSkill == $skill[Aloysius' Antiphon of Aptitude] || VarSkill == $skill[The Moxious Madrigal] || VarSkill == $skill[Cletus's Canticle of Celerity] || VarSkill == $skill[The Polka of Plenty] || VarSkill == $skill[The Magical Mojomuscular Melody] || VarSkill == $skill[The Power Ballad of the Arrowsmith] || VarSkill == $skill[Brawnee's Anthem of Absorption] || VarSkill == $skill[Fat Leon's Phat Loot Lyric] || VarSkill == $skill[The Psalm of Pointiness] || VarSkill == $skill[Jackasses' Symphony of Destruction] || VarSkill == $skill[Stevedave's Shanty of Superiority] || VarSkill == $skill[The Ode to Booze] || VarSkill == $skill[The Sonata of Sneakiness] || VarSkill == $skill[Carlweather's Cantata of Confrontation] || VarSkill == $skill[Ur-Kel's Aria of Annoyance]){if( item_amount($item[Rock and Roll Legend]) != 0){return(15);} else {return(5);}}
 return(0);
}

I believe it was Nightmist who finished that part of the script. Yeah it's dated, but it covered the skills used by the script. That's one of many huge messes I can leave out this time.

c_wraith feel free to use it till version 10 comes out. I would re-name it to the function name holatuwol listed before using though so when version 10 is released you can simply delete it from the script.

question for holatuwol:
will "int turns_per_cast( skill )" take the wizard hat into account? If so does it count it just being in inventory or count it only if it's equipped?
 

Nightmist

Member
[quote author=efilnikufecin link=topic=637.msg3001#msg3001 date=1166261538]
due to hard drive failure
[/quote]
Ouch... That's bad luck man, hope there wasn't anything too important on the drive.

Heh... xD Just got to love huge aged blocks of repeated "VarSkill == " >>. *sigh* Good ole days eh.
 

holatuwol

Developer
[quote author=efilnikufecin link=topic=637.msg3001#msg3001 date=1166261538]will "int turns_per_cast( skill )" take the wizard hat into account? If so does it count it just being in inventory or count it only if it's equipped?[/quote]
Yes, it counts it being either in inventory or equipped, because KoLmafia will automatically equip it when needed.
 
Top