Bug - Fixed Mafia automatically using custom combat macro

Veracity

Developer
Staff member
So every RelayAgent has an associated RelayAutoCombatThread.

This is used to automate the whole fight when the browser requests /fight.php?action=custom
This is used to automate the whole fight when the browser requests /fight.php?hotkey=11
This is used to execute a single combat action when the browser requests /fight.php?hotkey=XX where XX is not 11

"Automating the whole fight" means calling FightRequest.INSTANCE.run() in a RelayAutoCombatThread.
"Executing a single combat action" means calling FightRequest.INSTANCE.runOnce( this.desiredAction ) in a RelayAutoCombatThread.

Neither of those request is synchronized, so you could have multiple RelayAutoCombatThreads in there stepping on each other.
I don't see evidence of that in your log.

When we call FightRequest.run(), that is, by definition, automating the fight. Extracted from that method:

Code:
		FightRequest.isAutomatingFight = true;

		do
		{
			this.runOnce( null );
		}
		while ( this.responseCode == 200 && FightRequest.currentRound != 0 && !KoLmafia.refusesContinue() );

		if ( this.responseCode == 302 )
		{
			FightRequest.clearInstanceData();
		}

		FightRequest.isAutomatingFight = false;
I'd synchronize those methods and put the set/clear of the static class variable in try/finally, just to protect from real double clicks coming from the browser.

I'm still trying to figure out how FightRequest.run() got called for your second fight BEFORE you later pressed the "script" button.
 
Last edited:

heeheehee

Developer
Staff member
Another thing I pondered was whether it's possible to exit that block in comment #21, e.g. by GenericRequest throwing an exception. I don't think that's consistent with the log, though.
 

heeheehee

Developer
Staff member
I don't know enough about how Mafia relay browser works, but is it possible that the HTTP response for the completion of fight.php gets served to the browser before FightRequest.run() completes?
 

Veracity

Developer
Staff member
I did several changes which I cannot confirm will fix this, since I still cannot come up with a scenario that caused this.

- I made a new RelayAutoCombatThread for each RelayAgent, rather than sharing one without synchronization.
- I attempted to synchronize of FIghtRequest.INSTANCE whenever it is used.
- I moved the setting/clearing of FightRequest.isAutomating fights into a try/finally block

Since I do not understand what caused your "glitch", I cannot guarantee that this solves it, but, please try it out.

I did go into the Relay Browser, repeatedly, and click on the "script" button up to 5 times, and I always got back exactly the resonse I expected - the result of the first click - even though up to 5 threads wre responding to the click, as dispatched by requests from the browser.

Revision 19544.
 

Malibu Stacey

Active member
I did several changes which I cannot confirm will fix this, since I still cannot come up with a scenario that caused this.

- I made a new RelayAutoCombatThread for each RelayAgent, rather than sharing one without synchronization.
- I attempted to synchronize of FIghtRequest.INSTANCE whenever it is used.
- I moved the setting/clearing of FightRequest.isAutomating fights into a try/finally block

Since I do not understand what caused your "glitch", I cannot guarantee that this solves it, but, please try it out.

I did go into the Relay Browser, repeatedly, and click on the "script" button up to 5 times, and I always got back exactly the resonse I expected - the result of the first click - even though up to 5 threads wre responding to the click, as dispatched by requests from the browser.

Revision 19544.

Would this also fix multiple clicks of the "Begin" button in the Adventure tab causing it to run multiple adventures simultaneously?
 

fredg1

Member
Glitch doesn't seem to trigger (though maybe I am overestimating how easy it is to trigger it).

Worth noting that the fight result screen seemed to take a little bit longer to appear. Not sure if it is a result of the changes, but it could be that instead of the glitch being fixed, the conditions to get it were made harder to obtain. (For all I know, maybe 2 of the 3 changes fixed the glitch, while the 3rd just made the fight result appear slower/later, who knows)
 

Veracity

