Page 1 of 1

checkAction problem

Posted: 26 October 2020, 20:26
by RavingWanderer
I am working on a card game where each player's turn begins with a Buy phase. This is a multiactive state, where most
of the players get to make a bid for purchasing the last discard, at the cost/benefit of drawing an extra card. When
all of the players have decided, a game state is invoked in which the Winning Player is determined. In this state,
the game logic gives the discard and draws the extra card for the Winning Player. It also remembers the choice of Turn Player,
since s/he is required to make his choice if it wasn't buying the discard, and transitions into the "player draw" state.
There, the cached action of the Turn Player is retrieved (in this case a card draw) and executed. The "draw card" logic
for both players goes through the same routine, with a flag indicating whether it is a buy or regular draw. This flag
(among other things) gates a call to checkAction to verify that the play is legal, and a call that transitions out of
the draw state. (Before anyone asks: this action caching mechanism is necessary because the state machine is going
to get more complicated in the future, so the draw should not happen at the same time as the buy.)

When I run a play sequence in which Turn Player chooses to draw in the buy phase, and Winning Player chooses to buy the discard,
I get the error "It is not your turn" when the last player makes their decision. The log indicates something is wrong:

Code: Select all

Enter Process buy results state:   26/10 16:35:24 [info] [T207751] [2325995/RWDev3] New game state: 'buyResults'
Player whose turn it is:           26/10 16:35:24 [info] [T207751] [2325995/RWDev3] stProcessBuyResults: 2325993
Player who won the buy draws:      26/10 16:35:24 [info] [T207751] [2325995/RWDev3] DrawCard: player=2325995 nCards=1 advance=bool(false)
 [above call is made in stProcessBuyResults]
 [intervening db traffic processing draw omitted]
Transition out of buyResults:      26/10 16:35:24 [info] [T207751] [2325995/RWDev3] nextState with action: 'noShanghai'
 [above transition occurs at the end of stProcessBuyResults]
Transition into playerDraw:        26/10 16:35:24 [info] [T207751] [2325995/RWDev3] New game state: 'playerDraw'
Player whose turn it is:           26/10 16:35:24 [info] [T207751] [2325995/RWDev3] stPlayerDraw: Active Player 2325993
Turn player's forced draw:         26/10 16:35:24 [info] [T207751] [2325995/RWDev3] DrawCard: player=2325993 activePlayer=2325993 nCards=1 advance=bool(true)
 [above call is made in stPlayerDraw]
???                                26/10 16:35:24 [info] [T207751] [2325995/RWDev3] This is not turn of player 2325995 (this is turn of player 2325993)
26/10 16:35:24 [info] [T207751] [2325995/RWDev3] DB rollback: action cancelled
26/10 16:35:24 [notice] [T207751] [2325995/RWDev3] Exception: It is not your turn
The ??? line appears to be generated by checkAction, called from drawCard, indicating it thinks that 2325995 (the buy phase
Winning Player) is trying to make this draw action, even though in my code it clearly isn't (getActivePlayerId
returns ...3 as shown in the previous log entries, and is the player id passed in). When I remove the checkAction call, everything works correctly.

Is something wrong with checkAction?

Re: checkAction problem

Posted: 26 October 2020, 23:12
by RavingWanderer
It appears that checkAction is using the current player, rather than the active one, even though the game is now in an active state. The server-side execution thread started in a multiactive state, but ended in an active state.

26/10 22:59:40 [info] [T202271] [2325993/RWDev1] Before checkAction: action=drawCard state=playerDraw current=2325993 active=2325994 turn=23259942
26/10 22:59:40 [info] [T202271] [2325993/RWDev1] This is not turn of player 2325993 (this is turn of player 2325994)2

If I end the multiactive state by playing the "turn player" last, the checkAction succeeds. If I end it with any other player, it fails.

Re: checkAction problem

Posted: 26 October 2020, 23:15
by Tisaac
I had this issue several times, only workaround I found was to give second optional parameter of checkAction to false.

Re: checkAction problem

Posted: 27 October 2020, 12:00
by Archduke
  • current player is the player who made the request
  • active player is the player whose turn it is
checkAction should always check the current player, not the active player. It will always be the active player's turn, so there is no point checking it.
Because the transitions in your example are all automatic, the processing is all happening from the original player's request, which is why current player is not as you wish.

You shouldn't call checkAction in stGameState functions, but you must call it in every action triggered by an actual user's request. I understand you are automatically doing actions for the user, so I suppose you're using the same function - I'd therefore suggest just adding an optional parameter to indicate whether the function was called via an stGameState function or via action.inc.php.

I may not have understand, but if I have, I hope that helps!

Re: checkAction problem

Posted: 27 October 2020, 14:23
by RavingWanderer
Archduke wrote: 27 October 2020, 12:00
  • current player is the player who made the request
  • active player is the player whose turn it is
checkAction should always check the current player, not the active player. It will always be the active player's turn, so there is no point checking it.
Because the transitions in your example are all automatic, the processing is all happening from the original player's request, which is why current player is not as you wish.

You shouldn't call checkAction in stGameState functions, but you must call it in every action triggered by an actual user's request. I understand you are automatically doing actions for the user, so I suppose you're using the same function - I'd therefore suggest just adding an optional parameter to indicate whether the function was called via an stGameState function or via action.inc.php.

I may not have understand, but if I have, I hope that helps!
Thank you, this explains the behavior (and the rationale for it as well). It should be documented in the wiki which player is being checked.

Re: checkAction problem

Posted: 27 October 2020, 17:08
by Tisaac
Archduke wrote: 27 October 2020, 12:00
  • current player is the player who made the request
  • active player is the player whose turn it is
checkAction should always check the current player, not the active player. It will always be the active player's turn, so there is no point checking it.
Because the transitions in your example are all automatic, the processing is all happening from the original player's request, which is why current player is not as you wish.

You shouldn't call checkAction in stGameState functions, but you must call it in every action triggered by an actual user's request. I understand you are automatically doing actions for the user, so I suppose you're using the same function - I'd therefore suggest just adding an optional parameter to indicate whether the function was called via an stGameState function or via action.inc.php.

I may not have understand, but if I have, I hope that helps!
Sorry my answer wasn't precise enough but this is precisely what I did in my project, your suggestion is definitively the way to go !