[Solved] Waiting before triggering next state

Game development with Board Game Arena Studio
Post Reply
0BuRner
Posts: 12
Joined: 13 April 2020, 17:00

[Solved] Waiting before triggering next state

Post by 0BuRner »

Hello,

In the game I'm developing, at one point I need to wait few seconds (2/3) to see if any player still want to do some action, before triggering the next state.
I tried with "sleep()", but the issue is everything is synchronous so the wait prevent players to play before the method related to the state execute.

What I want is:
- state "playerTurn" trigger "endTurn" at the end
- before endTurn is called, wait X seconds and let players still do action (slap the pile)

Here is what I did (with sleep implemented in first line of endTurn):
1. BuRner0 played a card, call method playCard() in 'playerTurn' state that triggers 'endTurn' state at its end
2. BuRner1 slapped the pile (during sleep)
3. BuRner0 slapped the pile (during sleep)

Here is what I get:
Image

Here is what I want (same order as the pic):
3. BuRner0 plays 2 ♦
2. BuRner1 slapped the pile
1. BuRner0 slapped the pile
Last edited by 0BuRner on 23 April 2020, 19:14, edited 1 time in total.
User avatar
DoctorPelusa
Posts: 36
Joined: 16 March 2020, 12:32

Re: Waiting before triggering next state

Post by DoctorPelusa »

Can't you use a timer to call the function that advances the game state? I'm still pretty new with php and the studio but it's what I usually use on qt: https://www.php.net/manual/es/event.addtimer.php
0BuRner
Posts: 12
Joined: 13 April 2020, 17:00

Re: Waiting before triggering next state

Post by 0BuRner »

DoctorPelusa wrote: 21 April 2020, 21:37 Can't you use a timer to call the function that advances the game state? I'm still pretty new with php and the studio but it's what I usually use on qt: https://www.php.net/manual/es/event.addtimer.php
Yes it is something like that I need but this one need PECL "event" extension and it seems to be not activated on the server... I don't really know how to activate it, if possible.
User avatar
DoctorPelusa
Posts: 36
Joined: 16 March 2020, 12:32

Re: Waiting before triggering next state

Post by DoctorPelusa »

0BuRner wrote: 21 April 2020, 21:52
DoctorPelusa wrote: 21 April 2020, 21:37 Can't you use a timer to call the function that advances the game state? I'm still pretty new with php and the studio but it's what I usually use on qt: https://www.php.net/manual/es/event.addtimer.php
Yes it is something like that I need but this one need PECL "event" extension and it seems to be not activated on the server... I don't really know how to activate it, if possible.
If it's not provided you could try to implement it yourself with time() function, (I've also done that for c++ projects without qt) but it takes a bit more work and it's less flexible, as you usually make a very simple implementation using a memory variable...

The way I usually do it is to save a variable with myvar=time()+delay, and in the next iterations check if time()>myvar; (I'm guessing you don't need much accuracy, you can try with microtime() and would probably work much better, but you'll still have some imprecision from the delay between calls)
0BuRner
Posts: 12
Joined: 13 April 2020, 17:00

Re: Waiting before triggering next state

Post by 0BuRner »

DoctorPelusa wrote: 21 April 2020, 22:23
0BuRner wrote: 21 April 2020, 21:52
DoctorPelusa wrote: 21 April 2020, 21:37 Can't you use a timer to call the function that advances the game state? I'm still pretty new with php and the studio but it's what I usually use on qt: https://www.php.net/manual/es/event.addtimer.php
Yes it is something like that I need but this one need PECL "event" extension and it seems to be not activated on the server... I don't really know how to activate it, if possible.
If it's not provided you could try to implement it yourself with time() function, (I've also done that for c++ projects without qt) but it takes a bit more work and it's less flexible, as you usually make a very simple implementation using a memory variable...