Developer
Staff member
I am noticing that my script which runs the LOV is getting "A choice follows this fight immediately." when trying to take the choice following the second fight.
Looking at the code, I cannot see how that is possible, given the ASH functions I am calling.
But, this is new and repeatable, so I guess I need to turn on DEBUG logging and see what's up.
 

Veracity

Developer
Staff member
Worth noting that the fight result screen seemed to take a little bit longer to appear.
Give me some metrics about exactly "how much" "a little bit longer" is, and I'll pay attention.

Hard to imagine that synchronizing on something which is not actually in contention would cause a noticible effect. Which is to say, I want something more concrete than "it seems to take longer".

FWIW, I also added DEBUG logging when various thread activation things happened.
 

ckb

Minion
Staff member
I am noticing that my script which runs the LOV is getting "A choice follows this fight immediately." when trying to take the choice following the second fight.
Looking at the code, I cannot see how that is possible, given the ASH functions I am calling.
But, this is new and repeatable, so I guess I need to turn on DEBUG logging and see what's up.

This is also happening to me, when I am running my LOV script. It used to not happen, and I am not sure it happens 100% of the time. I feel like it started maybe 7-10 days ago. I'll pour through my logs and check.
 

Veracity

Developer
Staff member
OK. Let try revision 19547. That gets rid of the RelayAutoCombatThread. We do other potentially multi-round things in the same thread that RelayRequest came in on (like automating chains of choice adventures), so why not? Worked just fine in my testing.

(Actually, we post the choice in a different thread, but we wait for it to run and pick up the response. Not sure why that is useful. The point of running stuff in distinct threads like that is to not make requests to KoL in the Swing event thread and blocking the UI, but that is not relevant to the Relay Browser.)
 

Malibu Stacey

Active member
This is causing fights in the relay browser to only show the final action if you use a consult script. It just sits at the first round then jumps to the final round once the fight is over. e.g

[174059] Your Witchess Set
Encounter: Play against the Witchess Pieces
Encounter: Witchess Bishop
Round 0: Malibu Stacey wins initiative!
Round 1: Malibu Stacey executes a macro!
Round 1: Malibu Stacey casts DIGITIZE! <- didn't see this round.
WHAM: Running SmartStasis
Round 2: Malibu Stacey executes a macro!
Round 2: Malibu Stacey casts SUMMON LOVE GNATS! <- or this
Round 3: CNV darts back and forth past your foe making weird blooping noises, confusing him.
Round 3: Malibu Stacey casts EXTRACT! <- or this
You acquire an item: Source essence
Round 4: Your opponent seems startled by the fact that you're accompanied by a creature that is a mouth and nothing else.
Round 4: Malibu Stacey casts SING ALONG! <- or this
Round 5: Your opponent seems puzzled by this weird yellow most-of-a-circle that's running around.
WHAM: Starting evaluation and performing of attack
WHAM: We are going to 1-shot with attack with your weapon.
Round 5: Malibu Stacey executes a macro!
Round 5: Malibu Stacey attacks!
Round 6: Witchess Bishop takes 22321 damage. <- only thing ever shown on screen.
Round 6: Malibu Stacey wins the fight!
After Battle: A love dragonfly buzzes softly in your ear.
After Battle: You gain 7 Roguishness
You gain 170 Meat
You acquire an item: Sacramento wine
You gain 30 Meat.
After Battle: CNV rubs against your leg, shedding a stray pixel.
You acquire an item: yellow pixel
After Battle: CNV tells you the classic Miss Funny joke about the bishop and the washer-woman. (+2 Moxie Stats)
After Battle: You gain 72 Strengthliness
After Battle: You gain 59 Wizardliness
After Battle: You gain 142 Sarcasm

19543 and earlier don't do this. Also none of the things which happen before the monster dies are listed in the "Found in this fight:" section either (e.g the Source Essence from above).

I don't do too much in the relay browser so it's easy enough to work around but there may be other people more affected and since I've been stuck in aftercore for a while I can imagine it could be much more of an issue to people in-run.

Code:
> version

KoLmafia v19.7 r19548
 
Last edited:

Veracity

Developer
Staff member
I'll try that out. Works fine for a CCS with no consult script:

