Page 1 of 1
gamedatas and undo in in-game replay
Posted: 10 July 2020, 22:50
by paramesis
Since my project involves a fixed number of tokens that can be in several potential locations, I decided early on to update this.gamedatas to reflect the current and previous location of every object so that all of the animation can be centrally coordinated by a single function whenever a notification moves things around.
This has been great for keeping the project organized, but where it has become an issue is in the in-game replay whenever a user undoes their turn. At that point, the interface is reloaded and reflects the final location of all of the objects based on the current gamestate. Then, historic notifications try to run against that state, which either moves tokens back to previous locations or produces errors from functions trying to reference objects that don't exist any more. I haven't seen this occur with post-game replays.
All my undo function does is call $this->undoRestorePoint() on the server side and this.restoreServerGameState() on the client side. This hasn't caused a problem anywhere else. Is there something I can do to make sure that this.gamedatas reflects the correct historic state of the board in this situation?
Edit: important detail about what my undo function was doing on the PHP side.
Re: gamedatas and undo in in-game replay
Posted: 11 July 2020, 17:15
by paramesis
I have an apparent solution to this problem, but please do let me know if there are any errors in my observation or conclusions. It would appear that
creates a notification log item that resets the user interface. For this reason, it is unnecessary to call restoreServerGameState on the client side. The interface reset also overwrites this.gamedatas. In an instant replay, this.gamedatas is overwritten with the end-of-replay game state, causing the conflicts I described. I would argue this is a bug in the BGA framework.
I don't think there was necessarily anything wrong with updating this.gamedatas the way I was, however I should clone to a new object, such as this.gamedatas_local and make my changes and references to that clone. I have added the following lines at the beginning of my setup function.
Code: Select all
if ( typeof g_replayFrom == "undefined" || typeof this.gamedatas_local == "undefined" ) {
this.gamedatas_local = dojo.clone(this.gamedatas);
}
This is the only reference to this.gamedatas in the entire interface logic. Everything else, including setup, uses this.gamedatas_local, which is always initialized in setup, unless it already exists
and we are in an instant replay. The game state reflected from the first gamedatas at the beginning of the replay is preserved until the end of the replay and everything now behaves as expected.
Re: gamedatas and undo in in-game replay
Posted: 11 July 2020, 22:34
by docthib
Hello,
Not sure if you read the doc:
http://en.doc.boardgamearena.com/BGA_Undo_policy
It is mentioned
The undoRestorePoint method:
- restores the game database
- removes all your game HTML + the player panels
- restores the game HTML + the player panels according to their state at the initial game loading calls your "setup" method
Important: because undoRestorePoint is calling your "setup" method, you must ensure that your whole game state can be restored from there. In particular, all your member variables must be initialized inside the "setup" method (and not only in the constructor !)
I'm using framework undo for a project and have no problem with it. Code looks like this (not sure it will help but well):
Code: Select all
setup: function(gamedatas)
{
(...) // blabla lot of code before this
// once undo is complete, remove this flag
document.body.classList.remove('undo-ing');
$btnUndo = document.getElementById('undo_button');
$btnUndo.classList.add('active');
this.addTooltipHtml($btnUndo.id, 'Undo all your actions for the current turn');
if (this.connexions['undo_button'] == undefined) {
this.connexions['undo_button'] = dojo.connect($btnUndo, 'onclick', this, 'onClickUndoButton' );
}
}
onClickUndoButton: function(event)
{
console.log('onClickUndoButton', event);
dojo.stopEvent(event);
var self = this;
var $btn = event.target;
// check if user can undo
if ($btn.classList.contains('disabled')
|| ! this.checkAction('undo')
|| document.body.classList.contains('undo-ing')
) {
return;
}
// warn user
if (this.tempArgs.confirm == false) {
this.confirmationDialog( _('You are going to cancel <b>ALL YOUR ACTIONS</b> until last save point (begin of turn / last draw), are you <b>SURE</b>?'), dojo.hitch( this, function() {
self.tempArgs.confirm = true;
self.onClickUndoButton(event);
} ) );
return;
}
// disconnect everything
for (var key in this.connexions) {
console.log(key);
dojo.disconnect(this.connexions[key]);
delete this.connexions[key];
};
document.body.classList.add('undo-ing');
this.ajaxcall("/awesomegame/awesomegame/undo.html", {lock: true }, function(ok) {}, function(nok) {});
},
Re: gamedatas and undo in in-game replay
Posted: 12 July 2020, 00:40
by paramesis
Does in-game replay work as expected over a player's turn in which they use a framework undo? The undo itself has been working perfectly fine everywhere else throughout the project. Thanks for the doc link - I had seen it before, but didn't remember the specifics at the bottom. The undoRestorePoint description is consistent with my understanding.
The bug I'm seeing is with in-game replay specifically, and it can show up in every game with framework undo. I can confirm that it occurs in La Granja:
Edit again: removed link, as replay no longer demonstrates issue. It can happen in any game if you click "replay from this point" at some point before any player cancels their move.
Once that undo occurs, the current game state is loaded, and for remainder of the replay, the notifications are moving bits back to previous locations in a way that doesn't accurately reflect what had previously occurred.
Re: gamedatas and undo in in-game replay
Posted: 14 July 2020, 15:07
by hersh
interesting. i notice the same thing in marco polo, replay crashes due to undo.
https://boardgamearena.com/2/marcopolo? ... ayFrom=204
looks like something that has to be fixed in bga platform. i put a break-point in setup() to inspect gamedatas state. i notice after undo notification gamedatas state passed is the current state instead of move N state. for marco polo that causes some pieces/objects to not exist when notif is sent and js errors.
in post-game replays when a player undoes the setup() function isn't called again, but for in-flight games it is. not sure why the behaviour is different.
curious - how does bga replay work internally? does it keep a snapshot of gamedatas for each move? I notice that gamedatas is different depending where I start replay from for in-flight games.