Page 1 of 1

multiplayer: isCurrentPlayerActive() and checkAction()

Posted: 10 October 2019, 00:28
by RicardoRix
Inside .JS, For a multiplayer action. I am noticing some strange behaviour with 'active' player functions.
I am trying to implement some 'user changes their mind' functionality.

1.
within: onEnteringState: function( stateName, args )

the this.isCurrentPlayerActive() is not set to true during normal game flow.
If the page is refreshed via F5, then this.isCurrentPlayerActive() does come back as true, and all works ok.

2.
Also, the this.checkAction('action_name') works fine when the player is active, but if the player is not active then this returns false.
The wiki doc suggests that this checks the game state, and doesn't say anything about the player being active or not. I can't find anything specific for checking the game state for JS.

Re: multiplayer: isCurrentPlayerActive() and checkAction()

Posted: 11 October 2019, 16:41
by fafa-fr
Hi,
RicardoRix wrote: 10 October 2019, 00:28 I can't find anything specific for checking the game state for JS.
Maybe this.gamedatas.gamestate.name is what you're looking for?

Re: multiplayer: isCurrentPlayerActive() and checkAction()

Posted: 11 October 2019, 20:26
by RicardoRix
fafa-fr wrote: 11 October 2019, 16:41 Maybe this.gamedatas.gamestate.name is what you're looking for?
Yes, thanks!

Turns out as well the this.gamedatas.gamestate.multiactive is empty during the onEnteringState event.
There is also a multiactive array as part of the 'args' to the event, again it is empty.
Hit F5 - refresh and both arrays are now full of all the player ids'

I've come up with the following work-arounds for multiplayer states.

Code: Select all

checkActionMulti: function(state)
		{
			return (this.checkActionMulti(state, false));
		},
		
		checkActionMulti: function(state, noMessage)
		{
			var isState = (this.gamedatas.gamestate.name == state);
			
			if ((!noMessage) && (!isState))
				this.checkAction(state);
			
			return isState;
		},
		
		isCurrentMultiPlayerActive: function()
		{
			//return (this.gamedatas.gamestate.multiactive.length == 0) || (this.isCurrentPlayerActive.gamestate.multiactive.includes(String(this.player_id)));
			
			return ((this.gamedatas.gamestate.multiactive.length == 0) || this.isCurrentPlayerActive());
		},		

Re: multiplayer: isCurrentPlayerActive() and checkAction()

Posted: 12 October 2019, 00:23
by Victoria_La
Check this thread about multiactive and onEnteringState
viewtopic.php?f=12&t=12193

checkAction would return false only for activate player because if player is not activate action is not allowed, only activate players can do actions

Re: multiplayer: isCurrentPlayerActive() and checkAction()

Posted: 12 October 2019, 13:31
by RicardoRix
1.
On entering the state, both players should be active.

