Bug Actually Ed and consult scripts: failure when hitting underworld entrance

So I've only recently started playing around with a consult script. And I'm running up against a wall where the script is still trying to run, even when Mafia hits the Underworld entrance choice adventure.

My script reads:
Code:
void main(int round, monster foe, string page) {
    use_skill($skill[Storm of the Scarab]);
}

This works fine anytime I win the combat before dying. But when I die, and Mafia hits the Underworld choice adventure, it spits out: You don't have a skill uniquely matching "1 Storm of the Scarab". Then I have to run through the choice manually, via the Relay Browser, and run the script again when I'm back in combat.

If the script would just hand control back off, Mafia would navigate the choice adventure correctly, and return me to combat. (It was doing this correctly before I was using a consult script). But it looks like the script is still trying, and failing, to run the choice adventure on its own.

How can I fix this? Can I tell the script to stop without using abort(), which will stop Mafia altogether?
 
If you add a check that you have the skill first, does that help?

Code:
if(have_skill($skill[Storm of the Scarab]))
{
    use_skill($skill[Storm of the Scarab]);
}
Thanks for the suggestion. Unfortunately, that throws the same error.

If your consult script isn't long, you could convert it to a combat filter and use that. It won't fail this situation since it does not directly try to invoke the skill but rather it returns the string "skill storm of the scarab" when it would be called.
I think that I'd have to be adventuring with adventure(int, location, string) in order to use a combat filter, right? I'm just trying to get this consult script to work when adventuring either through the relay browser, or with Mafia's Adventure tab.
 

Theraze

Active member
The problem from an end-user standpoint is that it appears to believe that the combat is continuing while in the underworld. When it tries to continue the combat and fails, you either get that sort of error or one regarding being overdrunk.
 
The problem from an end-user standpoint is that it appears to believe that the combat is continuing while in the underworld. When it tries to continue the combat and fails, you either get that sort of error or one regarding being overdrunk.
Exactly right. If Mafia could tell that the combat was over, and take control back from the script, it could navigate the choice correctly.

It occurred to me that I could detect the choice adventure in-script; after all, the script has the page HTML. But I'm not sure how to tell the script to select one of the options at that choice adventure. Hmm...
 

Theraze

Active member
I believe it's already actually supposed to do that and default to fighting the battle twice before it aborts to the underworld choice. The problem appears to be that it doesn't use that when coming from a consult script, but only with simple actions.
 
I believe it's already actually supposed to do that and default to fighting the battle twice before it aborts to the underworld choice. The problem appears to be that it doesn't use that when coming from a consult script, but only with simple actions.
Yep. My installation of Mafia handles this just fine when it's running combat based on a CCS. It will navigate through the choice adventure correctly, as determined by my _edDefeats and edDefeatAbort preferences. But it never gets to that point when using a consult script.

With a little more research, it looks like I could call visit_url("choice.php?pwd&whichchoice=1023&option=2") to navigate through the choice? Hmm... I'll have to try that.
 
Last edited:
Okay, hard-coding the choice visit into the script worked. So now it reads:

Code:
void main(int round, monster foe, string page) {
    if(contains_text(page, "Like a Bat Into Hell")) {
        visit_url("choice.php?pwd&whichchoice=443&option=2");
    }
    else use_skill($skill[Storm of the Scarab]);
}

I'm still perplexed as to why it doesn't work natively, but this is a not-too-kludgy workaround. Woohoo! Thanks for the input, everyone.
 
Last edited:

Theraze

Active member
Since this is actually a bug report, could this thread be moved to the proper board? There is a hackish workaround, but two facts remain:
1) This is a mafia bug where consult scripts don't properly pass their handling to the choice handler when dying in Ed-runs, and
2) This is not a CCS script for the repository and so is currently in the wrong place.
 
So I've discovered an issue with this workaround.

Code:
void main(int round, monster foe, string page) {
    if(contains_text(page, "Like a Bat Into Hell")) {
        visit_url("choice.php?pwd&whichchoice=443&option=2");
    }
    else use_skill($skill[Storm of the Scarab]);
}

It works OK if the 'else' is an action that is guaranteed to kill the monster in one round. But it fails with other options. If I try to use this:

Code:
void main(int round, monster foe, string page) {
    if(contains_text(page, "Like a Bat Into Hell")) {
        visit_url("choice.php?pwd&whichchoice=443&option=2");
    }
    else {
[COLOR="#0000FF"]        use_skill($skill[Mild Curse]);[/COLOR]
        use_skill($skill[Storm of the Scarab]);
    }
}

... then Mafia casts Mild Curse, hits the Underworld, and fails with "You don't have a skill uniquely matching "1 Storm of the Scarab" (because it never gets back to line 2 of the script).

Even doing the check for Underworld text again won't work:

Code:
void main(int round, monster foe, string page) {
    if(contains_text(page, "Like a Bat Into Hell")) {
        visit_url("choice.php?pwd&whichchoice=443&option=2");
    }
    else {
        use_skill($skill[Mild Curse]);
[COLOR="#0000FF"]        if(contains_text(page, "Like a Bat Into Hell")) {
            visit_url("choice.php?pwd&whichchoice=443&option=2");
        }[/COLOR]
        use_skill($skill[Storm of the Scarab]);
    }
}

... because when the script hits the Underworld, the version of page that it has is the original version from the start of the round; that page text isn't updated during execution, so it doesn't contain the Underworld choice.