Code:
[ barf mountain ]
try to steal an item
skill pocket crumbs
skill summon mayfly swarm
attack with weapon
Encounter:

Code:
[1843] Barf Mountain
Encounter: angry tourist
Round 0: Veracity wins initiative!
Round 1: Veracity executes a macro!
Round 1: Veracity tries to steal an item!
Round 2: Psychic Grrl says, I sense an unexpected windfall in your near future! and hands you some meat.
You gain 13 Meat.
Round 2: Veracity casts POCKET CRUMBS!
Round 3: angry tourist drops 14 attack power.
Round 3: angry tourist drops 12 defense.
Round 3: Psychic Grrl says, I sense an unexpected windfall in your near future! and hands you some meat.
You gain 14 Meat.
Round 3: Veracity casts SUMMON MAYFLY SWARM!
Round 4: You open the little container full of mayfly bait and swing it around. A tiny swarm of mayflies buzzes into the area.
Round 4: Psychic Grrl says, I sense an unexpected windfall in your near future! and hands you some meat.
You gain 5 Meat.
Round 4: Veracity attacks!
Round 5: angry tourist takes 1023 damage.
Round 5: Veracity wins the fight!
After Battle: You remember a party at KoL Con VI, when everybody got really excited about your super-Moxious Disco Bandit costume.
After Battle: You gain 8 Cheek
After Battle: The swarm of mayflies buzzes away. "I'll see you tomorr..." you begin, but finish your sentence with a single tear.
After Battle: You relax for a moment and watch meteors streak across the cosmos, and consider what it all means.
After Battle: You gain 6 Enchantedness
After Battle: Psychic Grrl surveys the scene from atop the throne and sighs.
After Battle: Hasemary dances around the corpse, shouting "Take that, mean ol' monster!" and then searches their pockets for candy. She's gonna be a damn fine adventurer one day.
After Battle: You gain 36 hit points
After Battle: You gain 65 Mojo Points
You gain 3771 Meat
After Battle: Cryptic Zelda peeks out of the shadows, checks for danger, and sidles up to you with some meat.
You gain 15 Meat.
You acquire an item: expensive camera
You acquire an item: How to Avoid Scams
You gain 65 Meat.
You acquire an item: normal barrel
After Battle: You gain 13 Strengthliness
After Battle: You gain 5 Enchantedness
After Battle: You gain 21 Chee
Every round was shown in the relay browser.

Found in this fight:

Code:
Found in this fight:

expensive camera	You acquire an item: expensive camera [acc1] [acc2] [acc3]
How to Avoid Scams	You acquire an item: How to Avoid Scams [use multiple]
normal barrel	You acquire an item: normal barrel [use] [smash party]
 

Veracity

Developer
Staff member
I got a "A choice follows this fight immediately" executing my LOV script again.

Here is the condensed DEBUG log:

