Is there a script or will it be part of daily deeds for campground workshed items?

Tom Sawyer

Member
For example the LP-ROM burner. A script that will automatically max out your mana and then make as many recordings as possible? Like so many other things I tend to forget or overlook a quick script from the masters of scripting would be awesome :)
 

ereinion

Member
I was looking into this, but I am struggling with creating a regex for matching the skills in the html. So far I have this:
Code:
script "campground_caster.ash";
notify "ereinion";

void main() {
    int[skill] available_skills; string info_from_campground;
    matcher skills_left;
    info_from_campground = visit_url("campground.php?action=lprom");
    if (info_from_campground.contains_text("Choose a Song")) {
        available_skills[$skill[The Ballad of Richie Thingfinder]] = 1;
        skills_left = create_matcher("The Ballad of Richie Thingfinder \((\\d+)", info_from_campground);
        print(skills_left.group());
    } else {
        print("You don't have a warbear LP-ROM burner in your workshed");
    }
}
More or less based on the sample code I found on the wiki-page for regexes. However, this fails to yield any results.


Now, I've messed about a bit on some regex testing pages and I think the pattern should be something like "(?<=The Ballad of Richie Thingfinder \()(\d+)", but upon trying to put that into the matcher I get an error on invalid pattern syntax. So I was wondering if any of you guys could give me some pointers on where I should go from here?
 

Bale

Minion
There are three errors in the above code.
  • The first is that you had a single \ in front of the first parenthesis. You need to double that because you are passing it through a parser, as you did in front of d. Escape the escape character.
  • Next, you forgot to do find(skills_left) before checking the group.
  • Third You are checking group(0) instead of group(1) to find the number of turns remaining.


Try it like this:

Code:
void main() {
    int[skill] available_skills; string info_from_campground;
    matcher skills_left;
    info_from_campground = visit_url("campground.php?action=lprom");
    if (info_from_campground.contains_text("Choose a Song")) {
        available_skills[$skill[The Ballad of Richie Thingfinder]] = 1;
        skills_left = create_matcher("The Ballad of Richie Thingfinder \\((\\d+)", info_from_campground);
        if(skills_left.find())
            print(skills_left.group(1));
        else print("Not found");
    } else {
        print("You don't have a warbear LP-ROM burner in your workshed");
    }
}

Of course you'll need to create a more general purpose match to find all skills, rather than just one skill, but you should be on the right path now. I look forward to seeing the finished script. Don't hesitate to ask more questions and post more bad code for comment.
 
Last edited:

ereinion

Member
There are three errors in the above code.
  • The first is that you had a single \ in front of the first parenthesis. You need to double that because you are passing it through a parser, as you did in front of d. Escape the escape character.
Ah, yes, I had missed that. I was a bit unsure about why the author of the wiki-page pointed out that there were two backslashes before d+, but I think I'm starting to get it now :)
  • Next, you forgot to do find(skills_left) before checking the group.
Now that was a really silly mistake, I can't believe I missed that >_<

  • Third You are checking group(0) instead of group(1) to find the number of turns remaining.
Yes, it seems I had misunderstood how the indexing works - it's a good thing I've got you to help me point out my errors :D Thanks a lot for your help. As it turns out, I think I may not have to use regexes anyway, or at least not for this part of the script, it seems I can get all the information I need from properties and from the proxy-fields of the skills (if I figure out how to access them). I may still have to check for the skills in the html for the page, but that should be fairly simple :) Just in case you are curious then my latest attempt at using regexes looks like this:

Code:
script "campground_caster.ash";
notify "ereinion";