Code: Select all

        onEnteringState: function( stateName, args )
        {

			//debugger;
			if (args.multiactive != null)
				this.log( 'Entering state: '+ stateName + ':' + args.multiactive.length + ':' + this.isCurrentPlayerActive() + ':' + this.gamedatas.gamestate.multiactive.length );	
When entering the state via normal game flow.
Entering state: playCards:0:false:0

Without doing anything, Pressing F5 / page refresh:
Entering state: playCards:2:true:2

2.
If the 'checkAction()' is reliant on a player being active, then there should be a checkState() or at-least some alternative which is not player active dependent. fafa-fr has suggested this.gamedatas.gamestate.name which works well.

I think it's quite common in multiplayer mode actions, that users may like to change their mind. The only way to stop the clock is to make the player inactive. What is the preferred way to deal with a player's actions in this player inactive condition?

Re: multiplayer: isCurrentPlayerActive() and checkAction()

Posted: 18 October 2019, 10:31
by sourisdudesert
On client side, you can use the following:

Code: Select all

            if( ! this.checkPossibleActions( 'chooseCard' ) )
            {   return; }
It does the same than "checkAction", but it does not test if current player is active. Thus, you can check that you are on the right game state, but it does not take active player into account.


In addition, on server side, you can use the following:

Code: Select all

        $bChangeMind = false;
        if( self::checkAction( 'chooseCard', false ) )
        {
        }
        else
        {
            $this->gamestate->checkPossibleAction( 'chooseCard' ) ;       
            $bChangeMind = true;
        }
It works exactly the same way than on JS side, plus it allows you to determine if this is a "changing my mind" action or a normal "first action".

Re: multiplayer: isCurrentPlayerActive() and checkAction()

Posted: 18 October 2019, 10:58
by RicardoRix
sourisdudesert wrote: 18 October 2019, 10:31 On client side, you can use the following:

Code: Select all

            if( ! this.checkPossibleActions( 'chooseCard' ) )
            {   return; }
That's great!

checkPossibleActions() is not documented on the wiki:
http://en.doc.boardgamearena.com/Game_i ... amename.js


Do you have any information about the difference with the multiactive, in onEnteringState my point 1.

Code: Select all

onEnteringState: function( stateName, args )
        {

			//debugger;
			if (args.multiactive != null)
				this.log( 'Entering state: '+ stateName + ':' + args.multiactive.length + ':' + this.isCurrentPlayerActive() + ':' + this.gamedatas.gamestate.multiactive.length );	
When entering the state via normal game flow.
Entering state: playCards:0:false:0

Without doing anything, Pressing F5 / page refresh:
Entering state: playCards:2:true:2

Re: multiplayer: isCurrentPlayerActive() and checkAction()

Posted: 18 October 2019, 11:26
by sourisdudesert
RicardoRix wrote: 18 October 2019, 10:58 Do you have any information about the difference with the multiactive, in onEnteringState my point 1
During a multiplayer state, players activity is managed dynamically by you DURING the state. In general, you active all the player in the "stYourFunction" method associated to the state.

This is why when "entering" into a state, the players are not active yet. When you do a F5 afterwards the situation has evolved and of course your players are active.

TL;DR: isCurrentPlayerActive is not reliable during onEnteringState for multipleplayers state. You must use onUpdateActionButtons, which is called for each player activation/unactivation during a multiplayer state.

Re: multiplayer: isCurrentPlayerActive() and checkAction()

Posted: 18 October 2019, 11:47
by RicardoRix
I'm not sure why this should work differently for a multiplayer state than an single turn-by-turn state. Maybe they are both the same?

The state machine normally goes, play state followed by a transitional resolve state

So currently I do set everyone active in the play state:

Code: Select all

function stPlayCards()
	{		
		$this->gamestate->setAllPlayersMultiactive();        
	}
but are you saying it is necessary or possible to do this on a previous state ?

Is that a bug?

or just use onUpdateActionButtons for everything multiplayer and single player states, and ignore onEnteringState.

Is there a picture /timing diagram for the state machine?

Re: multiplayer: isCurrentPlayerActive() and checkAction()

Posted: 18 October 2019, 11:59
by sourisdudesert
This is not a bug. activePlayer is mean to be simple, and multipleActivePlayer is mean to give you a lot of flexibility. So the way they are working are slightly different.

In a classic "activePlayer" state:

  • You cannot change the active player DURING the state
  • This is to ensure that during 1 activePlayer state, only ONE player is active
  • As a consequence, you must set the active player BEFORE entering the activePlayer state
  • Finally, during onEnteringState, on JS side, the active player is signaled as active and the information is reliable and usable.

In a "multiplePlayer" state:

  • You can (and must) change the active players DURING the state
  • During such a state, players can be activated/desactivated anytime during the state, giving you the maximum of possibilities.
  • You shouldn't set actives player before entering the state. I'm not sure this is allowed or not but you shouldn't do this.
  • Finally, during onEnteringState, on JS side, the active players are NOT actives yet so you must use onUpdateActionButtons to perform the client side operation which depends on a player active/unactive status.