Code:
class net.sourceforge.kolmafia.request.GenericRequest
Requesting: https://www.kingdomofloathing.com/place.php?whichplace=town_wrong
Retrieved: https://www.kingdomofloathing.com/place.php?whichplace=town_wrong
---
class net.sourceforge.kolmafia.request.GenericRequest
Requesting: https://www.kingdomofloathing.com/place.php?whichplace=town_wrong&action=townwrong_tunnel
Retrieved: https://www.kingdomofloathing.com/place.php?whichplace=town_wrong&action=townwrong_tunnel
Field: Location = [choice.php?forceoption=0]
---
class net.sourceforge.kolmafia.request.GenericRequest
Requesting: https://www.kingdomofloathing.com/choice.php?forceoption=0
Retrieved: https://www.kingdomofloathing.com/choice.php?forceoption=0
---
class net.sourceforge.kolmafia.session.ChoiceManager$1
Requesting: https://www.kingdomofloathing.com/choice.php?whichchoice=1222&option=1&pwd
Retrieved: https://www.kingdomofloathing.com/choice.php?whichchoice=1222&option=1&pwd
[1841] The Tunnel of L.O.V.E.
Encounter: L.O.V. Entrance
Submitting option 1 for choice 1223
---
class net.sourceforge.kolmafia.session.ChoiceManager$1
Requesting: https://www.kingdomofloathing.com/choice.php?whichchoice=1223&option=1&pwd
Retrieved: https://www.kingdomofloathing.com/choice.php?whichchoice=1223&option=1&pwd
Field: Location = [fight.php?ireallymeanit=1568779649]
---
class net.sourceforge.kolmafia.request.FightRequest
Requesting: https://www.kingdomofloathing.com/fight.php?ireallymeanit=1568779649
Retrieved: https://www.kingdomofloathing.com/fight.php?ireallymeanit=1568779649
Encounter: LOV Enforcer
Round 0: Veracity wins initiative!
---
class net.sourceforge.kolmafia.request.FightRequest
Round 1: Veracity executes a macro!
Requesting: https://www.kingdomofloathing.com/fight.php?action=macro&macrotext=%0Apickpocket%0A
Retrieved: https://www.kingdomofloathing.com/fight.php?action=macro&macrotext=%0Apickpocket%0A
...
Round 5: Veracity wins the fight!
This combat did not cost a turn
---
class net.sourceforge.kolmafia.request.GenericRequest
Requesting: https://www.kingdomofloathing.com/choice.php
Retrieved: https://www.kingdomofloathing.com/choice.php
[1841] The Tunnel of L.O.V.E.
Encounter: L.O.V. Equipment Room
You gain 550 hit points
You gain 884 Mojo Points
---
Submitting option 4 for choice 1224
class net.sourceforge.kolmafia.session.ChoiceManager$1
Requesting: https://www.kingdomofloathing.com/choice.php?whichchoice=1224&option=4&pwd
Retrieved: https://www.kingdomofloathing.com/choice.php?whichchoice=1224&option=4&pwd
[1841] The Tunnel of L.O.V.E.
Encounter: L.O.V. Engine Room
---
Submitting option 1 for choice 1225
class net.sourceforge.kolmafia.session.ChoiceManager$1
Retrieved: https://www.kingdomofloathing.com/choice.php?whichchoice=1225&option=1&pwd
Field: Location = [fight.php?ireallymeanit=1568779651]
---
class net.sourceforge.kolmafia.request.FightRequest
Requesting: https://www.kingdomofloathing.com/fight.php?ireallymeanit=1568779651
Retrieved: https://www.kingdomofloathing.com/fight.php?ireallymeanit=1568779651
Encounter: LOV Engineer
Round 0: Veracity wins initiative!
---
class net.sourceforge.kolmafia.request.FightRequest
Round 1: Veracity executes a macro!
Requesting: https://www.kingdomofloathing.com/fight.php?action=macro&macrotext=%0A%0A%0Amark+mafiafinal%0Aif+hasskill+28%0Askill+28%0Aendif%0Agoto+mafiafinal
Retrieved: https://www.kingdomofloathing.com/fight.php?action=macro&macrotext=%0A%0A%0Amark+mafiafinal%0Aif+hasskill+28%0Askill+28%0Aendif%0Agoto+mafiafinal
...
Round 5: Veracity wins the fight!
This combat did not cost a turn
---
class net.sourceforge.kolmafia.request.GenericRequest
Retrieved: https://www.kingdomofloathing.com/choice.php
Requesting: https://www.kingdomofloathing.com/choice.php
[1841] The Tunnel of L.O.V.E.
Encounter: L.O.V. Emergency Room
You gain 57 hit points
You gain 472 Mojo Points
---
Submitting option 3 for choice 1226
class net.sourceforge.kolmafia.session.ChoiceManager$1
Requesting: https://www.kingdomofloathing.com/choice.php?whichchoice=1226&option=3&pwd
Retrieved: https://www.kingdomofloathing.com/choice.php?whichchoice=1226&option=3&pwd
[1841] The Tunnel of L.O.V.E.
Encounter: L.O.V. Elbow Room
You acquire an effect: Wandering Eye Surgery (50)
Processing result: Wandering Eye Surgery (50)
---
Submitting option 1 for choice 1227
class net.sourceforge.kolmafia.session.ChoiceManager$1
Requesting: https://www.kingdomofloathing.com/choice.php?whichchoice=1227&option=1&pwd
Retrieved: https://www.kingdomofloathing.com/choice.php?whichchoice=1227&option=1&pwd
Field: Location = [fight.php?ireallymeanit=1568779653]