The way I usually do it is to save a variable with myvar=time()+delay, and in the next iterations check if time()>myvar; (I'm guessing you don't need much accuracy, you can try with microtime() and would probably work much better, but you'll still have some imprecision from the delay between calls)
Thanks but my issue here is not related to the delay but related to multithreading (or another way to do what I want)... Otherwise, as I sayed earlier, the "sleep()" function would have been enough.
clavat
Posts: 9
Joined: 05 April 2020, 17:49

Re: Waiting before triggering next state

Post by clavat »

Hello,

I agree with the solution of DoctorPelusa.
In your states.inc file you could use the parameter "action" http://en.doc.boardgamearena.com/Your_g ... php#action.

In my opinion you can implement in both server and client side :
Server side, at the end of the precedent action, remember in database the "end time", and in this "action" function you can check the delay and don't go to the next state until your delay was gone.
Client side, you can implement easily sleep function, or callback, to wait until trigger new ajax request to perform the next action.
http://en.doc.boardgamearena.com/Game_i ... ifications

Indeed, you cant force the server to sleep or wait for you, if you do that, you block 1 thread for you and other games will "lag", and it will cause performance issue.
User avatar
fafa-fr
Posts: 383
Joined: 22 December 2013, 21:58

Re: Waiting before triggering next state

Post by fafa-fr »

Hi,
This is what I did on a game I was working on (paused at the moment because I'm working on another game, but I WILL continue). I'd be happy to have your opinions about this.

Since it was not possible (or desirable, don't know exactly) to use a timer server-side, in game.php I record in DB (BGA global variable) the starting time with time(), and I send a notification to clients, that each start a timer with setTimeout(). When the timer triggers, the clients each send an ajaxcall (I'll call them "timeFinished") to the server.

The first time (only the first time, see below) the server receives a timeFinished ajaxcall, it checks if the elapsed time is correct, then it removes timer start time from DB and triggers what must be done when the timer is finished.

How do I check that a timeFinished ajaxcall is the first, so that the triggered method is executed only once? I don't know if it's the best way, but I use checkAction() (with $bThrowException=false so that it doesn't throw an exception), because I believe (but I'm not sure, so I'll ask something about this at the end of this post) that the server response to the first call will be entirely executed (changes to DB commited, gamestate changed) before the second ajaxcall execution starts. So when the second and subsequent ajaxcalls are executed, the gamestate has already changed and the timeFinished action is not allowed anymore, so checkAction() returns false, and I stop the action's execution. I still have to send a silent notification to the clients, otherwise they'll wait for an answer, considering that an action is still in progress.

Note: if you're not in a multiplayer gamestate, you must use checkPossibleAction() instead of checkAction(), see BGA doc, Main game logic page. Of course in both cases you must allow "timeFinished" actions for this state in your states.inc.php file.

Second note: I think that this can be dangerous, because if for some reason (bug, connection problem, ...) the clients do not send the timeFinished call, the game hangs forever. In my game, if a player reloads their page during the timer state, getAllDatas() sends the remaining time (0 if negative), and in JS' setup the timeFinished call is launched if needed. So at least a F5 can solve the problem.

I wanted to ask here someday about the "possibility of concurrent action execution" stuff, so here I go. Are we absolutely sure that for a given game table, even in a multiplayer gamestate, a chain of actions following a client request is always entirely executed until its end (including gamestate changes) before another action execution starts? This would seem logical to me, but I'd like to be sure, because the BGA Framework may not have originally been designed with the possibility of simultaneous actions depending of each other in mind.
User avatar
apollo1001
Posts: 191
Joined: 21 July 2015, 10:41

Re: Waiting before triggering next state

Post by apollo1001 »

I would highly recommend you don’t use setTimout() as it causes potential issues (particularly with the game replay feature which will not wait for timeouts before parsing the notifications to get to the correct move).

Is the wait period defined in the rules? If so you could have a makemove action which sets a global variable to track the move time and a second action endTurn which the user has to trigger which checks lapsed time before moving on a state (this can throw an error if not enough time has passed). This would get around the possibility of a game hanging forever and avoids the use of timeouts which could cause other bugs.

The alternative is to move on to the next state anyway which has the slap action available and again, refuses to take a normal move action until the time has elapsed. This would be my preferred option as it doesn’t require a second confirmation from the original player and avoids unnecessary timeouts.
User avatar
fafa-fr
Posts: 383
Joined: 22 December 2013, 21:58

Re: Waiting before triggering next state

Post by fafa-fr »

I forgot to say that I don't start the timer in replay mode (if ( typeof g_replayFrom != "undefined" ) ). But it wouldn't surprise me if there were other issues I didn't think about. The last suggestion from apollo1001 may be the best one for you, 0BuRner. It won't be for my game, so if anyone has advice or knows of specific issues with setTimeout, I'm interested. (Some day I'll open a new thread about this, when I get back to this game.)
0BuRner
Posts: 12
Joined: 13 April 2020, 17:00

Re: Waiting before triggering next state

Post by 0BuRner »

Hi ,

Thank you all for the help.
Before I saw your answers I went with "setTimeout" client-side and I don't like it neither, I wasn't sure about the issue it could caused but now with apollo1001's answer it's obvious it will cause issue some times.
The alternative is to move on to the next state anyway which has the slap action available and again, refuses to take a normal move action until the time has elapsed. This would be my preferred option as it doesn’t require a second confirmation from the original player and avoids unnecessary timeouts.
The issue with this method is there are only 2 states in my game "playerTurn" and "endTurn". The "endTurn" state is the "play validator" that will process every actions done during "playerTurn" (in fact all players can do actions - play or slap - during this state). I don't really see how to use this method with my game as it is exactly my issue: delay between playerTurn end and endTurn.
Is the wait period defined in the rules? If so you could have a makemove action which sets a global variable to track the move time and a second action endTurn which the user has to trigger which checks lapsed time before moving on a state (this can throw an error if not enough time has passed). This would get around the possibility of a game hanging forever and avoids the use of timeouts which could cause other bugs.
There is no wait period defined, because in the real game there is often a little wait by every player to think if there is some action to do or not, and if nobody react the next player plays his card.
However, I can set a default wait value (which what I did in setTimeout) and add a button for the player to "validate" the turn and trigger "endTurn" instead of setTimeout. What I dislike is it will not reflect the real game and the game experience may be altered. But it seems it's the only viable option...
Post Reply

Return to “Developers”