void main() {
    int[skill] available_casts; string info_from_campground;
    matcher max_casts; string pattern;
    
    info_from_campground = visit_url("campground.php?action=lprom");
    
    if (info_from_campground.contains_text("Choose a Song")) {
        available_casts[$skill[The Ballad of Richie Thingfinder]] = to_int(get_property("_thingfinderCasts"));
        available_casts[$skill[Benetton's Medley of Diversity]] = to_int(get_property("_benettonsCasts"));
        available_casts[$skill[Elron's Explosive Etude]] = to_int(get_property("_elronCasts"));
        available_casts[$skill[Chorale of Companionship]] = to_int(get_property("_companionshipCasts"));
        available_casts[$skill[Prelude of Precision]] = to_int(get_property("_precisionCasts"));
        available_casts[$skill[Donho's Bubbly Ballad]] = to_int(get_property("_donhosCasts"));
        available_casts[$skill[Inigo's Incantation of Inspiration]] = to_int(get_property("_inigosCasts"));
        
        foreach key in available_casts {
            pattern = to_string(key) + " \\(\\d+\\/(\\d+)";
            max_casts = create_matcher(pattern, info_from_campground);
            if (max_casts.find()) {
                //print(max_casts.group(1));
                available_casts[key] = max_casts.group(1) - available_casts[key]
            } else {
                available_casts[key] = 0
            }
        }
    } else {
        print("You don't have a warbear LP-ROM burner in your workshed");
    }
It evened seemed to work, it's almost a shame max_casts is available from the proxy-fields as well :)

Again, thanks for your help, I'll let you know how the work progresses.
 
Last edited:

Bale

Minion
You're welcome.

As it turns out, I think I may not have to use regexes anyway, or at least not for this part of the script, it seems I can get all the information I need from properties and from the proxy-fields of the skills (if I figure out how to access them).

Good point. $skill[].dailylimit shows how many casts are left for the day, so you can actually do without any string parsing at all. (Value of -1 indicates that there is no limit.) Hopefully my little lesson will eventually be useful in the future even if you cannot use it now.


Code:
void main() {
    if (visit_url("campground.php?action=lprom").contains_text("Choose a Song")) {
        foreach sk in $skills[The Ballad of Richie Thingfinder, Benetton's Medley of Diversity, Elron's Explosive Etude, Chorale of Companionship, 
          Prelude of Precision, Donho's Bubbly Ballad, Inigo's Incantation of Inspiration]
            if(have_skill(sk) && sk.dailylimit > 0)
                print("Make " + sk.dailylimit + " recordings of "+sk);
    } else {
        print("You don't have a warbear LP-ROM burner in your workshed");
    }
}

Of course, if not an AT you'll need to skip the AT only songs.
 
Last edited:

ereinion

Member
Heh, that was compact :)

I feel that I am quite close to finishing a first draft for the script, but for some reason I don't manage to make the actual recordings :p

Which is odd considering that when I put the string I get printed from my print-statement into a cli-command (ash visit_url(string)) it seems to work. Maybe you can shed some light on it? The relevant parts are towards the end of the code.
Code:
script "campground_caster.ash";
notify "ereinion";

void main() {
    int[skill] effect_number; string info_from_campground; familiar used_familiar;
    matcher available_in_list; int number_of_casts; string url_to_submit;
    
    // Gather info on availability
    info_from_campground = visit_url("campground.php?action=lprom");
    
    if (info_from_campground.contains_text("Choose a Song")) {
        // Initialize map of skills/effectnumbers
        effect_number[$skill[The Ballad of Richie Thingfinder]] = 0;
        effect_number[$skill[Benetton's Medley of Diversity]] = 0;
        effect_number[$skill[Elron's Explosive Etude]] = 0;
        effect_number[$skill[Chorale of Companionship]] = 0;
        effect_number[$skill[Prelude of Precision]] = 0;
        effect_number[$skill[Donho's Bubbly Ballad]] = 0;
        effect_number[$skill[Inigo's Incantation of Inspiration]] = 0;
        
        // Assign effectnumbers for available skills
        foreach key in effect_number {
            available_in_list = create_matcher(to_string(key), info_from_campground);
            if (available_in_list.find()) {
                effect_number[key] = to_int(to_effect(key));
            } else {
                effect_number[key] = 0;
            }
        }
        
        // Maximize mp
        cli_execute("checkpoint");
        used_familiar = my_familiar();
        if (have_familiar($familiar[Disembodied Hand]) && used_familiar != $familiar[Disembodied Hand]) {
            use_familiar($familiar[Disembodied Hand]);
        }
        maximize("mp", false);
        
        // Loop through the skills and start casting
        foreach key in effect_number {
            if (effect_number[key] != 0) {
                while (key.dailylimit > 0 && my_maxmp()*0.9 >= mp_cost(key)) {
                    number_of_casts = floor(my_mp()/mp_cost(key));
                    if (number_of_casts > key.dailylimit) {
                        number_of_casts = key.dailylimit;
                    }
                    url_to_submit = "choice.php?whicheffect=" + to_string(effect_number[key]) + "&times=" + to_string(number_of_casts) + "&pwd&whichchoice=821&option=1";
                    print("Casting " + to_string(key) + " " + to_string(number_of_casts) + ((number_of_casts>1)? " times." : " time."));
                    print(url_to_submit);
                    visit_url(url_to_submit);
                    restore_mp(to_int(my_maxmp()*0.9));
                }
            }
        }
    } else {
        print("You don't have a warbear LP-ROM burner in your workshed");
    }
}
 
Last edited:

Bale

Minion
The solution to your problem is that you are making choices in a choice adventure, but you first need to encounter the choice adventure! Once you start the choice adventure, you can record any number of songs until you take another action. Then after restore_mp() you'll need to encounter the choice again. The url to start recording songs is...

Code:
visit_url("campground.php?action=lprom");

If you don't mind my asking, why did you decide to use string parsing instead of have_skill() when mafia already possess that information? Also, you didn't add any code to keep from using AT songs when you're not an AT. Those choices are present in the drop-down although the character gets scolded if they are chosen.
 
Last edited:

lostcalpolydude

Developer
Staff member
Switching to a disembodied hand and doing other stuff to maximize MP would take you out of the choice adventure, making all the stuff in the choice adventure fail.
 

Bale

Minion
Ah. I missed that he actually did start the choice before changing gear. Also, here's a nice trick for maximizing: maximize("mp, switch disembodied hand", false);
 

ereinion

Member
I assumed that they were absent from the dropdown, if you visited the burner without being an AT (apparently I was wrong) - that is also the reason I didn't use have_skill() as I assume that returns true even if you can't cast the skills. However, maybe the proxy-field dailylimits returns 0 when you are not an AT, preventing the script from entering the while-loop? If someone who's not an AT and who has at least some of the AT-exclusive skills could check that, that would be great :)

As for how I get the choiceadventure to work, do I just put the two urls in two separate lines, or do I concatenate the the address you gave me and the one generated by the script to one?

The reason I didn't include the switch familiar-statement in the maximize command, was that I didn't think the maximizer would consider equipment for the familiar you switch in, but after testing in the cli it appears I was wrong here as well :)

Thanks a lot for your continued help, it's really very simple to write scripts when I get as good support as I've gotten here ;)

- edit - On a completely different note, is there any way to see what formula mafia uses to calculate how many potions it needs to restore mp to the given point? I have it set to use generic mana potions, and it seems to overshoot the goal by a far bit, meaning that a lot of the mp is wasted when I try to restore to 90%.
 
Last edited:

Winterbay

Active member
Code:
[COLOR=olive]> ash to_skill("benetton")[/COLOR]

Returned:      Benetton's Medley of Diversity
level => -1
traincost => 0
class      => Accordion Thief
libram => false
passive => false
buff      => true
combat => false
song => false
expression => false
permable      => true
dailylimit => 0
timescast => 0

[COLOR=olive]>      ash my_class()[/COLOR]

Returned: Pastamancer
primestat =>      Mysticality

[COLOR=olive]> ash      have_skill(to_skill("benetton"))[/COLOR]

Returned: true
 

Bale

Minion
However, maybe the proxy-field dailylimits returns 0 when you are not an AT, preventing the script from entering the while-loop?

Ah. This is true. This time I missed something.

As for how I get the choiceadventure to work, do I just put the two urls in two separate lines, or do I concatenate the the address you gave me and the one generated by the script to one?

I'd prefer the first because you don't need to hit campground.php?action=lprom unless you leave the choice adventure. Better not to get the server hit just because you decided to record another song with the MP you still possess.
 

ereinion

Member
Ok, so I thought this was going to work:
Code:
script "campground_caster.ash";
notify "ereinion";

void main() {
    int[skill] effect_number; string info_from_campground; familiar used_familiar;
    int number_of_casts; string url_to_submit;boolean at_burner = false;
    
    // Gather info on availability
    info_from_campground = visit_url("campground.php?action=lprom");
    
    if (info_from_campground.contains_text("Choose a Song")) {
        // Initialize map of skills/effectnumbers
        effect_number[$skill[The Ballad of Richie Thingfinder]] = 0;
        effect_number[$skill[Benetton's Medley of Diversity]] = 0;
        effect_number[$skill[Elron's Explosive Etude]] = 0;
        effect_number[$skill[Chorale of Companionship]] = 0;
        effect_number[$skill[Prelude of Precision]] = 0;
        effect_number[$skill[Donho's Bubbly Ballad]] = 0;
        effect_number[$skill[Inigo's Incantation of Inspiration]] = 0;
        
        // Maximize mp
        cli_execute("checkpoint");
        used_familiar = my_familiar();
        maximize("mp, switch disembodied hand", false);
        
        // Loop through the skills and start casting
        foreach key in effect_number {
            
            effect_number[key] = to_int(to_effect(key));
            
            while (key.dailylimit > 0 && my_maxmp()*0.9 >= mp_cost(key)) {
                if (my_mp() < mp_cost(key)) {
                    restore_mp(to_int(my_maxmp()*0.9));
                    at_burner = false;
                }
                number_of_casts = floor(my_mp()/mp_cost(key));
                if (number_of_casts > key.dailylimit) {
                    number_of_casts = key.dailylimit;
                }
                url_to_submit = "choice.php?whicheffect=" + to_string(effect_number[key]) + "&times=" + to_string(number_of_casts) + "&pwd&whichchoice=821&option=1";
                print("Casting " + to_string(key) + " " + to_string(number_of_casts) + ((number_of_casts>1)? " times." : " time."), "blue");
                if (!at_burner) {
                    visit_url("campground.php?action=lprom");
                    at_burner = true;
                }
                print(url_to_submit);
                visit_url(url_to_submit);
            }
        }
        if (my_familiar() != used_familiar) {
            use_familiar(used_familiar);
        }
        outfit("checkpoint");
    } else {
        print("You don't have a warbear LP-ROM burner in your workshed");
    }
}
But apparently I'm still doing something wrong, because no songs are produced.

I tried putting the string put out by the print-statement into the mini-browser and it produces the correct result (a recording), even if I don't visit the LP-ROM burner first:

Have you got any idea on where I am going wrong?
 
Last edited:

Winterbay

Active member
Things I've found out by testing that code: 1) you don't actually need to visit the burner in order to record things, 2) submitting the printed URL in the mini-browser works just fine, 3) submitting it via visit_url in the CLI works fine, 4) the script does nothing (well apart from the maximization thingie).

ETA: So... why is there a difference in submitting the URL via visit_url in a script and via ash-converting the CLI? I though that was exactly the same thing?
 
Last edited:

Veracity

Developer
Staff member
Code:
url_to_submit = "choice.php?whicheffect=" + to_string(effect_number[key]) + "&times=" + to_string(number_of_casts) + "&pwd&whichchoice=821&option=1";
Why that, rather than:

Code:
url_to_submit = "choice.php?whicheffect=" + to_string(effect_number[key]) + "&times=" + to_string(number_of_casts) + "&pwd&whichchoice=821&option=1";
You certainly do not want the HTML entity for & instead of & itself in the URL.
 

ereinion

Member
Ah, I assumed that since the result when I try:
Code:
ashq print("&times")
[COLOR=olive]> ashq print("×")[/COLOR]

×
Is an ×, it would be better to use the HTML entity (the string url_to_submit) also had an × instead of &times when printed at least), as that looked correct when printed :) I guess I should have known better than to trust looks ;)

Fixing this issue the script does indeed work. Thanks a lot for all your help :)

I made another thread for the script, as that will make it easier for potential users to find it: http://kolmafia.us/showthread.php?14593-Campground-caster-makes-all-your-LP-ROM-recordings-for-you
 
Last edited:

Veracity

Developer
Staff member
The gCLI displays HTML using Java's built-in HTML renderer. That is known to be quirky. I am surprised that "&times" prints as the times sign, since the actual entity would be "×". I'll play with this a bit to see if we are munging the string before passing it to the HTML renderer or something, but perhaps this is one of those quirks I mentioned.

In any case, URLs are not HTML encoded. They are URL encoded, so a space is a +, for example, but & needs to be the single character.
 

ereinion

Member
I see. I'll try to remember for next time :) Again, thanks a lot for your help, and feel free to come with any other suggestions for improvements on my code that you may think of :)
 
Top