Phase changes and passing priority are cryptic
Post MTG Forge Related Programming Questions Here
Moderators: timmermac, Agetian, friarsol, Blacksmith, KrazyTheFox, CCGHQ Admins
7 posts
• Page 1 of 1
Phase changes and passing priority are cryptic
by alexAG76 » 21 Jun 2011, 02:00
First, some questions:
Now I shall report some strangeness. This is from my game-state unit-tests, with my comments in dark red:
Game-state initialized.
Cards added to Human's library.
Human draws 5 cards.
Cards added to Computer's library.
Computer draws 3 cards.
Phase.handleBeginPhase() completed.
For Turn 1 (Human's) Upkeep Step, Human's possible moves are [passes priority].
Human passes priority.
For Turn 1 (Human's) Upkeep Step, Computer's possible moves are [passes priority].
So far, so good.
Computer passes priority.
For Turn 1 (Human's) Upkeep Step, Human's possible moves are [passes priority].
What? We should be in the Draw step now.
Human passes priority.
For Turn 1 (Human's) Draw Step, Computer's possible moves are [passes priority].
Computer passes priority.
For Turn 1 (Human's) Draw Step, Human's possible moves are [passes priority].
Human passes priority.
OK, both players passed priority, but the Human player should have had priority at the start of the Draw step.
For Turn 1 (Human's) Main1 Step, Computer's possible moves are [passes priority].
Computer passes priority.
For Turn 1 (Human's) Main1 Step, Human's possible moves are [plays land "Island", passes priority].
Human plays land "Island".
For Turn 1 (Human's) BeginCombat Step, Human's possible moves are [passes priority].
How did we get to BeginCombat from Main1 without both players passing? Granted, nobody had any other possible moves to make, so maybe this is an optimization. Am I right? It does not seem to be a case of auto-passing priority (e.g., from GUI settings).
I'm considering fixing this in the following manner:
*Otherwise, I'm sure to introduce bugs.
- Why does passing priority into the next phase not automatically call Phase.handleBeginPhase? It seems this is only called from InputControl.updateInput when Phase.doPhaseEffects returns true.
- Can someone explain why MagicStack.add calls Phase.passPriority when the simultaneousStackEntryList is non-empty?
Now I shall report some strangeness. This is from my game-state unit-tests, with my comments in dark red:
Game-state initialized.
Cards added to Human's library.
Human draws 5 cards.
Cards added to Computer's library.
Computer draws 3 cards.
Phase.handleBeginPhase() completed.
For Turn 1 (Human's) Upkeep Step, Human's possible moves are [passes priority].
Human passes priority.
For Turn 1 (Human's) Upkeep Step, Computer's possible moves are [passes priority].
So far, so good.
Computer passes priority.
For Turn 1 (Human's) Upkeep Step, Human's possible moves are [passes priority].
What? We should be in the Draw step now.
Human passes priority.
For Turn 1 (Human's) Draw Step, Computer's possible moves are [passes priority].
Computer passes priority.
For Turn 1 (Human's) Draw Step, Human's possible moves are [passes priority].
Human passes priority.
OK, both players passed priority, but the Human player should have had priority at the start of the Draw step.
For Turn 1 (Human's) Main1 Step, Computer's possible moves are [passes priority].
Computer passes priority.
For Turn 1 (Human's) Main1 Step, Human's possible moves are [plays land "Island", passes priority].
Human plays land "Island".
For Turn 1 (Human's) BeginCombat Step, Human's possible moves are [passes priority].
How did we get to BeginCombat from Main1 without both players passing? Granted, nobody had any other possible moves to make, so maybe this is an optimization. Am I right? It does not seem to be a case of auto-passing priority (e.g., from GUI settings).
I'm considering fixing this in the following manner:
- Augment Phase.passPriority so that it maintains a Set of the players who have passed when the stack was empty. Once all players have passed, it gives priority to the turn-owner and sets needToNextPhase.
- I'll try to retain the calls (which I do not comprehend*) to InputControl.resetInput, MagicStack.chooseOrderOfSimultaneousStackEntryAll, MagicStack.hasSimultaneousStackEntries, and MagicStack.resolveStack.
- Change MagicStack so that whenever something is pushed onto the MagicStack, it resets Phase's memory of what players have passed. (All players must pass priority for a phase to end.)
*Otherwise, I'm sure to introduce bugs.

Re: Phase changes and passing priority are cryptic
by Sloth » 21 Jun 2011, 11:07
Once again this part of the code has grown from something really simple (I can remember when the AI only played cards during his Main 1 and lot of phases and steps were missing completely) and went through a lot of changes/fixes. The AI not beeing able to respond to the human playing lands (and maybe even casting spells) in main 1 is a serious disadvantage.
You seem to know what you're doing, so please by all means submit your changes.
You seem to know what you're doing, so please by all means submit your changes.
-

Sloth - Programmer
- Posts: 3498
- Joined: 23 Jun 2009, 19:40
- Has thanked: 125 times
- Been thanked: 507 times
Re: Phase changes and passing priority are cryptic
by Chris H. » 21 Jun 2011, 11:52
Alex, you can send your google gmail address to Dennis Bergkamp via private message and he in turn can give you commit status to our SVN.
-

Chris H. - Forge Moderator
- Posts: 6320
- Joined: 04 Nov 2008, 12:11
- Location: Mac OS X Yosemite
- Has thanked: 644 times
- Been thanked: 643 times
Re: Phase changes and passing priority are cryptic
by Hellfish » 21 Jun 2011, 11:58
The SimultaneousStackEntry functions are for triggers going off simultaneously. chooseOrderof... presents a list of triggers to the human to order them onto the stack and lets the AI order it's triggers in APNAP order, if there are more than 1 triggers waiting,of course.
MagicStack.add passes priority if there are any Simultaneous trigger entries because I believe I added that as a bugfix to triggered abilities that look for spells cast not being added to the stack right away, but waiting until priority was passed otherwise, which was far too late. Phase.passPriority() calls the chooseOrderOf... method because that's ideally the only place where it should be called from, rules-compliance-wise.
EDIT: Also unrelated question because it will be bugging me otherwise: Is that not Gabriel from Constantine in your avatar?
MagicStack.add passes priority if there are any Simultaneous trigger entries because I believe I added that as a bugfix to triggered abilities that look for spells cast not being added to the stack right away, but waiting until priority was passed otherwise, which was far too late. Phase.passPriority() calls the chooseOrderOf... method because that's ideally the only place where it should be called from, rules-compliance-wise.
EDIT: Also unrelated question because it will be bugging me otherwise: Is that not Gabriel from Constantine in your avatar?
Last edited by Hellfish on 21 Jun 2011, 17:22, edited 1 time in total.
So now you're
Screaming for the blood of the cookie monster
Evil puppet demon of obesity
Time to change the tune of his fearful ballad
C is for "Lettuce," that's good enough for me
Screaming for the blood of the cookie monster
Evil puppet demon of obesity
Time to change the tune of his fearful ballad
C is for "Lettuce," that's good enough for me
-

Hellfish - Programmer
- Posts: 1297
- Joined: 07 Jun 2009, 10:41
- Location: South of the Pumphouse
- Has thanked: 110 times
- Been thanked: 169 times
Re: Phase changes and passing priority are cryptic
by friarsol » 21 Jun 2011, 12:29
Some quick answers: All of Forge is based around this cryptic Input system. I think it was based around the original IDE Rares was using to get Forge up and running relatively quickly. At this point it has left us with leftover code that we need to work around so not break the system.
PassingPriority doesn't call straight into BeginPhase because of how this Input system works. Since I'm the one who most recently updated the Stack system, I recall that trying to call the BeginPhase directly led to multiple BeginPhase events happening (drawing two cards, dealing double damage, things like that), which is why UpdateInput also checks to make sure it actually is the beginning of a phase before calling there.
While I'm not saying your Unit Test is wrong (it would be great to have a test suite) I haven't noticed any issues with Priority being passed in my months of testing/playing since the Phase code was most recently rewritten. It seems like your Priority wasn't set properly when your Test first started which caused lots of issues down the road. Are you sure your Game State is correct when your Test starts?
PassingPriority doesn't call straight into BeginPhase because of how this Input system works. Since I'm the one who most recently updated the Stack system, I recall that trying to call the BeginPhase directly led to multiple BeginPhase events happening (drawing two cards, dealing double damage, things like that), which is why UpdateInput also checks to make sure it actually is the beginning of a phase before calling there.
While I'm not saying your Unit Test is wrong (it would be great to have a test suite) I haven't noticed any issues with Priority being passed in my months of testing/playing since the Phase code was most recently rewritten. It seems like your Priority wasn't set properly when your Test first started which caused lots of issues down the road. Are you sure your Game State is correct when your Test starts?
passPriority already does exactly what you are suggesting you change it to. getPriorityPlayer() is determining which player has priority, and getFirstPriority() is determining who acted first in this segment of the Stack. If the current priority player is also the first player to act, Priority is given to the opponent. Otherwise, either the Stack Resolves or the Phase ends. Then updateInput() checks the game state and moves the game along.alexAG76 wrote:
- Augment Phase.passPriority so that it maintains a Set of the players who have passed when the stack was empty. Once all players have passed, it gives priority to the turn-owner and sets needToNextPhase.
- Change MagicStack so that whenever something is pushed onto the MagicStack, it resets Phase's memory of what players have passed. (All players must pass priority for a phase to end.)
- friarsol
- Global Moderator
- Posts: 7593
- Joined: 15 May 2010, 04:20
- Has thanked: 243 times
- Been thanked: 965 times
Re: Phase changes and passing priority are cryptic
by alexAG76 » 21 Jun 2011, 23:03
Thank you; that is exactly the information I needed.friarsol wrote:Some quick answers: All of Forge is based around this cryptic Input system. ... PassingPriority doesn't call straight into BeginPhase because of how this Input system works. Since I'm the one who most recently updated the Stack system, I recall that trying to call the BeginPhase directly led to multiple BeginPhase events happening (drawing two cards, dealing double damage, things like that), which is why UpdateInput also checks to make sure it actually is the beginning of a phase before calling there.
Thanks, but I am now pretty sure the unit-test is wrong.friarsol wrote:While I'm not saying your Unit Test is wrong (it would be great to have a test suite) I haven't noticed any issues with Priority being passed in my months of testing/playing since the Phase code was most recently rewritten.
No, because of the lack of interaction with InputControl and Input. I may have to trace through a regular initialization (of the GUI) to make sure I get it right.friarsol wrote:It seems like your Priority wasn't set properly when your Test first started which caused lots of issues down the road. Are you sure your Game State is correct when your Test starts?
OK; that was not obvious from reading the code. Thanks for the clarification.friarsol wrote:passPriority already does exactly what you are suggesting you change it to. getPriorityPlayer() is determining which player has priority, and getFirstPriority() is determining who acted first in this segment of the Stack. If the current priority player is also the first player to act, Priority is given to the opponent. Otherwise, either the Stack Resolves or the Phase ends. Then updateInput() checks the game state and moves the game along.alexAG76 wrote:
- Augment Phase.passPriority so that it maintains a Set of the players who have passed when the stack was empty. Once all players have passed, it gives priority to the turn-owner and sets needToNextPhase.
- Change MagicStack so that whenever something is pushed onto the MagicStack, it resets Phase's memory of what players have passed. (All players must pass priority for a phase to end.)
I'm glad I listened to the voice in my head that said, "You need more help."
Re: Phase changes and passing priority are cryptic
by Jaedayr » 22 Jun 2011, 00:02
You only have one voice in your head that says that to you?! ALL of them in mine say that.alexAG76 wrote:I'm glad I listened to the voice in my head that said, "You need more help."
7 posts
• Page 1 of 1
Who is online
Users browsing this forum: No registered users and 7 guests