---
class net.sourceforge.kolmafia.request.FightRequest
Requesting: https://www.kingdomofloathing.com/fight.php?ireallymeanit=1568779653
Retrieved: https://www.kingdomofloathing.com/fight.php?ireallymeanit=1568779653
Encounter: LOV Equivocator
Round 0: Veracity wins initiative!
---
class net.sourceforge.kolmafia.request.FightRequest
Round 1: Veracity executes a macro!
Requesting: https://www.kingdomofloathing.com/fight.php?action=macro&macrotext=%0A%0A%0Apickpocket%0Amark+mafiafinal%0Aattack%0Agoto+mafiafinal
Retrieved: https://www.kingdomofloathing.com/fight.php?action=macro&macrotext=%0A%0A%0Apickpocket%0Amark+mafiafinal%0Aattack%0Agoto+mafiafinal
Round 1: Veracity tries to steal an item!
...
Round 5: Veracity wins the fight!
This combat did not cost a turn
A choice follows this fight immediately.
Here is the portion of my script where that last fight was selected and fought.

Code:
    // Fight or sneak around the LOV Equivocator
    if ( lov_enemies contains LOV_EQUIVOCATOR ) {
	run_choice( 1 );
	run_combat();
    } else {
	run_choice( 2 );
    }
    visit_url( "choice.php" );
In other words, I selected the choice option to fight the LOV Equivocator, did run_combat() to fight him, and then when it was time to visit_url( "choice.php" ) to select the choice to choose my reward, KoLmafia aborted with "A choice follows this fight immediately.".

Confusing.

Huh. I wonder if it was trying to restore HP/MP at the end of the fight but couldn't.
 

Veracity

Developer
Staff member
This is causing fights in the relay browser to only show the final action if you use a consult script.
Can I see the CCS section which invoked the consult script, please?
Looks like you had digitize, summon love gnats, extract, sing along and then called WHAM?
The first four would get composed into a macro, each round of which we would show on a single screen, since it was a mcro, and then we'd call the consult script, which would do its stuff.
How did it used to show? Did it show all the rounds from the macro and then all the rounds from Wham, all on one page?

Or did it used to refresh a time or two, showing the initial rounds, and then show the final round?
 
Last edited:

Veracity

Developer
Staff member
The way it used to be:

We'd fire off a thread to execute the fight.
We then tell the browser to redirect and refresh once a second. Using a non-standard Netscape HTTP extension, which is supported almost everywhere, in spite of not being in the HTTP spec.
Each time we get a refresh, we wait, 200 msec at a time time, looking for a new round to have finished.
We show the (decorated) result. Doing the decoration is what accumulates the "found in this fight" data.
Eventually, the fight is over, and we should the final (decorated) response, which includes all the items.

Which means, it worked by luck: if the thread executing the fight got more than one response between refreshes by your browser, only the most recent one would get decorated and accumulated into the results.

I don't think I'm going to reproduce the "this works by luck" aspect where it shows you some of the responses (all of them, if you are lucky and the timing works, as it might, almost always).

I can make it accumulate the "found in this fight" stuff, even if it is showing the final round, and thereby show you everything that was found earlier.
 

Veracity

Developer
Staff member
OK, I did that in revision 19549. It no longer depends on luck to accumulate multiple rounds worth of items; every time we parse a fight response, we create the decorated page which will build up the deferred list of found items, and when the fight is over, you will see all of the items.

I tested with a CCS with three actions and a call to WHAM.

I don't think I want WHAM; it sometimes one shotted with an attack and sometimes used a love song. I can always finish my fights in Barf Mountain with with an attack. :)
 
Top