So this is back to being close-to-fully-broken. The workaround only functions in a subset of cases.
 

Theraze

Active member
Well, you'd need to do a check for round and have it check the page each hit. More like this:
Code:
void main(int round, monster foe, string page) {
    if(contains_text(page, "Like a Bat Into Hell")) {
        visit_url("choice.php?pwd&whichchoice=443&option=2");
    }
    else {
        if (round == 0) use_skill($skill[Mild Curse]);
        else use_skill($skill[Storm of the Scarab]);
    }
}
Of course, that only works if you get the jump. If you want to do mild curse for the first 2 rounds if you get the jump and only one if you fail init, change the round == 0 check to round < 2.
 
Well, you'd need to do a check for round and have it check the page each hit. More like this:
Code:
void main(int round, monster foe, string page) {
    if(contains_text(page, "Like a Bat Into Hell")) {
        visit_url("choice.php?pwd&whichchoice=443&option=2");
    }
    else {
        if (round == 0) use_skill($skill[Mild Curse]);
        else use_skill($skill[Storm of the Scarab]);
    }
}
Of course, that only works if you get the jump. If you want to do mild curse for the first 2 rounds if you get the jump and only one if you fail init, change the round == 0 check to round < 2.
My apologies; I picked an overly complicated way to demonstrate this issue. Using Mild Curse was just intended as an obvious "will probably get me killed" action. But what I'm actually looking to do is something more generic, like this:
Code:
void main(int round, monster foe, string page) {
    if(contains_text(page, "Like a Bat Into Hell")) {
        visit_url("choice.php?pwd&whichchoice=443&option=2");
    }
    [I]action1[/I];
    use_skill($skill[Storm of the Scarab]);
}
... Sometimes, action1 will kill the monster. Great. Other times, it won't do enough damage, and the monster will kill me. Then I end up aborting in the Underworld. (Because, as I outlined above, the script doesn't get a fresh copy of the page text between those steps, and it tries to use the skill even though it's sitting at the Underworld choice.) I don't think I can work around this by checking against round.

The only way to truly fix it is to have control handed back out of the script when a non-combat page is hit. I could also work around this if I knew how to pull a fresh copy of the current page HTML during execution (since the HTML passed as page is outdated at this point). If I had up-to-date page HTML, I could check for the choice adventure between combat steps. Is there a simple way to do that?
 
Last edited:
It occurred to me that maybe this kludge would work:
- see if the skill is used successfully
- if not, try a visit_url() to a random page, which will hopefully return the Like a Bat Into Hell HTML
- handle it from there

Code:
void main(int round, monster foe, string page) {
    if(!contains_text(page, "Like a Bat Into Hell")) {
        if(!use_skill($skill[Fist of the Mummy])) {
            print("edConsult.ash failed; attempting to get page text", "red");
            if(contains_text(visit_url("charsheet.php"))) visit_url("choice.php?pwd&whichchoice=443&option=2");
        }
    }
}

However, use_skill(skill) isn't currently returning a boolean... So this won't work, either. It just fails for a different reason.

Argh!
 
Last edited:

lostcalpolydude

Developer
Staff member
Since use_skill( skill ) returns a buffer, you don't have to "try a random visit_url()", since it should already have the response text that you want.
 
Well, boolean vs. buffer isn't exactly equivalent, since the buffer has the defeat text and I was checking for Underworld text. It took me a bit to figure that out. But I can just check for defeat text, instead. Thanks!

This seems to work:

Code:
void main(int round, monster foe, string page) {
    string pageText;
    repeat {
        pageText = use_skill(Fist of the Mummy);
    } until(contains_text(pageText, "You have been defeated, for now.") || contains_text(pageText, "You win the fight!"));
    if(contains_text(pageText, "You have been defeated, for now.")) {
        print("In the Underworld", "red");
        if(get_property("_edDefeats") < get_property("edDefeatAbort")) run_choice(2);
        else abort("Stuck in the Underworld.");
    }
}

That last check against "You win the fight!" is necessary, otherwise Mafia keeps trying to use the skill even though combat's over. There's probably a cleaner way to do it, but it's early and I'm too foggy to think it through.
 

Theraze

Active member
Well, the eventual cleaner way will be when mafia no longer believes you're in a combat when it changes over from a consult script, like with simple actions. :)

But hey, workarounds reduce wasted server hits. Even if there are probably thousands of 'bonus' random daily server hits from people using consult scripts in Ed that don't have this sort of hack in.
 

Darzil

Developer
Does the same issue occur with Haunted Bedroom ? I've never used a consult script, but that's another occasion where it goes straight into a non-combat.
 
Does the same issue occur with Haunted Bedroom ? I've never used a consult script, but that's another occasion where it goes straight into a non-combat.
Nope. Using a consult script, Mafia will run adventures in the Bedroom just fine, choosing the options I've set for the choice adventures, and flowing from a combat, through the noncombat, into the next combat, just fine. So this appears to be Ed-specific. (Or, at least, doesn't affect the Bedroom).
 

Theraze

Active member
The interesting thing about Ed and this failure is that it appears to be tied into not using the edDefeatAbort property properly. If I understand how that feature is supposed to work, when that is set to 2 (the default), mafia is supposed to return you to combat twice before it goes into the underworld automatically. With this consult bit, it just goes straight into the underworld without returning to combat twice and completely ignores that custom handling.
 
Top