<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
	<id>https://en.doc.boardgamearena.com/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Sguzzer+Gunayer</id>
	<title>Board Game Arena - User contributions [en]</title>
	<link rel="self" type="application/atom+xml" href="https://en.doc.boardgamearena.com/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Sguzzer+Gunayer"/>
	<link rel="alternate" type="text/html" href="https://en.doc.boardgamearena.com/Special:Contributions/Sguzzer_Gunayer"/>
	<updated>2026-10-07T08:23:42Z</updated>
	<subtitle>User contributions</subtitle>
	<generator>MediaWiki 1.39.0</generator>
	<entry>
		<id>https://en.doc.boardgamearena.com/index.php?title=Table&amp;diff=22832</id>
		<title>Table</title>
		<link rel="alternate" type="text/html" href="https://en.doc.boardgamearena.com/index.php?title=Table&amp;diff=22832"/>
		<updated>2024-10-02T09:54:40Z</updated>

		<summary type="html">&lt;p&gt;Sguzzer Gunayer: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This is reference for public and protected method defined in Table and its ancestors, this information obtained by using php reflection.&lt;br /&gt;
&lt;br /&gt;
Most of these methods are documented on various other wikis, this is just reference for completeness and in case you run into accidental overloading of undocumented functions...&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;Its a long list please help with editing this wiki&amp;lt;/span&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If you need these method for IDE autocompletion and validation there is unofficial project that has stubs to documented methods: &lt;br /&gt;
* https://github.com/elaskavaia/bga-sharedcode/blob/master/misc/module/table/table.game.php (if you want more stubs pull requests are welcome to this repository)&lt;br /&gt;
&lt;br /&gt;
== Class hierarchy ==&lt;br /&gt;
&lt;br /&gt;
* APP_Object&lt;br /&gt;
** APP_DbObject&lt;br /&gt;
***  APP_GameClass&lt;br /&gt;
****    Table - this is a class all games inherit&lt;br /&gt;
****    [[Deck]] - db handling component for specific schema (deck)&lt;br /&gt;
&lt;br /&gt;
== Methods in the Table class ==&lt;br /&gt;
;Table.getGameName&lt;br /&gt;
:part of template, return game name, not to be modified by developer, not document on wiki&lt;br /&gt;
;Table._&lt;br /&gt;
:translation wrapper function, see [[Translations]]&lt;br /&gt;
;Table.setTable&lt;br /&gt;
:method that sets up the php side, do not call or override&lt;br /&gt;
;Table.initTable protected&lt;br /&gt;
:This method is called by framework before every action (does nothing by default), unlike constructor this method has initialized state of the table so it can access db, undocumented as it has very limited use&lt;br /&gt;
;Table.getAllTableDatas&lt;br /&gt;
:undocumented&lt;br /&gt;
;Table.getAllDatas&lt;br /&gt;
:part of template, override, see [[Main game logic: yourgamename.game.php]]&lt;br /&gt;
;Table.setupNewGameTable&lt;br /&gt;
:undocumented&lt;br /&gt;
;Table.setupNewGame&lt;br /&gt;
:part of template, override, see [[Main game logic: yourgamename.game.php]]&lt;br /&gt;
;Table.getTableOptionsForGame static&lt;br /&gt;
:undocumented&lt;br /&gt;
;Table.getTableOptions&lt;br /&gt;
:undocumented, likely return gameoptions (i.e. variants of the games)&lt;br /&gt;
;Table.getTablePreferencesForGame static&lt;br /&gt;
:undocumented&lt;br /&gt;
;Table.getTablePreferences&lt;br /&gt;
:undocumented, likely return UI preferences (i.e. display tooltips or not) &lt;br /&gt;
;Table.getGameInfosForGame static&lt;br /&gt;
:undocuments, likely return $gameinfos from gameinfos.inc.php&lt;br /&gt;
;Table.getGameOptionsInfos&lt;br /&gt;
:undocumented&lt;br /&gt;
;Table.start&lt;br /&gt;
:undocumented, likely starts the game, do not call&lt;br /&gt;
;Table.stMakeEveryoneActive&lt;br /&gt;
:this method can be used in state machine to make everybody active as &amp;quot;st&amp;quot; method of multiplayeractive state&lt;br /&gt;
&lt;br /&gt;
;Table.loadPlayersBasicInfos&lt;br /&gt;
:very usefull function get players table, see [[Main game logic: yourgamename.game.php]]&lt;br /&gt;
;Table.reloadPlayersBasicInfos&lt;br /&gt;
:reload players info, see [[Main game logic: yourgamename.game.php]]&lt;br /&gt;
;Table.reattributeColorsBasedOnPreferences&lt;br /&gt;
:change players colors, see [[Main game logic: yourgamename.game.php]]&lt;br /&gt;
;Table.getBestColorFromColorPrefs&lt;br /&gt;
:undocumented, do not call, use to pick a color based on preference&lt;br /&gt;
;Table.initSetupPlayersInfos&lt;br /&gt;
:undocumented&lt;br /&gt;
;Table.getPlayersNumber&lt;br /&gt;
:returns number of players, see [[Main game logic: yourgamename.game.php]]&lt;br /&gt;
;Table.checkAction&lt;br /&gt;
:check action on server, see [[Main game logic: yourgamename.game.php]]&lt;br /&gt;
;Table.checkGameStart&lt;br /&gt;
;Table.color_to_color_back&lt;br /&gt;
:@deprecated, undocumented&lt;br /&gt;
;Table.initGameStateLabels&lt;br /&gt;
;Table.setGameStateInitialValue&lt;br /&gt;
:Set initial state of global, technically same as setGameStateValue see [[Main_game_logic:_yourgamename.game.php#Use_globals]]&lt;br /&gt;
;Table.getGameStateValue&lt;br /&gt;
:get value of global see [[Main_game_logic:_yourgamename.game.php#Use_globals]]&lt;br /&gt;
;Table.setGameStateValue&lt;br /&gt;
:set value of global see [[Main_game_logic:_yourgamename.game.php#Use_globals]]&lt;br /&gt;
;Table.incGameStateValue&lt;br /&gt;
:increment value of global see [[Main_game_logic:_yourgamename.game.php#Use_globals]]&lt;br /&gt;
;Table.is_testmode&lt;br /&gt;
:@deprecated&lt;br /&gt;
;Table.testmodedatas&lt;br /&gt;
:@deprecated&lt;br /&gt;
;Table.applyTestModeDbFixture&lt;br /&gt;
;Table.getActivePlayerId&lt;br /&gt;
:get active player id, see [[Main_game_logic:_yourgamename.game.php#Game_states_and_active_players]]&lt;br /&gt;
;Table.getActivePlayerName&lt;br /&gt;
:get active player name, see [[Main_game_logic:_yourgamename.game.php#Game_states_and_active_players]]&lt;br /&gt;
;Table.getCurrentPlayerId&lt;br /&gt;
:get current player id, see [[Main_game_logic:_yourgamename.game.php#Game_states_and_active_players]]&lt;br /&gt;
;Table.getCurrentPlayerName&lt;br /&gt;
:get currrent player name, see [[Main_game_logic:_yourgamename.game.php#Game_states_and_active_players]]&lt;br /&gt;
;Table.getCurrentPlayerColor&lt;br /&gt;
:get current player color, see [[Main_game_logic:_yourgamename.game.php#Game_states_and_active_players]]&lt;br /&gt;
;Table.getPlayerNameById&lt;br /&gt;
:get the name by id, see [[Main_game_logic:_yourgamename.game.php#Accessing_player_information]]&lt;br /&gt;
;Table.getPlayerColorById&lt;br /&gt;
:get the color by id, see [[Main_game_logic:_yourgamename.game.php#Accessing_player_information]]&lt;br /&gt;
;Table.getPlayerNoById&lt;br /&gt;
:get &#039;player_no&#039; (number) by id, see [[Main_game_logic:_yourgamename.game.php#Accessing_player_information]]&lt;br /&gt;
;Table.isCurrentPlayerZombie&lt;br /&gt;
;Table.getPlayerCount&lt;br /&gt;
:@deprecated, use getPlayersNumber, &lt;br /&gt;
;Table.createNextPlayerTable&lt;br /&gt;
:Return linked table of player order using passed parameter, see [[Main_game_logic:_yourgamename.game.php#Players turn order]]&lt;br /&gt;
;Table.getNextPlayerTable&lt;br /&gt;
:Return linked table of player order using natural players order, see [[Main_game_logic:_yourgamename.game.php#Players turn order]]&lt;br /&gt;
;Table.createPrevPlayerTable&lt;br /&gt;
:do not use&lt;br /&gt;
;Table.getPrevPlayerTable&lt;br /&gt;
:Return linked table of player order using natural players order reversed, see [[Main_game_logic:_yourgamename.game.php#Players turn order]]&lt;br /&gt;
;Table.getPlayerAfter&lt;br /&gt;
:get player after, see [[Main_game_logic:_yourgamename.game.php#Players turn order]]&lt;br /&gt;
;Table.getPlayerBefore&lt;br /&gt;
:get player before, see [[Main_game_logic:_yourgamename.game.php#Players turn order]]&lt;br /&gt;
;Table.activeNextPlayer&lt;br /&gt;
:Make the next player active in the natural player orde, see [[Main_game_logic:_yourgamename.game.php#Game states and active players]]&lt;br /&gt;
;Table.activePrevPlayer&lt;br /&gt;
:Make the prev player active in the natural player orde, see [[Main_game_logic:_yourgamename.game.php#Game states and active players]]&lt;br /&gt;
;Table.forceEndOfGame&lt;br /&gt;
:force to abandon game, normally its called when all players agree, but can be called to force people out when testing alpha or beta games and don&#039;t want to deal with update db and such (&amp;lt;code&amp;gt;$this-&amp;gt;forceEndOfGame( $reason )&amp;lt;/code&amp;gt;)&lt;br /&gt;
;Table.giveExtraTime&lt;br /&gt;
:give extra time to a player, usually when turn require multiple player states, see [[Main_game_logic:_yourgamename.game.php#Reflexion_time]]&lt;br /&gt;
;Table.checkZombieTurn&lt;br /&gt;
;Table.skipPlayersOutOfTime&lt;br /&gt;
:this is called by framework, do not use&lt;br /&gt;
;Table.onPlayerHasBeenZombified&lt;br /&gt;
:called when some player has been zombified because he quits the game (or have been &amp;quot;skipped&amp;quot;), unlikely you need to override this method, if you do you have to take into account first player quit vs any other player quit, you must call super implementation in any case if you decide to override it&lt;br /&gt;
;Table.forceAbandon&lt;br /&gt;
:it may be possible for force to abandon game in some cases, for example in alpha games when new database schema requires update and you did not code this (because for alpha its waste of time)&lt;br /&gt;
;Table.zombieBack&lt;br /&gt;
;Table.aiPlayer&lt;br /&gt;
;Table.aiNotPlaying&lt;br /&gt;
;Table.aiError&lt;br /&gt;
;Table.say&lt;br /&gt;
:this function processes chat message, do not use for game purposes, for word games use dedicated control&lt;br /&gt;
;Table.getGameProgression&lt;br /&gt;
:part of template, override to return proper data, see [[Main_game_logic:_yourgamename.game.php]] and [[Your_game_state_machine:_states.inc.php]]&lt;br /&gt;
;Table.getStatTypesForGame static&lt;br /&gt;
;Table.getStatTypes &lt;br /&gt;
:get the $stats_type array defined in stats.inc.php&lt;br /&gt;
;Table.stat_type_id_to_name&lt;br /&gt;
;Table.initStat&lt;br /&gt;
:initialize statistic https://en.doc.boardgamearena.com/Main_game_logic:_yourgamename.game.php#Game_statistics&lt;br /&gt;
;Table.getStat&lt;br /&gt;
:get statistic https://en.doc.boardgamearena.com/Main_game_logic:_yourgamename.game.php#Game_statistics&lt;br /&gt;
;Table.setStat&lt;br /&gt;
:set statistic https://en.doc.boardgamearena.com/Main_game_logic:_yourgamename.game.php#Game_statistics&lt;br /&gt;
;Table.setStatForAllPlayers&lt;br /&gt;
:set player statistics for all players, not document, does not check params, have some bad side effects&lt;br /&gt;
;Table.incStat&lt;br /&gt;
:inc statistic https://en.doc.boardgamearena.com/Main_game_logic:_yourgamename.game.php#Game_statistics&lt;br /&gt;
;Table.getStatFromResult&lt;br /&gt;
:helper function, do not use, should have been private for table class&lt;br /&gt;
;Table.setStatOnResult&lt;br /&gt;
:helper function, do not use, should have been private for table class&lt;br /&gt;
;Table.setStatOnResultForPlayer&lt;br /&gt;
:helper function, do not use, should have been private for table class&lt;br /&gt;
;Table.getStandardGameResultObject&lt;br /&gt;
:helper function, do not use, should have been private for table class&lt;br /&gt;
;Table.getGameRankInfos&lt;br /&gt;
;Table.argGameEnd&lt;br /&gt;
:framework end game function, do not call or override&lt;br /&gt;
;Table.stGameEnd&lt;br /&gt;
:framework end game function, do not call or override&lt;br /&gt;
;Table.stTutorialStart&lt;br /&gt;
;Table.isSoloGame&lt;br /&gt;
:return true if game is 1 player game or all other players are AI&lt;br /&gt;
;Table.notifyAllPlayers&lt;br /&gt;
:notification function, see https://en.doc.boardgamearena.com/Main_game_logic:_yourgamename.game.php&lt;br /&gt;
;Table.notifyPlayer&lt;br /&gt;
:notification function, see https://en.doc.boardgamearena.com/Main_game_logic:_yourgamename.game.php&lt;br /&gt;
;Table.onEndAjaxAction&lt;br /&gt;
:can be overriden to be executed before end of ajax action, unclear why would anybody need that&lt;br /&gt;
;Table.checkReturnState&lt;br /&gt;
:framework internal check action, do not call or override&lt;br /&gt;
;Table.sendNotifications&lt;br /&gt;
:framework internal function, do not call or override&lt;br /&gt;
;Table.getCurrentNotificationNextNo&lt;br /&gt;
;Table.getNotificationHistory&lt;br /&gt;
;Table.debugChat&lt;br /&gt;
:studio only - execute php code from chat, overriding won&#039;t work as it is called statically from table class&lt;br /&gt;
;Table.timeout&lt;br /&gt;
:studio only - can call from chat console to zombify current player&lt;br /&gt;
;Table.eliminatePlayer&lt;br /&gt;
:eliminate player, https://en.doc.boardgamearena.com/Main_game_logic:_yourgamename.game.php&lt;br /&gt;
;Table.isAsync&lt;br /&gt;
:return true if game is turn based, false if realtime, undocumented (why?)&lt;br /&gt;
;Table.getTimeLimits static&lt;br /&gt;
:internal framework function, do not call or override&lt;br /&gt;
;Table.getAsyncTimeLimits&lt;br /&gt;
:return time limits for turn based games&lt;br /&gt;
;Table.checkAsyncActivePlayersChange&lt;br /&gt;
:framework internal check action, do not call or override&lt;br /&gt;
;Table.upgradeTableDb&lt;br /&gt;
:override to perform db upgrade, see game template, also some notes in https://en.doc.boardgamearena.com/Post-release_phase&lt;br /&gt;
;Table.getReplayPoints&lt;br /&gt;
;Table.saveReplayPoint&lt;br /&gt;
;Table.undoAndReplayInit&lt;br /&gt;
;Table.removeAutoIncrementFromTable&lt;br /&gt;
:@deprecated&lt;br /&gt;
;Table.getFieldsListOfTable&lt;br /&gt;
:do not use or override, framework internal method to return columns of table&lt;br /&gt;
;Table.undoInit&lt;br /&gt;
;Table.undoSavepoint&lt;br /&gt;
:Instruction to save database state after current transaction is complete [[Main game logic: yourgamename.game.php#Undo moves]]&lt;br /&gt;
;Table.doUndoSavePoint&lt;br /&gt;
:do not call directly&lt;br /&gt;
;Table.undoRestorePoint&lt;br /&gt;
:Restore database from save point [[Main game logic: yourgamename.game.php#Undo moves]]&lt;br /&gt;
;Table.showTutorial&lt;br /&gt;
:do not call directly&lt;br /&gt;
;Table.seenTutorial&lt;br /&gt;
:do not call directly&lt;br /&gt;
;Table.activeTutorial&lt;br /&gt;
:do not call directly&lt;br /&gt;
;Table.forceGameTournamendEnd&lt;br /&gt;
:do not call directly&lt;br /&gt;
;Table.showCursor&lt;br /&gt;
;Table.showCursorClick&lt;br /&gt;
:undocumented, probably to share the cursor for demo/training &lt;br /&gt;
;Table.storeLegacyData&lt;br /&gt;
:API for campain games see [[Main game logic: yourgamename.game.php#Legacy games API]]&lt;br /&gt;
;Table.storeLegacyTeamData&lt;br /&gt;
:API for campain games see [[Main game logic: yourgamename.game.php#Legacy games API]]&lt;br /&gt;
;Table.retrieveLegacyData&lt;br /&gt;
:API for campain games see [[Main game logic: yourgamename.game.php#Legacy games API]]&lt;br /&gt;
;Table.retrieveLegacyTeamData&lt;br /&gt;
:API for campain games see [[Main game logic: yourgamename.game.php#Legacy games API]]&lt;br /&gt;
;Table.removeLegacyData&lt;br /&gt;
:API for campain games see [[Main game logic: yourgamename.game.php#Legacy games API]]&lt;br /&gt;
;Table.removeLegacyTeamData&lt;br /&gt;
:API for campain games see [[Main game logic: yourgamename.game.php#Legacy games API]]&lt;br /&gt;
&lt;br /&gt;
== Methods in the APP_GameClass class ==&lt;br /&gt;
;APP_GameClass.getNewUnique&lt;br /&gt;
;APP_GameClass.getNew&lt;br /&gt;
;APP_GameClass.notifyNow&lt;br /&gt;
&lt;br /&gt;
== Methods in the APP_DbObject class ==&lt;br /&gt;
&lt;br /&gt;
;APP_DbObject.ConnectDb static&lt;br /&gt;
;APP_DbObject.DbQuery static&lt;br /&gt;
:main query method, see https://en.doc.boardgamearena.com/Main_game_logic:_yourgamename.game.php#Accessing_the_database&lt;br /&gt;
;APP_DbObject.DbTraceTimeBefore static&lt;br /&gt;
;APP_DbObject.DbTraceTimeAfter static&lt;br /&gt;
;APP_DbObject.DbGetLastId static&lt;br /&gt;
;APP_DbObject.DbDumpQueryHistory static&lt;br /&gt;
;APP_DbObject.DbAffectedRow static&lt;br /&gt;
;APP_DbObject.DbStartTransaction static&lt;br /&gt;
;APP_DbObject.DbCommit static&lt;br /&gt;
;APP_DbObject.DbRollback static&lt;br /&gt;
;APP_DbObject.DbRestartTransaction static&lt;br /&gt;
;APP_DbObject.DbSelect static&lt;br /&gt;
;APP_DbObject.CommitAllAndRestart static&lt;br /&gt;
;APP_DbObject.setDeadlockMode&lt;br /&gt;
;APP_DbObject.isDeadlockModeRetry&lt;br /&gt;
;APP_DbObject.enableMultiQueries&lt;br /&gt;
;APP_DbObject.sendMultiQueries&lt;br /&gt;
;APP_DbObject.escapeStringForDB&lt;br /&gt;
;APP_DbObject.getCollectionFromDB&lt;br /&gt;
:see https://en.doc.boardgamearena.com/Main_game_logic:_yourgamename.game.php#Accessing_the_database&lt;br /&gt;
;APP_DbObject.getNonEmptyCollectionFromDB&lt;br /&gt;
;APP_DbObject.getDoubleKeyCollectionFromDB&lt;br /&gt;
:see https://en.doc.boardgamearena.com/Main_game_logic:_yourgamename.game.php#Accessing_the_database&lt;br /&gt;
;APP_DbObject.getUniqueValueFromDB&lt;br /&gt;
;APP_DbObject.mysql_fetch_row&lt;br /&gt;
;APP_DbObject.mysql_fetch_assoc&lt;br /&gt;
;APP_DbObject.mysql_query&lt;br /&gt;
;APP_DbObject.getObjectFromDB&lt;br /&gt;
:see https://en.doc.boardgamearena.com/Main_game_logic:_yourgamename.game.php#Accessing_the_database&lt;br /&gt;
;APP_DbObject.getNonEmptyObjectFromDB&lt;br /&gt;
:see https://en.doc.boardgamearena.com/Main_game_logic:_yourgamename.game.php#Accessing_the_database&lt;br /&gt;
;APP_DbObject.getObjectListFromDB&lt;br /&gt;
:see https://en.doc.boardgamearena.com/Main_game_logic:_yourgamename.game.php#Accessing_the_database&lt;br /&gt;
;APP_DbObject.getSelectedDb static&lt;br /&gt;
;APP_DbObject.sqlParsing&lt;br /&gt;
;APP_DbObject.DbUsePrefix&lt;br /&gt;
;APP_DbObject.applyPrefix&lt;br /&gt;
;APP_DbObject.cache_store static&lt;br /&gt;
;APP_DbObject.cache_add static&lt;br /&gt;
;APP_DbObject.cache_exists static&lt;br /&gt;
;APP_DbObject.cache_fetch static&lt;br /&gt;
;APP_DbObject.cache_delete static&lt;br /&gt;
;APP_DbObject.cache_rollback static&lt;br /&gt;
;APP_DbObject.cache_commit static&lt;br /&gt;
;APP_DbObject.ensure_enough_time_since_last_action&lt;br /&gt;
;APP_DbObject.getMasterNodeDomain&lt;br /&gt;
;APP_DbObject.getMasterNodeUrl&lt;br /&gt;
;APP_DbObject.masterNodeRequest&lt;br /&gt;
;APP_DbObject.gameserverNodeRequest&lt;br /&gt;
;APP_DbObject.gameserverNodeRequestNoTable&lt;br /&gt;
;APP_DbObject.bgaCallUrl&lt;br /&gt;
&lt;br /&gt;
== Methods in the APP_Object class ==&lt;br /&gt;
;APP_Object.watch&lt;br /&gt;
:@deprecated, do not use (noop)&lt;br /&gt;
;APP_Object.debug&lt;br /&gt;
:see https://en.doc.boardgamearena.com/Practical_debugging&lt;br /&gt;
;APP_Object.trace&lt;br /&gt;
:see https://en.doc.boardgamearena.com/Practical_debugging&lt;br /&gt;
;APP_Object.warn&lt;br /&gt;
:see https://en.doc.boardgamearena.com/Practical_debugging&lt;br /&gt;
;APP_Object.error&lt;br /&gt;
:see https://en.doc.boardgamearena.com/Practical_debugging&lt;br /&gt;
;APP_Object.dump&lt;br /&gt;
:see https://en.doc.boardgamearena.com/Practical_debugging&lt;br /&gt;
== Selected static methods in utility modules ==&lt;br /&gt;
;bga_rand&lt;br /&gt;
:recommended for randomness (dice rolls, etc), see [[Main game logic: yourgamename.game.php#About random and randomness]]&lt;br /&gt;
;shuffle_with_keys&lt;br /&gt;
:shuffle array with keys (basically shuffle keys and keep linked values), it shuffle argument, does not return anything&lt;br /&gt;
;totranslate&lt;br /&gt;
:returns its argument, used for MARKING of string for server strings https://en.doc.boardgamearena.com/Translations&lt;br /&gt;
;clienttranslate&lt;br /&gt;
:returns its argument, used for MARKING of string for client strings https://en.doc.boardgamearena.com/Translations&lt;br /&gt;
;_&lt;br /&gt;
:this is not the same as self::_, it is also translation function but only can translate mainsite strings, do not use in game code&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Category:Studio]]&lt;/div&gt;</summary>
		<author><name>Sguzzer Gunayer</name></author>
	</entry>
	<entry>
		<id>https://en.doc.boardgamearena.com/index.php?title=Tutorial_reversi&amp;diff=22811</id>
		<title>Tutorial reversi</title>
		<link rel="alternate" type="text/html" href="https://en.doc.boardgamearena.com/index.php?title=Tutorial_reversi&amp;diff=22811"/>
		<updated>2024-09-29T09:04:48Z</updated>

		<summary type="html">&lt;p&gt;Sguzzer Gunayer: /* The rules */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&#039;&#039;&#039;Check out an updated version&#039;&#039;&#039; of the [[BGA Type Safe Template: Reversi|Reversi Tutorial]] which uses the [[BGA Type Safe Template]]. {{Studio_Framework_Navigation}}&lt;br /&gt;
&lt;br /&gt;
== Introduction ==&lt;br /&gt;
&lt;br /&gt;
Using this tutorial, you can build a complete working game on the BGA environment: Reversi.&lt;br /&gt;
&lt;br /&gt;
Before you read this tutorial, you must:&lt;br /&gt;
* Read the overall presentations of the BGA Framework ([[Studio|see here]]).&lt;br /&gt;
* Know the [http://en.wikipedia.org/wiki/Reversi#Rules rules of Reversi].&lt;br /&gt;
* Know the languages used on BGA: PHP, SQL, HTML, CSS, Javascript&lt;br /&gt;
* &#039;&#039;&#039;Setup your development environment&#039;&#039;&#039; [http://en.doc.boardgamearena.com/First_steps_with_BGA_Studio First Steps with BGA Studio]&lt;br /&gt;
&lt;br /&gt;
== Create your first game ==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Note: you should already have created a project following instructions in [[First_steps_with_BGA_Studio#Create_a_new_game_project|Create a new game project]]. While you will find a &#039;&#039;&#039;reversi&#039;&#039;&#039; directory in your SFTP folder, do not use it for this tutorial. Instead, use the project you have created as an (empty) starting point.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
With the initial skeleton of code provided in your project, you can already start a game from the BGA Studio:&lt;br /&gt;
* Go to your [https://studio.boardgamearena.com/controlpanel studio Control panel], then Manage games and select your initial project. &#039;&#039;Note: there are warnings displayed about a missing BGG_ID and presentation text. You can ignore that for now.&#039;&#039;&lt;br /&gt;
* Click the Play link next to your project name. This will open the Play page and offer to create a new table for your project. &#039;&#039;Optional: click the Heart icon to add your project to your favorite games list.&#039;&#039;&lt;br /&gt;
* On the Play page, on the top of the page, make sure that your settings are &amp;quot;Simple game&amp;quot;, &amp;quot;Real time&amp;quot; and &amp;quot;Manual&amp;quot;.&lt;br /&gt;
* Click &amp;quot;Create table&amp;quot; to create a table of your project. &lt;br /&gt;
* For now, we are going to work with one player only, so use the (-) button to set the number of players to 1. Most of the time it is simpler to proceed with only one player during the early phase of development of your game, as it&#039;s easy and fast to start/stop games. If you choose to start with 2 players, you should see two names on the right: testdude0 and testdude1. To switch between them, press the red arrow button near their names; it will open another tab. This way you don&#039;t need to login and logout from multiple accounts.) &lt;br /&gt;
* Reminder: Always use the &amp;quot;Express Start&amp;quot; button to start the game.&lt;br /&gt;
&lt;br /&gt;
Thus, you can start a &amp;quot;Reversi&amp;quot; game, and arrive on a void, empty game. Yeah.&lt;br /&gt;
&lt;br /&gt;
End the game by clicking on the game options icon on the top right, and then on &amp;quot;Express Stop&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
== Editing the game information (Optional) ==&lt;br /&gt;
&lt;br /&gt;
This step is optional and will fix the warnings on the project page (missing BGG_ID and presentation).&lt;br /&gt;
&lt;br /&gt;
==== Edits to fix Errors ====&lt;br /&gt;
* Edit your local copy of the &amp;lt;code&amp;gt;gameinfos.inc.php&amp;lt;/code&amp;gt; file:&lt;br /&gt;
** Change the &amp;lt;code&amp;gt;bgg_id&amp;lt;/code&amp;gt; value from &amp;lt;code&amp;gt;0&amp;lt;/code&amp;gt; to &amp;lt;code&amp;gt;2389&amp;lt;/code&amp;gt; - that&#039;s around line 37.&lt;br /&gt;
** Add &amp;lt;code&amp;gt;1,&amp;lt;/code&amp;gt; to the players array - that&#039;s around line 41.&lt;br /&gt;
** Change the presentation array content - that&#039;s around line 134. Uncomment one line and change the text. Remove the final comma if you keep only one line!&lt;br /&gt;
* Upload the &amp;lt;code&amp;gt;gameinfos.inc.php&amp;lt;/code&amp;gt; file to the SFTP server (see [[First_steps_with_BGA_Studio#Connect_to_your_SFTP_folder|Connect to your SFTP folder]]).&lt;br /&gt;
&lt;br /&gt;
==== Test your Edits ====&lt;br /&gt;
* Go back to your project page, and in the &amp;quot;Game Information&amp;quot; section, click &amp;quot;Reload game informations&amp;quot;.&lt;br /&gt;
* Finally, refresh the project page in your browser (usually CTRL-F5).&lt;br /&gt;
&lt;br /&gt;
===== Not working? =====&lt;br /&gt;
Some changes will require bypassing the cache. It is often worth doing a hard refresh to make sure the&lt;br /&gt;
&lt;br /&gt;
Sometimes the cache will keep your changes from showing. Since this is a possibility, it will be useful to know how to bypass the cache. To do so you may manually clear cache or use a shortcut to refresh and ignore the cached version of the page. Here&#039;s how&lt;br /&gt;
&lt;br /&gt;
====== Windows ======&lt;br /&gt;
Chrome, Firefox, or Edge: Press &amp;lt;code&amp;gt;Ctrl+F5&amp;lt;/code&amp;gt; or &amp;lt;code&amp;gt;Shift+F5&amp;lt;/code&amp;gt; or &amp;lt;code&amp;gt;Ctrl+Shift+R&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====== Mac ======&lt;br /&gt;
Chrome or Firefox: Press &amp;lt;code&amp;gt;Shift+Command+R&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Safari for Mac: Press &amp;lt;code&amp;gt;Command+Option+E&amp;lt;/code&amp;gt; to empty the cache, then hold down Shift and click Reload in the toolbar&lt;br /&gt;
&lt;br /&gt;
== Make it look like Reversi ==&lt;br /&gt;
&lt;br /&gt;
Let&#039;s start with the board. This will give you a good idea of how things will look and where tokens should go.&lt;br /&gt;
&lt;br /&gt;
Be careful designing the layout of your game: you must always keep in mind that players with a 1024px screen width must be able to play. Usually, it means that the width of the play area can be 750px (in the worst case).&lt;br /&gt;
&lt;br /&gt;
For Reversi, it&#039;s useless to have a 750x750px board - much too big, so we chose this one which fit perfectly (536x528):&lt;br /&gt;
&lt;br /&gt;
[[File:Board.jpg]]&lt;br /&gt;
&lt;br /&gt;
Note that we are using a jpg file. Jpg files are lighter than png, so they are faster to load. Later, we are going to use PNGs for tokens because they allow for transparency.&lt;br /&gt;
&lt;br /&gt;
==== Add the board ====&lt;br /&gt;
use lowercase file names&lt;br /&gt;
* upload &amp;lt;code&amp;gt;board.jpg&amp;lt;/code&amp;gt; in your &amp;lt;code&amp;gt;img/&amp;lt;/code&amp;gt; directory. &lt;br /&gt;
* edit &amp;lt;code&amp;gt;reversi_reversi.tpl&amp;lt;/code&amp;gt; to add a &amp;lt;code&amp;gt;div&amp;lt;/code&amp;gt; for your board.&lt;br /&gt;
&lt;br /&gt;
Note: If you are building this game by following the tutorial, you will have a different project name than &amp;lt;code&amp;gt;reversi&amp;lt;/code&amp;gt; (i.e. &amp;lt;code&amp;gt;mygame_mygame.tpl&amp;lt;/code&amp;gt;). The file names in your project will be different than shown in this tutorial, replacing &amp;lt;code&amp;gt;reversi&amp;lt;/code&amp;gt; with your project name. Be sure that any code (other than comments) that references &amp;lt;code&amp;gt;reversi&amp;lt;/code&amp;gt; is changed to your actual project name.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;div id=&amp;quot;board&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* edit your &amp;lt;code&amp;gt;reversi.css&amp;lt;/code&amp;gt; file to transform it into a visible board:&lt;br /&gt;
&lt;br /&gt;
 #board {&lt;br /&gt;
    width: 536px;&lt;br /&gt;
    height: 528px;&lt;br /&gt;
    background-image: url(&#039;img/board.jpg&#039;);&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Important: refresh your page.&#039;&#039;&#039; Here&#039;s your board:[[File:reversi1.jpg]]&lt;br /&gt;
&lt;br /&gt;
If the board does not appear, refresh the page (always do this when you update the CSS file), and check the image filename. Remember file names are case sensitive!&lt;br /&gt;
&lt;br /&gt;
==== Code the Grid ====&lt;br /&gt;
Now, we need to create some invisible HTML elements where squares are. These elements will be used as position references for the white and black tokens. &lt;br /&gt;
&lt;br /&gt;
===== Build the grid of squares =====&lt;br /&gt;
The board is 8 squares by 8 squares. This means we need 64 squares. To avoid writing 64 individual &amp;lt;code&amp;gt;div&amp;lt;/code&amp;gt; elements on our template, we are going to generate the squares on JS &amp;lt;code&amp;gt;setup&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
We&#039;ll do this in our Javascript &amp;lt;code&amp;gt;setup&amp;lt;/code&amp;gt; method under &amp;lt;code&amp;gt;// TODO: Set up your game interface here, according to &amp;quot;gamedatas&amp;quot;&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
const board = document.getElementById(&#039;board&#039;);&lt;br /&gt;
const hor_scale = 64.8;&lt;br /&gt;
const ver_scale = 64.4;&lt;br /&gt;
for (let x=1; x&amp;lt;=8; x++) {&lt;br /&gt;
    for (let y=1; y&amp;lt;=8; y++) {&lt;br /&gt;
        const left = Math.round((x - 1) * hor_scale + 10);&lt;br /&gt;
        const top = Math.round((y - 1) * ver_scale + 7);&lt;br /&gt;
        // we use afterbegin to make sure squares are placed before discs&lt;br /&gt;
        board.insertAdjacentHTML(`afterbegin`, `&amp;lt;div id=&amp;quot;square_${x}_${y}&amp;quot; class=&amp;quot;square&amp;quot; style=&amp;quot;left: ${left}px; top: ${top}px;&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;`);&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note: as you can see, squares in our &amp;lt;code&amp;gt;board.jpg&amp;lt;/code&amp;gt; files do not have an exact width/height in pixels, and that&#039;s the reason we are using floating point numbers here.&lt;br /&gt;
&lt;br /&gt;
===== Style Those Squares =====&lt;br /&gt;
Now, to finish our work and check if everything works fine, we are going to style our square a little bit in our CSS stylesheet:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#board {&lt;br /&gt;
    width: 536px;&lt;br /&gt;
    height: 528px;&lt;br /&gt;
    background-image: url(&#039;img/board.jpg&#039;);&lt;br /&gt;
    position: relative;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.square {&lt;br /&gt;
    width: 62px;&lt;br /&gt;
    height: 62px;&lt;br /&gt;
    position: absolute;&lt;br /&gt;
    background-color: red;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Explanations:&lt;br /&gt;
* With &amp;quot;&amp;lt;code&amp;gt;position: relative&amp;lt;/code&amp;gt;&amp;quot; on board, we ensure square elements are positioned relatively to board.&lt;br /&gt;
* &amp;lt;code&amp;gt;background-color: red;&amp;lt;/code&amp;gt; is used for testing. This allows us to see the invisible elements. (You could instead do something like &amp;lt;code&amp;gt;outline: 2px solid orange;&amp;lt;/code&amp;gt; have fun and be creative)&lt;br /&gt;
&lt;br /&gt;
Let&#039;s refresh and check our (beautiful) squares:&lt;br /&gt;
&lt;br /&gt;
[[File:reversi2.jpg]]&lt;br /&gt;
&lt;br /&gt;
Now that you know the squares are there, you can remove the test line &amp;lt;code&amp;gt;background-color: red;&amp;lt;/code&amp;gt;  from your &amp;lt;code&amp;gt;.square&amp;lt;/code&amp;gt; class in the CSS stylesheet.&lt;br /&gt;
&lt;br /&gt;
===== Not Working? =====&lt;br /&gt;
If the styled squares do not appear, inspect and check your css (Chrome DevTools: Application &amp;gt; Frames &amp;gt; top &amp;gt; Stylesheets &amp;gt; reversi.css). &lt;br /&gt;
&lt;br /&gt;
== The Tokens ==&lt;br /&gt;
&lt;br /&gt;
Now, our board is ready for some tokens!&lt;br /&gt;
&lt;br /&gt;
[Note: Throughout this tutorial, sometimes &amp;quot;tokens&amp;quot; is used, and sometimes &amp;quot;discs&amp;quot; is used. They are often swapped if you&#039;re looking at code in the reversi example project.]&lt;br /&gt;
&lt;br /&gt;
=== Build the Token ===&lt;br /&gt;
There are quite a few steps before the tokens will appear. You may be used to testing after every change, but that won&#039;t work well here. The token will &#039;&#039;&#039;not&#039;&#039;&#039; show until you have add styles to the css, js template to the tpl, utility method in the js,  adjusted the php file, and added the token to the board in the js file.&lt;br /&gt;
&lt;br /&gt;
==== HTML in the .tpl file ====&lt;br /&gt;
At first, we introduce a new &#039;div&#039; element as a child of &amp;quot;board&amp;quot; to host all these tokens (in our template):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;div id=&amp;quot;board&amp;quot;&amp;gt;&lt;br /&gt;
    &lt;br /&gt;
    &amp;lt;div id=&amp;quot;discs&amp;quot;&amp;gt;&lt;br /&gt;
    &amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note: &amp;lt;code&amp;gt;discs&amp;lt;/code&amp;gt; is plural. This div will be used to hold the token divs. Shortly, we will use javascript to add individual tokens to the board.&lt;br /&gt;
&lt;br /&gt;
==== Add Token to img directory ====&lt;br /&gt;
Here&#039;s a new piece of art with the tokens. We need transparency here so we are using a png file:&lt;br /&gt;
&lt;br /&gt;
[[File:tokens.png]]&lt;br /&gt;
&lt;br /&gt;
Upload this image file &amp;lt;code&amp;gt;tokens.png&amp;lt;/code&amp;gt; in your &amp;lt;code&amp;gt;img/&amp;lt;/code&amp;gt; directory.&lt;br /&gt;
&lt;br /&gt;
Important Fun Fact: we are using ONE file for both tokens. It is really important to use a minimum number of graphic files for your game. This is called the &amp;quot;CSS sprite&amp;quot; technique, because it makes the game load faster and more reliable. [http://www.w3schools.com/css/css_image_sprites.asp Read more about CSS sprites].&lt;br /&gt;
&lt;br /&gt;
==== Style the Tokens in .css file ====&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
.disc {&lt;br /&gt;
    width: 56px;&lt;br /&gt;
    height: 56px;&lt;br /&gt;
    position: absolute;&lt;br /&gt;
    background-image: url(&#039;img/tokens.png&#039;);&lt;br /&gt;
    background-size: auto 100%;&lt;br /&gt;
}&lt;br /&gt;
.disc[data-color=&amp;quot;ffffff&amp;quot;] { background-position-x: 0%; }&lt;br /&gt;
.disc[data-color=&amp;quot;000000&amp;quot;] { background-position-x: 100%; }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
With this CSS code, we can set and change the token color by changing the &amp;lt;code&amp;gt;data-color&amp;lt;/code&amp;gt; attribute. Using data instead of a class ensures it can be only one of them (the disc cannot be black and white at the same time).&lt;br /&gt;
&lt;br /&gt;
Note the &amp;quot;&amp;lt;code&amp;gt;position: absolute&amp;lt;/code&amp;gt;&amp;quot; which allows us to position tokens on the board and make them &amp;quot;slide&amp;quot; to their positions.&lt;br /&gt;
&lt;br /&gt;
==== Add Token Utility Method in .js file ====&lt;br /&gt;
Now, let&#039;s make the first token appear on our board. Tokens are not visible at the beginning of the game: they appear dynamically during the game. For this reason, we are going to make them appear from our Javascript code, using a template string&lt;br /&gt;
&lt;br /&gt;
Let&#039;s create a method in our Javascript code (in the &amp;lt;code&amp;gt;reversi.js&amp;lt;/code&amp;gt; file) that will make a token appear on the board, using this template. Add under the section &amp;lt;code&amp;gt;//// Utility methods&amp;lt;/code&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
addDiscOnBoard: function( x, y, player )&lt;br /&gt;
{&lt;br /&gt;
    var color = this.gamedatas.players[ player ].color;&lt;br /&gt;
    &lt;br /&gt;
    document.getElementById(&#039;discs&#039;).insertAdjacentHTML(&#039;beforeend&#039;, `&amp;lt;div class=&amp;quot;disc&amp;quot; data-color=&amp;quot;${color}&amp;quot; id=&amp;quot;disc_${x}${y}&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;`);&lt;br /&gt;
    &lt;br /&gt;
    this.placeOnObject( `disc_${x}${y}`, &#039;overall_player_board_&#039;+player );&lt;br /&gt;
    this.slideToObject( `disc_${x}${y}`, &#039;square_&#039;+x+&#039;_&#039;+y ).play();&lt;br /&gt;
},  &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===== Utility Method Explanation =====&lt;br /&gt;
* with &amp;lt;code&amp;gt;element.insertAdjacentHTML&amp;lt;/code&amp;gt; method, we create a HTML piece of code and insert it as a new child of &amp;lt;code&amp;gt;tokens&amp;lt;/code&amp;gt; div element.&lt;br /&gt;
* with &amp;lt;code&amp;gt;this.placeOnObject&amp;lt;/code&amp;gt; BGA method, we place this element over the panel of some player. &lt;br /&gt;
* Immediately after, using &amp;lt;code&amp;gt;this.slideToObject&amp;lt;/code&amp;gt; BGA method, we make the token slide to the &amp;lt;code&amp;gt;square&amp;lt;/code&amp;gt; element, its final destination.&lt;br /&gt;
* &amp;lt;code&amp;gt;&#039;overall_player_board_&#039;+player&amp;lt;/code&amp;gt; refers to the div element that contains each player&#039;s information and avatar. By initially placing the token here, it gives the effect that the player&#039;s avatar is throwing the token onto the board.&lt;br /&gt;
&lt;br /&gt;
Note: don&#039;t forget to call the &amp;lt;code&amp;gt;play()&amp;lt;/code&amp;gt;, otherwise the token will remain at its original location.&lt;br /&gt;
&lt;br /&gt;
Note: during this process, the parent of the new token HTML element will stay &amp;lt;code&amp;gt;tokens&amp;lt;/code&amp;gt;. &amp;lt;code&amp;gt;placeOnObject&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;slideToObject&amp;lt;/code&amp;gt; methods are &#039;&#039;only&#039;&#039; moving the position of elements on screen, and they are &#039;&#039;not&#039;&#039; modifying the HTML tree.&lt;br /&gt;
&lt;br /&gt;
==== Set Token Colors in setupNewGame in .game.php file ====&lt;br /&gt;
Before we can show a token, we need to set the player colors in the &amp;lt;code&amp;gt;setupNewGame&amp;lt;/code&amp;gt; function in &amp;lt;code&amp;gt;reversi.game.php&amp;lt;/code&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
Replace &amp;lt;code&amp;gt;$default_colors = $gameinfos[&#039;player_colors&#039;];&amp;lt;/code&amp;gt; with the following line:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$default_colors = array( &amp;quot;ffffff&amp;quot;, &amp;quot;000000&amp;quot; );&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note: A few lines below, you may have to remove the line &amp;lt;code&amp;gt;this-&amp;gt;reattributeColorsBasedOnPreferences( $players, $gameinfos[&#039;player_colors&#039;] );&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Test the Token ===&lt;br /&gt;
Now, to test if everything works fine&lt;br /&gt;
&lt;br /&gt;
==== &amp;lt;code&amp;gt;addTokenOnBoard()&amp;lt;/code&amp;gt; in .js file to Test ====&lt;br /&gt;
In &amp;lt;code&amp;gt;reversi.js&amp;lt;/code&amp;gt;, in &amp;lt;code&amp;gt;setup: function&amp;lt;/code&amp;gt;, under the code we added to generate the squares. &lt;br /&gt;
 this.addDiscOnBoard( 2, 2, this.player_id );&lt;br /&gt;
Now restart the game.&lt;br /&gt;
&lt;br /&gt;
A token should appear and slide immediately to its position, like this:&lt;br /&gt;
&lt;br /&gt;
[[File:reversi3.jpg]]&lt;br /&gt;
&lt;br /&gt;
== The database ==&lt;br /&gt;
&lt;br /&gt;
We did most of the client-side programming, so let&#039;s have a look on the other side now. To design the database model of our game, you will need to access the database. You won&#039;t need to do anything in database UI, yet.&lt;br /&gt;
&lt;br /&gt;
=== Accessing the Database ===&lt;br /&gt;
To access the database, start a game, then click &amp;quot;Go to game database&amp;quot; link at the bottom of our game, to access the database directly with a PhpMyAdmin instance.&lt;br /&gt;
&lt;br /&gt;
After the first time you&#039;ve access the database, you could skip opening a game and instead, go to https://studio.boardgamearena.com/db/ . Your PhpMyAdmin username/password is in your welcome email.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note&#039;&#039;&#039;: do not remove existing tables&lt;br /&gt;
&lt;br /&gt;
=== Create Table in .sql file ===&lt;br /&gt;
Now, you are able to create the table(s) you need for your game, and report every SQL command used in your &amp;lt;code&amp;gt;dbmodel.sql&amp;lt;/code&amp;gt; file. &lt;br /&gt;
&lt;br /&gt;
The database model of Reversi is short: just one table with the squares of the board. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
CREATE TABLE IF NOT EXISTS `board` (&lt;br /&gt;
  `board_x` smallint(5) unsigned NOT NULL,&lt;br /&gt;
  `board_y` smallint(5) unsigned NOT NULL,&lt;br /&gt;
  `board_player` int(10) unsigned DEFAULT NULL,&lt;br /&gt;
  PRIMARY KEY (`board_x`,`board_y`)&lt;br /&gt;
) ENGINE=InnoDB DEFAULT CHARSET=utf8;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Add the above SQL to &amp;lt;code&amp;gt;dbmodel.sql&amp;lt;/code&amp;gt;. Pay special attention to the backtick &amp;lt;code&amp;gt;`&amp;lt;/code&amp;gt; character vs. the single quote &amp;lt;code&amp;gt;&#039;&amp;lt;/code&amp;gt; when working with SQL. &lt;br /&gt;
&lt;br /&gt;
=== Test the Table ===&lt;br /&gt;
Now, a new database with a &amp;lt;code&amp;gt;board&amp;lt;/code&amp;gt; table will be created each time we start a Reversi game. This is why after modifying our &amp;lt;code&amp;gt;dbmodel.sql&amp;lt;/code&amp;gt; it&#039;s a good time to stop your current game &amp;amp; start a new game.&lt;br /&gt;
&lt;br /&gt;
Start a new game and verify a table is created.&lt;br /&gt;
&lt;br /&gt;
== Setup the initial game position ==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note&#039;&#039;&#039;: From now on, you must launch the game with &#039;&#039;&#039;two players&#039;&#039;&#039; to get two &amp;lt;code&amp;gt;player_id&amp;lt;/code&amp;gt;s within the database. Otherwise, the game will crash.&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;setupNewGame&amp;lt;/code&amp;gt; method of our &amp;lt;code&amp;gt;reversi.game.php&amp;lt;/code&amp;gt; is called during initial setup. This initializes our data and places the starting tokens on the board. At the beginning of the game, there should be 4 tokens on the board.&lt;br /&gt;
&lt;br /&gt;
=== Initialize the Board in .game.php file ===&lt;br /&gt;
Under &amp;lt;code&amp;gt;// TODO: setup the initial game situation here&amp;lt;/code&amp;gt;, initialize the board&amp;lt;pre&amp;gt;&lt;br /&gt;
// Init the board&lt;br /&gt;
$sql = &amp;quot;INSERT INTO board (board_x,board_y,board_player) VALUES &amp;quot;;&lt;br /&gt;
$sql_values = array();&lt;br /&gt;
list( $blackplayer_id, $whiteplayer_id ) = array_keys( $players );&lt;br /&gt;
for( $x=1; $x&amp;lt;=8; $x++ )&lt;br /&gt;
{&lt;br /&gt;
	for( $y=1; $y&amp;lt;=8; $y++ )&lt;br /&gt;
	{&lt;br /&gt;
	$token_value = &amp;quot;NULL&amp;quot;;&lt;br /&gt;
	if( ($x==4 &amp;amp;&amp;amp; $y==4) || ($x==5 &amp;amp;&amp;amp; $y==5) )  // Initial positions of white player&lt;br /&gt;
	$token_value = &amp;quot;&#039;$whiteplayer_id&#039;&amp;quot;;&lt;br /&gt;
	else if( ($x==4 &amp;amp;&amp;amp; $y==5) || ($x==5 &amp;amp;&amp;amp; $y==4) )  // Initial positions of black player&lt;br /&gt;
	$token_value = &amp;quot;&#039;$blackplayer_id&#039;&amp;quot;;&lt;br /&gt;
                    &lt;br /&gt;
	$sql_values[] = &amp;quot;(&#039;$x&#039;,&#039;$y&#039;,$token_value)&amp;quot;;&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
$sql .= implode( &#039;,&#039;, $sql_values );&lt;br /&gt;
$this-&amp;gt;DbQuery( $sql );&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Board Initialization Explanation ====&lt;br /&gt;
&lt;br /&gt;
* We create one table entry for each square, with a &amp;lt;code&amp;gt;NULL&amp;lt;/code&amp;gt; value which means &amp;quot;empty square&amp;quot;&lt;br /&gt;
* On 4 of the squares, we place an initial token.&lt;br /&gt;
&lt;br /&gt;
After this, we set &amp;lt;code&amp;gt;activeNextPlayer&amp;lt;/code&amp;gt; to make the first player active at the beginning of the game (this line is already present in the default code template).&lt;br /&gt;
&lt;br /&gt;
If you didn&#039;t do it earlier, you need to remove the call to &amp;lt;code&amp;gt;this-&amp;gt;reattributeColorsBasedOnPreferences()&amp;lt;/code&amp;gt; in &amp;lt;code&amp;gt;SetupNewGame()&amp;lt;/code&amp;gt;. If you don&#039;t, player color preferences will try (and fail) to override the two colors supported here.&lt;br /&gt;
&lt;br /&gt;
=== Show the Initial Token Setup ===&lt;br /&gt;
Now, we need to make these tokens appear on the client side. The first step is to return the token positions with our &amp;lt;code&amp;gt;getAllDatas()&amp;lt;/code&amp;gt; PHP method. &amp;lt;code&amp;gt;getAllDatas()&amp;lt;/code&amp;gt; is called during each page reload.&lt;br /&gt;
&lt;br /&gt;
In the &amp;lt;code&amp;gt;getAllDatas()&amp;lt;/code&amp;gt; method, after &amp;lt;code&amp;gt;// TODO: Gather all information about current game situation (visible by player $current_player_id)&amp;lt;/code&amp;gt;, add the following lines:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
// Get reversi board token&lt;br /&gt;
$result[&#039;board&#039;] = self::getObjectListFromDB( &amp;quot;SELECT board_x x, board_y y, board_player player&lt;br /&gt;
	FROM board&lt;br /&gt;
	WHERE board_player IS NOT NULL&amp;quot; );&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Next, you may need to modify the query that gets player information to also get the player&#039;s colors. This is in the variable &amp;lt;code&amp;gt;$sql&amp;lt;/code&amp;gt;, above the lines you just inserted in &amp;lt;code&amp;gt;getAllDatas()&amp;lt;/code&amp;gt;. Below is what the line will look like. Notice how we&#039;ve added &amp;lt;code&amp;gt;player_color color&amp;lt;/code&amp;gt; to the sql query.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$sql = &amp;quot;SELECT player_id id, player_score score, player_color color FROM player &amp;quot;;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We are using the BGA framework&#039;s &amp;lt;code&amp;gt;getObjectListFromDB()&amp;lt;/code&amp;gt; that formats the result of this SQL query in a PHP array with x, y and player attributes. We add it to the result associative array with the key &amp;lt;code&amp;gt;board&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Last, we process this array client side. Let&#039;s place a token on the board for each array item. We&#039;ll do this in our Javascript &amp;lt;code&amp;gt;setup&amp;lt;/code&amp;gt; method under the code we added to generate the squares. &lt;br /&gt;
&lt;br /&gt;
This will result in a removal or edit of the previously added line &amp;lt;code&amp;gt;this.addDiscOnBoard(2, 2, this.player_id);&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
for( var i in gamedatas.board )&lt;br /&gt;
{&lt;br /&gt;
    var square = gamedatas.board[i];&lt;br /&gt;
    &lt;br /&gt;
    if( square.player !== null )&lt;br /&gt;
    {&lt;br /&gt;
        this.addDiscOnBoard( square.x, square.y, square.player );&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;board&amp;lt;/code&amp;gt; entry created in &amp;lt;code&amp;gt;getAllDatas()&amp;lt;/code&amp;gt; is used here as &amp;lt;code&amp;gt;gamedatas.board&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Test the Game Start ===&lt;br /&gt;
Reload... and here we are:&lt;br /&gt;
&lt;br /&gt;
[[File:reversi5.jpg]]&lt;br /&gt;
&lt;br /&gt;
It starts to feel like Reversi here...&lt;br /&gt;
&lt;br /&gt;
== The game state machine ==&lt;br /&gt;
&lt;br /&gt;
Stop your game, again. You&#039;re about to start the core game logic.&lt;br /&gt;
&lt;br /&gt;
You already read [http://www.slideshare.net/boardgamearena/bga-studio-focus-on-bga-game-state-machine Focus on BGA game state machine], so you know that this is the heart of your game logic. For reversi, it&#039;s relatively simple. Here&#039;s a diagram of our game state machine:&lt;br /&gt;
&lt;br /&gt;
[[File:reversi6.jpg]]&lt;br /&gt;
&lt;br /&gt;
=== Build your States ===&lt;br /&gt;
And here&#039;s our &amp;lt;code&amp;gt;states.inc.php&amp;lt;/code&amp;gt;, according to this diagram:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$machinestates = array(&lt;br /&gt;
&lt;br /&gt;
    ST_BGA_GAME_SETUP =&amp;gt; array(&lt;br /&gt;
        &amp;quot;name&amp;quot; =&amp;gt; &amp;quot;gameSetup&amp;quot;,&lt;br /&gt;
        &amp;quot;description&amp;quot; =&amp;gt; clienttranslate(&amp;quot;Game setup&amp;quot;),&lt;br /&gt;
        &amp;quot;type&amp;quot; =&amp;gt; &amp;quot;manager&amp;quot;,&lt;br /&gt;
        &amp;quot;action&amp;quot; =&amp;gt; &amp;quot;stGameSetup&amp;quot;,&lt;br /&gt;
        &amp;quot;transitions&amp;quot; =&amp;gt; array( &amp;quot;&amp;quot; =&amp;gt; ST_PLAYER_PLAY_DISC )&lt;br /&gt;
    ),&lt;br /&gt;
    &lt;br /&gt;
    ST_PLAYER_PLAY_DISC =&amp;gt; array(&lt;br /&gt;
        &amp;quot;name&amp;quot; =&amp;gt; &amp;quot;playerTurn&amp;quot;,&lt;br /&gt;
		&amp;quot;description&amp;quot; =&amp;gt; clienttranslate(&#039;${actplayer} must play a disc&#039;),&lt;br /&gt;
		&amp;quot;descriptionmyturn&amp;quot; =&amp;gt; clienttranslate(&#039;${you} must play a disc&#039;),&lt;br /&gt;
        &amp;quot;type&amp;quot; =&amp;gt; &amp;quot;activeplayer&amp;quot;,&lt;br /&gt;
        &amp;quot;args&amp;quot; =&amp;gt; &amp;quot;argPlayerTurn&amp;quot;,&lt;br /&gt;
        &amp;quot;possibleactions&amp;quot; =&amp;gt; array( &#039;actPlayDisc&#039; ),&lt;br /&gt;
        &amp;quot;transitions&amp;quot; =&amp;gt; array( &amp;quot;playDisc&amp;quot; =&amp;gt; ST_NEXT_PLAYER, &amp;quot;zombiePass&amp;quot; =&amp;gt; ST_NEXT_PLAYER )&lt;br /&gt;
    ),&lt;br /&gt;
    &lt;br /&gt;
    ST_NEXT_PLAYER =&amp;gt; array(&lt;br /&gt;
        &amp;quot;name&amp;quot; =&amp;gt; &amp;quot;nextPlayer&amp;quot;,&lt;br /&gt;
        &amp;quot;type&amp;quot; =&amp;gt; &amp;quot;game&amp;quot;,&lt;br /&gt;
        &amp;quot;action&amp;quot; =&amp;gt; &amp;quot;stNextPlayer&amp;quot;,&lt;br /&gt;
        &amp;quot;updateGameProgression&amp;quot; =&amp;gt; true,        &lt;br /&gt;
        &amp;quot;transitions&amp;quot; =&amp;gt; array( &amp;quot;nextTurn&amp;quot; =&amp;gt; ST_PLAYER_PLAY_DISC, &amp;quot;cantPlay&amp;quot; =&amp;gt; ST_NEXT_PLAYER, &amp;quot;endGame&amp;quot; =&amp;gt; ST_END_GAME )&lt;br /&gt;
    ),&lt;br /&gt;
   &lt;br /&gt;
    ST_END_GAME =&amp;gt; array(&lt;br /&gt;
        &amp;quot;name&amp;quot; =&amp;gt; &amp;quot;gameEnd&amp;quot;,&lt;br /&gt;
        &amp;quot;description&amp;quot; =&amp;gt; clienttranslate(&amp;quot;End of game&amp;quot;),&lt;br /&gt;
        &amp;quot;type&amp;quot; =&amp;gt; &amp;quot;manager&amp;quot;,&lt;br /&gt;
        &amp;quot;action&amp;quot; =&amp;gt; &amp;quot;stGameEnd&amp;quot;,&lt;br /&gt;
        &amp;quot;args&amp;quot; =&amp;gt; &amp;quot;argGameEnd&amp;quot;&lt;br /&gt;
    )&lt;br /&gt;
&lt;br /&gt;
);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We used constants to give an index to the different states. This is to avoid mistakes when we reuse these indexes on the transitions array.&lt;br /&gt;
&lt;br /&gt;
Let&#039;s create a file you&#039;ll put in &amp;lt;code&amp;gt;modules/php/constants.inc.php&amp;lt;/code&amp;gt; :&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;?php&lt;br /&gt;
&lt;br /&gt;
/*&lt;br /&gt;
 * State constants&lt;br /&gt;
 */&lt;br /&gt;
const ST_BGA_GAME_SETUP = 1;&lt;br /&gt;
&lt;br /&gt;
const ST_PLAYER_PLAY_DISC = 10;&lt;br /&gt;
const ST_NEXT_PLAYER = 11;&lt;br /&gt;
&lt;br /&gt;
const ST_END_GAME = 99;&lt;br /&gt;
&lt;br /&gt;
?&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You will also need to add &amp;lt;code&amp;gt;require_once(&amp;quot;modules/php/constants.inc.php&amp;quot;);&amp;lt;/code&amp;gt; at the beginning of the state.inc.php to load these constants.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Now, in &amp;lt;code&amp;gt;reversi.game.php&amp;lt;/code&amp;gt; let&#039;s create the methods that are declared in this game states description file:&lt;br /&gt;
* &amp;lt;code&amp;gt;argPlayerTurn&amp;lt;/code&amp;gt;: referenced in the &amp;lt;code&amp;gt;args&amp;lt;/code&amp;gt; property of the &amp;lt;code&amp;gt;playerTurn&amp;lt;/code&amp;gt; state; this is the name of the method to call to retrieve arguments for this gamestate. Arguments are sent to the client side to be used on &amp;lt;code&amp;gt;onEnteringState&amp;lt;/code&amp;gt; or to set arguments in the gamestate description.&lt;br /&gt;
* &amp;lt;code&amp;gt;stNextPlayer&amp;lt;/code&amp;gt;: referenced in the &amp;lt;code&amp;gt;action&amp;lt;/code&amp;gt; property of the &amp;lt;code&amp;gt;nextPlayer&amp;lt;/code&amp;gt; state; this is the name of the method to call when this game state become the current game state.&lt;br /&gt;
&lt;br /&gt;
=== Test Your States ===&lt;br /&gt;
... and start a new Reversi game.&lt;br /&gt;
&lt;br /&gt;
As you can see on the screen capture below, the BGA framework makes the game jump to our first game state &amp;lt;code&amp;gt;playerTurn&amp;lt;/code&amp;gt; right after the initial setup. That&#039;s why the status bar contains the description of &amp;lt;code&amp;gt;playerTurn&amp;lt;/code&amp;gt; state (&amp;quot;XXXX must play a disc&amp;quot;):&lt;br /&gt;
&lt;br /&gt;
[[File:reversi7.jpg]]&lt;br /&gt;
&lt;br /&gt;
== The rules ==&lt;br /&gt;
&lt;br /&gt;
We will use the &amp;lt;code&amp;gt;getPossibleMoves&amp;lt;/code&amp;gt; PHP method to:&lt;br /&gt;
* Indicate to the current player where she is allowed to play by returning a list of coordinates&lt;br /&gt;
* Check if the player has the right to play in the spot they choose&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;&lt;br /&gt;
Example of &amp;lt;code&amp;gt;getPossibleMoves&amp;lt;/code&amp;gt; here https://gist.github.com/leocaseiro/a8bc2851bd0caddd06685b5035937d15&lt;br /&gt;
&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This is pure PHP programming here, and there are no special things from the BGA framework that can be used. This is why we won&#039;t go into details here. The overall idea is:&lt;br /&gt;
* Create a &amp;lt;code&amp;gt;getTurnedOverDiscs(x,y)&amp;lt;/code&amp;gt; method that returns coordinates of discs that would be turned over if a token would be played at &amp;lt;code&amp;gt;x&amp;lt;/code&amp;gt;,&amp;lt;code&amp;gt;y&amp;lt;/code&amp;gt;.&lt;br /&gt;
* Loop through all free squares of the board and call the &amp;lt;code&amp;gt;getTurnedOverDiscs&amp;lt;/code&amp;gt; method on each of them. If at least 1 token is turned over, this is a valid move.&lt;br /&gt;
&lt;br /&gt;
IMPORTANT: Making a database query is slow! Please don&#039;t load the entire game board with a SQL query multiple times. In our implementation, we load the entire board once at the beginning of &amp;lt;code&amp;gt;getPossibleMoves&amp;lt;/code&amp;gt;, and then pass the board as an argument to all methods.&lt;br /&gt;
&lt;br /&gt;
If you want to look into details, please look at the &amp;quot;utility method&amp;quot; sections of &amp;lt;code&amp;gt;reversi.game.php&amp;lt;/code&amp;gt;. If building the tutorial yourself, copy the functions under &amp;quot;Utility functions&amp;quot; comment from the Reversi tutorial.&lt;br /&gt;
&lt;br /&gt;
== Display allowed moves ==&lt;br /&gt;
&lt;br /&gt;
Now we want to highlight the squares where the player can place a disc.&lt;br /&gt;
&lt;br /&gt;
To do this, we add a &amp;lt;code&amp;gt;argPlayerTurn&amp;lt;/code&amp;gt; method in &amp;lt;code&amp;gt;reversi.game.php&amp;lt;/code&amp;gt;. This method is called on the server each time we enter into &amp;lt;code&amp;gt;playerTurn&amp;lt;/code&amp;gt; game state, and its result is transferred automatically to the client-side:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
function argPlayerTurn(): array&lt;br /&gt;
{&lt;br /&gt;
    return [&lt;br /&gt;
        &#039;possibleMoves&#039; =&amp;gt; $this-&amp;gt;getPossibleMoves( intval($this-&amp;gt;getActivePlayerId()) )&lt;br /&gt;
    ];&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We use the &amp;lt;code&amp;gt;getPossibleMoves&amp;lt;/code&amp;gt; method we just developed.&lt;br /&gt;
&lt;br /&gt;
Each time we enter into a new game state, we use the &amp;lt;code&amp;gt;onEnteringState&amp;lt;/code&amp;gt; Javascript method (in the &amp;lt;code&amp;gt;reversi.js&amp;lt;/code&amp;gt; file, under &amp;quot;Game &amp;amp; client states&amp;quot;). This lets us use the data returned by the method above on the client side.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        onEnteringState: function( stateName, args )&lt;br /&gt;
        {&lt;br /&gt;
           console.log( &#039;Entering state: &#039;+stateName );&lt;br /&gt;
            &lt;br /&gt;
            switch( stateName )&lt;br /&gt;
            {&lt;br /&gt;
            case &#039;playerTurn&#039;:&lt;br /&gt;
                this.updatePossibleMoves( args.args.possibleMoves );&lt;br /&gt;
                break;&lt;br /&gt;
            }&lt;br /&gt;
        },&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
So, when we enter into &amp;lt;code&amp;gt;playerTurn&amp;lt;/code&amp;gt; game state, we call our &amp;lt;code&amp;gt;updatePossibleMoves&amp;lt;/code&amp;gt; method (under the &amp;quot;Utility methods&amp;quot; section). This method looks like this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
updatePossibleMoves: function( possibleMoves )&lt;br /&gt;
{&lt;br /&gt;
    // Remove current possible moves&lt;br /&gt;
    document.querySelectorAll(&#039;.possibleMove&#039;).forEach(div =&amp;gt; div.classList.remove(&#039;possibleMove&#039;));&lt;br /&gt;
&lt;br /&gt;
    for( var x in possibleMoves )&lt;br /&gt;
    {&lt;br /&gt;
        for( var y in possibleMoves[ x ] )&lt;br /&gt;
        {&lt;br /&gt;
            // x,y is a possible move&lt;br /&gt;
            document.getElementById(`square_${x}_${y}`).classList.add(&#039;possibleMove&#039;);&lt;br /&gt;
        }            &lt;br /&gt;
    }&lt;br /&gt;
                &lt;br /&gt;
    this.addTooltipToClass( &#039;possibleMove&#039;, &#039;&#039;, _(&#039;Place a disc here&#039;) );&lt;br /&gt;
},&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Here&#039;s what this does. At first, it removes all &amp;lt;code&amp;gt;possibleMove&amp;lt;/code&amp;gt; classes currently applied with the very useful &amp;lt;code&amp;gt;document.querySelectorAll&amp;lt;/code&amp;gt; method.&lt;br /&gt;
&lt;br /&gt;
Then it loops through all possible moves our PHP &amp;lt;code&amp;gt;updatePossibleMoves&amp;lt;/code&amp;gt; function created for us, and adds the &amp;lt;code&amp;gt;possibleMove&amp;lt;/code&amp;gt; class to each corresponding square.&lt;br /&gt;
&lt;br /&gt;
Finally, it uses the BGA framework &amp;lt;code&amp;gt;addTooltipToClass&amp;lt;/code&amp;gt; method to associate a tooltip to all those highlighted squares so that players can understand their meaning.&lt;br /&gt;
&lt;br /&gt;
To see the possible moves we need to create a CSS class (&amp;lt;code&amp;gt;possibleMove&amp;lt;/code&amp;gt;) that can be applied to a &amp;lt;code&amp;gt;square&amp;lt;/code&amp;gt; element to highlight it:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
.possibleMove {&lt;br /&gt;
    background-color: white;&lt;br /&gt;
    opacity: 0.2; &lt;br /&gt;
    cursor: pointer;  &lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
And here we are:&lt;br /&gt;
&lt;br /&gt;
[[File:reversi8.jpg.jpg]]&lt;br /&gt;
&lt;br /&gt;
== Let&#039;s play ==&lt;br /&gt;
&lt;br /&gt;
From now, it&#039;s better to restart a game with 2 players, because we are going to implement a complete Reversi turn. The summary of what we are going to do is:&lt;br /&gt;
* When we click on a &amp;lt;code&amp;gt;possibleMove&amp;lt;/code&amp;gt; square, send the move to the server.&lt;br /&gt;
* Server side, check the move is correct, apply Reversi rules and jump to next player.&lt;br /&gt;
* Client side, change the token position to reflect the move.&lt;br /&gt;
&lt;br /&gt;
First we associate each click on a square to one of our methods using our Javascript &amp;lt;code&amp;gt;setup&amp;lt;/code&amp;gt; method:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
document.querySelectorAll(&#039;.square&#039;).forEach(square =&amp;gt; square.addEventListener(&#039;click&#039;, e =&amp;gt; this.onPlayDisc(e)));&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note the use of the &amp;quot;dojo.query&amp;quot; method to get all HTML elements with &amp;quot;square&amp;quot; class in just one function call. Now, our &amp;quot;onPlayDisc&amp;quot; method is called each time someone clicks on a square.&lt;br /&gt;
&lt;br /&gt;
Here&#039;s our &amp;quot;onPlayDisc&amp;quot; method below:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
onPlayDisc: function( evt )&lt;br /&gt;
{&lt;br /&gt;
    // Stop this event propagation&lt;br /&gt;
    evt.preventDefault();&lt;br /&gt;
    evt.stopPropagation();&lt;br /&gt;
&lt;br /&gt;
    // Get the cliqued square x and y&lt;br /&gt;
    // Note: square id format is &amp;quot;square_X_Y&amp;quot;&lt;br /&gt;
    var coords = evt.currentTarget.id.split(&#039;_&#039;);&lt;br /&gt;
    var x = coords[1];&lt;br /&gt;
    var y = coords[2];&lt;br /&gt;
&lt;br /&gt;
    if(!document.getElementById(`square_${x}_${y}`).classList.contains(&#039;possibleMove&#039;)) {&lt;br /&gt;
        // This is not a possible move =&amp;gt; the click does nothing&lt;br /&gt;
        return ;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    this.bgaPerformAction(&amp;quot;actPlayDisc&amp;quot;, {&lt;br /&gt;
        x:x,&lt;br /&gt;
        y:y&lt;br /&gt;
    });&lt;br /&gt;
},&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
What we do here is:&lt;br /&gt;
* We stop the propagation of the Javascript &amp;lt;code&amp;gt;onclick&amp;lt;/code&amp;gt; event. Otherwise, it can lead to random behavior so it&#039;s always a good idea.&lt;br /&gt;
* We get the x/y coordinates of the square by using &amp;lt;code&amp;gt;evt.currentTarget.id&amp;lt;/code&amp;gt;&lt;br /&gt;
* We check that clicked square has the &amp;lt;code&amp;gt;possibleMove&amp;lt;/code&amp;gt; class, otherwise we know for sure that we can&#039;t play there.&lt;br /&gt;
* Finally, we make a call to the server using BGA &amp;lt;code&amp;gt;bgaPerformAction&amp;lt;/code&amp;gt; method with argument x and y. This call will check that &amp;lt;code&amp;gt;actPlayDisc&amp;lt;/code&amp;gt; action is possible, according to current game state (see &amp;lt;code&amp;gt;possibleactions&amp;lt;/code&amp;gt; entry in our &amp;lt;code&amp;gt;playerTurn&amp;lt;/code&amp;gt; game state defined above). This check is important to avoid issues if a player double clicks on a square.&lt;br /&gt;
&lt;br /&gt;
Now, we have to manage this &amp;lt;code&amp;gt;actPlayDisc&amp;lt;/code&amp;gt; action on the server side. Add a corresponding &amp;lt;code&amp;gt;actPlayDisc&amp;lt;/code&amp;gt; method in our game logic (&amp;lt;code&amp;gt;reversi.game.php&amp;lt;/code&amp;gt;):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
function actPlayDisc( int $x, int $y )&lt;br /&gt;
{&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
(The function will be called when the front-side action is triggered using the Autowire mechanism, if you want to see how it works in details check https://en.doc.boardgamearena.com/Main_game_logic:_yourgamename.game.php#Actions_%28autowired%29 )&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        $player_id = intval($this-&amp;gt;getActivePlayerId()); &lt;br /&gt;
        &lt;br /&gt;
        // Now, check if this is a possible move&lt;br /&gt;
        $board = $this-&amp;gt;getBoard();&lt;br /&gt;
        $turnedOverDiscs = $this-&amp;gt;getTurnedOverDiscs( $x, $y, $player_id, $board );&lt;br /&gt;
        &lt;br /&gt;
        if( count( $turnedOverDiscs ) &amp;gt; 0 )&lt;br /&gt;
        {&lt;br /&gt;
            // This move is possible!&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
...now, we are using the &amp;lt;code&amp;gt;getTurnedOverDiscs&amp;lt;/code&amp;gt; method again to check that this move is possible.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
            // Let&#039;s place a disc at x,y and return all &amp;quot;$returned&amp;quot; discs to the active player&lt;br /&gt;
            &lt;br /&gt;
            $sql = &amp;quot;UPDATE board SET board_player=&#039;$player_id&#039;&lt;br /&gt;
                    WHERE ( board_x, board_y) IN ( &amp;quot;;&lt;br /&gt;
            &lt;br /&gt;
            foreach( $turnedOverDiscs as $turnedOver )&lt;br /&gt;
            {&lt;br /&gt;
                $sql .= &amp;quot;(&#039;&amp;quot;.$turnedOver[&#039;x&#039;].&amp;quot;&#039;,&#039;&amp;quot;.$turnedOver[&#039;y&#039;].&amp;quot;&#039;),&amp;quot;;&lt;br /&gt;
            }&lt;br /&gt;
            $sql .= &amp;quot;(&#039;$x&#039;,&#039;$y&#039;) ) &amp;quot;;&lt;br /&gt;
                       &lt;br /&gt;
            $this-&amp;gt;DbQuery( $sql );&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
... we update the database to change the color of all turned over disc + the disc we just placed.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
            // Update scores according to the number of disc on board&lt;br /&gt;
            $sql = &amp;quot;UPDATE player&lt;br /&gt;
                    SET player_score = (&lt;br /&gt;
                    SELECT COUNT( board_x ) FROM board WHERE board_player=player_id&lt;br /&gt;
                    )&amp;quot;;&lt;br /&gt;
            $this-&amp;gt;DbQuery( $sql );&lt;br /&gt;
            &lt;br /&gt;
            // Statistics&lt;br /&gt;
            $this-&amp;gt;incStat( count( $turnedOverDiscs ), &amp;quot;turnedOver&amp;quot;, $player_id );&lt;br /&gt;
            if( ($x==1 &amp;amp;&amp;amp; $y==1) || ($x==8 &amp;amp;&amp;amp; $y==1) || ($x==1 &amp;amp;&amp;amp; $y==8) || ($x==8 &amp;amp;&amp;amp; $y==8) )&lt;br /&gt;
                $this-&amp;gt;incStat( 1, &#039;discPlayedOnCorner&#039;, $player_id );&lt;br /&gt;
            else if( $x==1 || $x==8 || $y==1 || $y==8 )&lt;br /&gt;
                $this-&amp;gt;incStat( 1, &#039;discPlayedOnBorder&#039;, $player_id );&lt;br /&gt;
            else if( $x&amp;gt;=3 &amp;amp;&amp;amp; $x&amp;lt;=6 &amp;amp;&amp;amp; $y&amp;gt;=3 &amp;amp;&amp;amp; $y&amp;lt;=6 )&lt;br /&gt;
                $this-&amp;gt;incStat( 1, &#039;discPlayedOnCenter&#039;, $player_id );&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
... now, we update both player score by counting all disc, and we manage game statistics.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
            // Notify&lt;br /&gt;
            $this-&amp;gt;notifyAllPlayers( &amp;quot;playDisc&amp;quot;, clienttranslate( &#039;${player_name} plays a disc and turns over ${returned_nbr} disc(s)&#039; ), array(&lt;br /&gt;
                &#039;player_id&#039; =&amp;gt; $player_id,&lt;br /&gt;
                &#039;player_name&#039; =&amp;gt; $this-&amp;gt;getActivePlayerName(),&lt;br /&gt;
                &#039;returned_nbr&#039; =&amp;gt; count( $turnedOverDiscs ),&lt;br /&gt;
                &#039;x&#039; =&amp;gt; $x,&lt;br /&gt;
                &#039;y&#039; =&amp;gt; $y&lt;br /&gt;
            ) );&lt;br /&gt;
&lt;br /&gt;
            $this-&amp;gt;notifyAllPlayers( &amp;quot;turnOverDiscs&amp;quot;, &#039;&#039;, array(&lt;br /&gt;
                &#039;player_id&#039; =&amp;gt; $player_id,&lt;br /&gt;
                &#039;turnedOver&#039; =&amp;gt; $turnedOverDiscs&lt;br /&gt;
            ) );&lt;br /&gt;
            &lt;br /&gt;
            $newScores = $this-&amp;gt;getCollectionFromDb( &amp;quot;SELECT player_id, player_score FROM player&amp;quot;, true );&lt;br /&gt;
            $this-&amp;gt;notifyAllPlayers( &amp;quot;newScores&amp;quot;, &amp;quot;&amp;quot;, array(&lt;br /&gt;
                &amp;quot;scores&amp;quot; =&amp;gt; $newScores&lt;br /&gt;
            ) );&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
... then we notify about all these changes. We are using for that 3 notifications (&amp;lt;code&amp;gt;playDisc&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;turnOverDiscs&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;newScores&amp;lt;/code&amp;gt; that we are going to implement on client side later). Note that the description of the &amp;lt;code&amp;gt;playDisc&amp;lt;/code&amp;gt; notification will be logged in the game log.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
            // Then, go to the next state&lt;br /&gt;
            $this-&amp;gt;gamestate-&amp;gt;nextState( &#039;playDisc&#039; );&lt;br /&gt;
        }&lt;br /&gt;
        else&lt;br /&gt;
            throw new BgaSystemException( &amp;quot;Impossible move&amp;quot; );&lt;br /&gt;
    }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
... finally, we jump to the next game state if everything goes fine (&amp;lt;code&amp;gt;playDisc&amp;lt;/code&amp;gt; is the name of a transition in the &amp;lt;code&amp;gt;playerTurn&amp;lt;/code&amp;gt; game state description above which leads to state 11 which is &amp;lt;code&amp;gt;nextPlayer&amp;lt;/code&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
To make the statistics work, we have to initialize them in &amp;lt;code&amp;gt;stats.json&amp;lt;/code&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
  &amp;quot;player&amp;quot;: {&lt;br /&gt;
    &amp;quot;discPlayedOnCorner&amp;quot;: {&lt;br /&gt;
      &amp;quot;id&amp;quot;: 10,&lt;br /&gt;
      &amp;quot;name&amp;quot;: &amp;quot;Discs played on a corner&amp;quot;,&lt;br /&gt;
      &amp;quot;type&amp;quot;: &amp;quot;int&amp;quot;&lt;br /&gt;
    },&lt;br /&gt;
    &amp;quot;discPlayedOnBorder&amp;quot;: {&lt;br /&gt;
      &amp;quot;id&amp;quot;: 11,&lt;br /&gt;
      &amp;quot;name&amp;quot;: &amp;quot;Discs played on a border&amp;quot;,&lt;br /&gt;
      &amp;quot;type&amp;quot;: &amp;quot;int&amp;quot;&lt;br /&gt;
    },&lt;br /&gt;
    &amp;quot;discPlayedOnCenter&amp;quot;: {&lt;br /&gt;
      &amp;quot;id&amp;quot;: 12,&lt;br /&gt;
      &amp;quot;name&amp;quot;: &amp;quot;Discs played on board center part&amp;quot;,&lt;br /&gt;
      &amp;quot;type&amp;quot;: &amp;quot;int&amp;quot;&lt;br /&gt;
    },&lt;br /&gt;
    &amp;quot;turnedOver&amp;quot;: {&lt;br /&gt;
      &amp;quot;id&amp;quot;: 13,&lt;br /&gt;
      &amp;quot;name&amp;quot;: &amp;quot;Number of discs turned over&amp;quot;,&lt;br /&gt;
      &amp;quot;type&amp;quot;: &amp;quot;int&amp;quot;&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
A last thing to do on the server side is to activate the next player when we enter the &amp;lt;code&amp;gt;nextPlayer&amp;lt;/code&amp;gt; game state (in the &amp;lt;code&amp;gt;reversi.game.php&amp;lt;/code&amp;gt; file, under &amp;quot;Game state reactions&amp;quot;):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    function stNextPlayer(): void&lt;br /&gt;
    {&lt;br /&gt;
        // Active next player&lt;br /&gt;
        $player_id = intval($this-&amp;gt;activeNextPlayer());&lt;br /&gt;
&lt;br /&gt;
        // Check if both player has at least 1 discs, and if there are free squares to play&lt;br /&gt;
        $player_to_discs = $this-&amp;gt;getCollectionFromDb( &amp;quot;SELECT board_player, COUNT( board_x )&lt;br /&gt;
                                                       FROM board&lt;br /&gt;
                                                       GROUP BY board_player&amp;quot;, true );&lt;br /&gt;
&lt;br /&gt;
        if( ! isset( $player_to_discs[ null ] ) )&lt;br /&gt;
        {&lt;br /&gt;
            // Index 0 has not been set =&amp;gt; there&#039;s no more free place on the board !&lt;br /&gt;
            // =&amp;gt; end of the game&lt;br /&gt;
            $this-&amp;gt;gamestate-&amp;gt;nextState( &#039;endGame&#039; );&lt;br /&gt;
            return ;&lt;br /&gt;
        }&lt;br /&gt;
        else if( ! isset( $player_to_discs[ $player_id ] ) )&lt;br /&gt;
        {&lt;br /&gt;
            // Active player has no more disc on the board =&amp;gt; he looses immediately&lt;br /&gt;
            $this-&amp;gt;gamestate-&amp;gt;nextState( &#039;endGame&#039; );&lt;br /&gt;
            return ;&lt;br /&gt;
        }&lt;br /&gt;
        &lt;br /&gt;
        // Can this player play?&lt;br /&gt;
&lt;br /&gt;
        $possibleMoves = $this-&amp;gt;getPossibleMoves( $player_id );&lt;br /&gt;
        if( count( $possibleMoves ) == 0 )&lt;br /&gt;
        {&lt;br /&gt;
&lt;br /&gt;
            // This player can&#039;t play&lt;br /&gt;
            // Can his opponent play ?&lt;br /&gt;
            $opponent_id = (int)$this-&amp;gt;getUniqueValueFromDb( &amp;quot;SELECT player_id FROM player WHERE player_id!=&#039;$player_id&#039; &amp;quot; );&lt;br /&gt;
            if( count( $this-&amp;gt;getPossibleMoves( $opponent_id ) ) == 0 )&lt;br /&gt;
            {&lt;br /&gt;
                // Nobody can move =&amp;gt; end of the game&lt;br /&gt;
                $this-&amp;gt;gamestate-&amp;gt;nextState( &#039;endGame&#039; );&lt;br /&gt;
            }&lt;br /&gt;
            else&lt;br /&gt;
            {            &lt;br /&gt;
                // =&amp;gt; pass his turn&lt;br /&gt;
                $this-&amp;gt;gamestate-&amp;gt;nextState( &#039;cantPlay&#039; );&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
        else&lt;br /&gt;
        {&lt;br /&gt;
            // This player can play. Give him some extra time&lt;br /&gt;
            $this-&amp;gt;giveExtraTime( $player_id );&lt;br /&gt;
            $this-&amp;gt;gamestate-&amp;gt;nextState( &#039;nextTurn&#039; );&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Now, when we play a token, the rules are checked and the token appears in the database.&lt;br /&gt;
&lt;br /&gt;
[[File:reversi9.jpg]]&lt;br /&gt;
&lt;br /&gt;
Of course, as we don&#039;t manage notifications on client side, we need to press F5 after each move to see the changes on the board.&lt;br /&gt;
&lt;br /&gt;
== Make the move appear automatically ==&lt;br /&gt;
&lt;br /&gt;
Now, what we have to do is process the notifications sent by the server and make the move appear on the interface.&lt;br /&gt;
&lt;br /&gt;
In our &amp;lt;code&amp;gt;setupNotifications&amp;lt;/code&amp;gt; method in &amp;lt;code&amp;gt;reversi.js&amp;lt;/code&amp;gt;, we register 2 methods for the 2 notifications we created at the previous step (&amp;lt;code&amp;gt;playDisc&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;turnOverDiscs&amp;lt;/code&amp;gt;):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
            const notifs = [&lt;br /&gt;
                [&#039;playDisc&#039;, 500],&lt;br /&gt;
                [&#039;turnOverDiscs&#039;, 1500],&lt;br /&gt;
                [&#039;newScores&#039;, 1],&lt;br /&gt;
            ];&lt;br /&gt;
    &lt;br /&gt;
            notifs.forEach((notif) =&amp;gt; {&lt;br /&gt;
                dojo.subscribe(notif[0], this, `notif_${notif[0]}`);&lt;br /&gt;
                this.notifqueue.setSynchronous(notif[0], notif[1]);&lt;br /&gt;
            });&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We will associate each of our 3 notifications with a method prefixed with &amp;lt;code&amp;gt;notif_&amp;lt;/code&amp;gt;. We also define these notifications as &amp;quot;synchronous&amp;quot;, with a duration in millisecond. It tells the user interface to wait some time after executing the notification, to let the animation end before starting the next notification. In our specific case, the animation will be the following:&lt;br /&gt;
* Make a disc slide from the player panel to its place on the board&lt;br /&gt;
* (wait 500ms)&lt;br /&gt;
* Make all turned over discs blink (and of course turned them over)&lt;br /&gt;
* (wait 1500ms)&lt;br /&gt;
* Update the player scores&lt;br /&gt;
* (no real delay on this one)&lt;br /&gt;
&lt;br /&gt;
The second part of the code is a generic thing to automatically bind the notifs we configured to the &amp;lt;code&amp;gt;notif_&amp;lt;notifName&amp;gt;&amp;lt;/code&amp;gt; functions we are about to create.&lt;br /&gt;
&lt;br /&gt;
Let&#039;s have a look now on the &amp;lt;code&amp;gt;playDisc&amp;lt;/code&amp;gt; notification handler method:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
notif_playDisc: function( notif )&lt;br /&gt;
{&lt;br /&gt;
    // Remove current possible moves (makes the board more clear)&lt;br /&gt;
    document.querySelectorAll(&#039;.possibleMove&#039;).forEach(div =&amp;gt; div.classList.remove(&#039;possibleMove&#039;));&lt;br /&gt;
&lt;br /&gt;
    this.addDiscOnBoard( notif.args.x, notif.args.y, notif.args.player_id );&lt;br /&gt;
},&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
No surprise here, we re-used some existing stuff to:&lt;br /&gt;
* Remove the highlighted squares.&lt;br /&gt;
* Add a new disc on board, coming from player panel.&lt;br /&gt;
&lt;br /&gt;
Now, here&#039;s the method that handles the &amp;lt;code&amp;gt;turnOverDiscs&amp;lt;/code&amp;gt; notification:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
notif_turnOverDiscs: function( notif )&lt;br /&gt;
{&lt;br /&gt;
    // Get the color of the player who is returning the discs&lt;br /&gt;
    var targetColor = this.gamedatas.players[ notif.args.player_id ].color;&lt;br /&gt;
&lt;br /&gt;
    // Made these discs blinking and set them to the specified color&lt;br /&gt;
    for( var i in notif.args.turnedOver )&lt;br /&gt;
    {&lt;br /&gt;
        var disc = notif.args.turnedOver[ i ];&lt;br /&gt;
        &lt;br /&gt;
        // Make the disc blink 2 times&lt;br /&gt;
        var anim = dojo.fx.chain( [&lt;br /&gt;
            dojo.fadeOut( { node: &#039;disc_&#039;+disc.x+&#039;&#039;+disc.y } ),&lt;br /&gt;
            dojo.fadeIn( { node: &#039;disc_&#039;+disc.x+&#039;&#039;+disc.y } ),&lt;br /&gt;
            dojo.fadeOut( { &lt;br /&gt;
                            node: &#039;disc_&#039;+disc.x+&#039;&#039;+disc.y,&lt;br /&gt;
                            onEnd: node =&amp;gt; $(node).dataset.color = targetColor,&lt;br /&gt;
                            } ),&lt;br /&gt;
            dojo.fadeIn( { node: &#039;disc_&#039;+disc.x+&#039;&#039;+disc.y  } )&lt;br /&gt;
                            &lt;br /&gt;
        ] ); // end of dojo.fx.chain&lt;br /&gt;
&lt;br /&gt;
        // ... and launch the animation&lt;br /&gt;
        anim.play();                &lt;br /&gt;
    }&lt;br /&gt;
},&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The list of the discs to be turned over has been made available by our server side code in &amp;lt;code&amp;gt;notif.args.turnedOver&amp;lt;/code&amp;gt; (see previous paragraph). We loop through all these discs, and create a complex animation using &amp;lt;code&amp;gt;dojo.Animation&amp;lt;/code&amp;gt; for each of them. The complete documentation on dojo animations [http://dojotoolkit.org/documentation/tutorials/1.6/animation/ can be found here].&lt;br /&gt;
&lt;br /&gt;
In few words: we create a chain of 4 animations to make the disc fade out, fade in, fade out again, and fade in again. At the end of the second fade out, we change the color of the disc. Finally, we launch the animation with &amp;lt;code&amp;gt;play()&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
And Also the notification to update the scores:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
notif_newScores: function( notif )&lt;br /&gt;
        {&lt;br /&gt;
            for( var player_id in notif.args.scores )&lt;br /&gt;
            {&lt;br /&gt;
                var newScore = notif.args.scores[ player_id ];&lt;br /&gt;
                this.scoreCtrl[ player_id ].toValue( newScore );&lt;br /&gt;
            }&lt;br /&gt;
        },&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Category:Studio]]&lt;/div&gt;</summary>
		<author><name>Sguzzer Gunayer</name></author>
	</entry>
	<entry>
		<id>https://en.doc.boardgamearena.com/index.php?title=Tutorial_reversi&amp;diff=22810</id>
		<title>Tutorial reversi</title>
		<link rel="alternate" type="text/html" href="https://en.doc.boardgamearena.com/index.php?title=Tutorial_reversi&amp;diff=22810"/>
		<updated>2024-09-29T08:54:45Z</updated>

		<summary type="html">&lt;p&gt;Sguzzer Gunayer: /* Build the grid of squares */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&#039;&#039;&#039;Check out an updated version&#039;&#039;&#039; of the [[BGA Type Safe Template: Reversi|Reversi Tutorial]] which uses the [[BGA Type Safe Template]]. {{Studio_Framework_Navigation}}&lt;br /&gt;
&lt;br /&gt;
== Introduction ==&lt;br /&gt;
&lt;br /&gt;
Using this tutorial, you can build a complete working game on the BGA environment: Reversi.&lt;br /&gt;
&lt;br /&gt;
Before you read this tutorial, you must:&lt;br /&gt;
* Read the overall presentations of the BGA Framework ([[Studio|see here]]).&lt;br /&gt;
* Know the [http://en.wikipedia.org/wiki/Reversi#Rules rules of Reversi].&lt;br /&gt;
* Know the languages used on BGA: PHP, SQL, HTML, CSS, Javascript&lt;br /&gt;
* &#039;&#039;&#039;Setup your development environment&#039;&#039;&#039; [http://en.doc.boardgamearena.com/First_steps_with_BGA_Studio First Steps with BGA Studio]&lt;br /&gt;
&lt;br /&gt;
== Create your first game ==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Note: you should already have created a project following instructions in [[First_steps_with_BGA_Studio#Create_a_new_game_project|Create a new game project]]. While you will find a &#039;&#039;&#039;reversi&#039;&#039;&#039; directory in your SFTP folder, do not use it for this tutorial. Instead, use the project you have created as an (empty) starting point.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
With the initial skeleton of code provided in your project, you can already start a game from the BGA Studio:&lt;br /&gt;
* Go to your [https://studio.boardgamearena.com/controlpanel studio Control panel], then Manage games and select your initial project. &#039;&#039;Note: there are warnings displayed about a missing BGG_ID and presentation text. You can ignore that for now.&#039;&#039;&lt;br /&gt;
* Click the Play link next to your project name. This will open the Play page and offer to create a new table for your project. &#039;&#039;Optional: click the Heart icon to add your project to your favorite games list.&#039;&#039;&lt;br /&gt;
* On the Play page, on the top of the page, make sure that your settings are &amp;quot;Simple game&amp;quot;, &amp;quot;Real time&amp;quot; and &amp;quot;Manual&amp;quot;.&lt;br /&gt;
* Click &amp;quot;Create table&amp;quot; to create a table of your project. &lt;br /&gt;
* For now, we are going to work with one player only, so use the (-) button to set the number of players to 1. Most of the time it is simpler to proceed with only one player during the early phase of development of your game, as it&#039;s easy and fast to start/stop games. If you choose to start with 2 players, you should see two names on the right: testdude0 and testdude1. To switch between them, press the red arrow button near their names; it will open another tab. This way you don&#039;t need to login and logout from multiple accounts.) &lt;br /&gt;
* Reminder: Always use the &amp;quot;Express Start&amp;quot; button to start the game.&lt;br /&gt;
&lt;br /&gt;
Thus, you can start a &amp;quot;Reversi&amp;quot; game, and arrive on a void, empty game. Yeah.&lt;br /&gt;
&lt;br /&gt;
End the game by clicking on the game options icon on the top right, and then on &amp;quot;Express Stop&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
== Editing the game information (Optional) ==&lt;br /&gt;
&lt;br /&gt;
This step is optional and will fix the warnings on the project page (missing BGG_ID and presentation).&lt;br /&gt;
&lt;br /&gt;
==== Edits to fix Errors ====&lt;br /&gt;
* Edit your local copy of the &amp;lt;code&amp;gt;gameinfos.inc.php&amp;lt;/code&amp;gt; file:&lt;br /&gt;
** Change the &amp;lt;code&amp;gt;bgg_id&amp;lt;/code&amp;gt; value from &amp;lt;code&amp;gt;0&amp;lt;/code&amp;gt; to &amp;lt;code&amp;gt;2389&amp;lt;/code&amp;gt; - that&#039;s around line 37.&lt;br /&gt;
** Add &amp;lt;code&amp;gt;1,&amp;lt;/code&amp;gt; to the players array - that&#039;s around line 41.&lt;br /&gt;
** Change the presentation array content - that&#039;s around line 134. Uncomment one line and change the text. Remove the final comma if you keep only one line!&lt;br /&gt;
* Upload the &amp;lt;code&amp;gt;gameinfos.inc.php&amp;lt;/code&amp;gt; file to the SFTP server (see [[First_steps_with_BGA_Studio#Connect_to_your_SFTP_folder|Connect to your SFTP folder]]).&lt;br /&gt;
&lt;br /&gt;
==== Test your Edits ====&lt;br /&gt;
* Go back to your project page, and in the &amp;quot;Game Information&amp;quot; section, click &amp;quot;Reload game informations&amp;quot;.&lt;br /&gt;
* Finally, refresh the project page in your browser (usually CTRL-F5).&lt;br /&gt;
&lt;br /&gt;
===== Not working? =====&lt;br /&gt;
Some changes will require bypassing the cache. It is often worth doing a hard refresh to make sure the&lt;br /&gt;
&lt;br /&gt;
Sometimes the cache will keep your changes from showing. Since this is a possibility, it will be useful to know how to bypass the cache. To do so you may manually clear cache or use a shortcut to refresh and ignore the cached version of the page. Here&#039;s how&lt;br /&gt;
&lt;br /&gt;
====== Windows ======&lt;br /&gt;
Chrome, Firefox, or Edge: Press &amp;lt;code&amp;gt;Ctrl+F5&amp;lt;/code&amp;gt; or &amp;lt;code&amp;gt;Shift+F5&amp;lt;/code&amp;gt; or &amp;lt;code&amp;gt;Ctrl+Shift+R&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====== Mac ======&lt;br /&gt;
Chrome or Firefox: Press &amp;lt;code&amp;gt;Shift+Command+R&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Safari for Mac: Press &amp;lt;code&amp;gt;Command+Option+E&amp;lt;/code&amp;gt; to empty the cache, then hold down Shift and click Reload in the toolbar&lt;br /&gt;
&lt;br /&gt;
== Make it look like Reversi ==&lt;br /&gt;
&lt;br /&gt;
Let&#039;s start with the board. This will give you a good idea of how things will look and where tokens should go.&lt;br /&gt;
&lt;br /&gt;
Be careful designing the layout of your game: you must always keep in mind that players with a 1024px screen width must be able to play. Usually, it means that the width of the play area can be 750px (in the worst case).&lt;br /&gt;
&lt;br /&gt;
For Reversi, it&#039;s useless to have a 750x750px board - much too big, so we chose this one which fit perfectly (536x528):&lt;br /&gt;
&lt;br /&gt;
[[File:Board.jpg]]&lt;br /&gt;
&lt;br /&gt;
Note that we are using a jpg file. Jpg files are lighter than png, so they are faster to load. Later, we are going to use PNGs for tokens because they allow for transparency.&lt;br /&gt;
&lt;br /&gt;
==== Add the board ====&lt;br /&gt;
use lowercase file names&lt;br /&gt;
* upload &amp;lt;code&amp;gt;board.jpg&amp;lt;/code&amp;gt; in your &amp;lt;code&amp;gt;img/&amp;lt;/code&amp;gt; directory. &lt;br /&gt;
* edit &amp;lt;code&amp;gt;reversi_reversi.tpl&amp;lt;/code&amp;gt; to add a &amp;lt;code&amp;gt;div&amp;lt;/code&amp;gt; for your board.&lt;br /&gt;
&lt;br /&gt;
Note: If you are building this game by following the tutorial, you will have a different project name than &amp;lt;code&amp;gt;reversi&amp;lt;/code&amp;gt; (i.e. &amp;lt;code&amp;gt;mygame_mygame.tpl&amp;lt;/code&amp;gt;). The file names in your project will be different than shown in this tutorial, replacing &amp;lt;code&amp;gt;reversi&amp;lt;/code&amp;gt; with your project name. Be sure that any code (other than comments) that references &amp;lt;code&amp;gt;reversi&amp;lt;/code&amp;gt; is changed to your actual project name.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;div id=&amp;quot;board&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* edit your &amp;lt;code&amp;gt;reversi.css&amp;lt;/code&amp;gt; file to transform it into a visible board:&lt;br /&gt;
&lt;br /&gt;
 #board {&lt;br /&gt;
    width: 536px;&lt;br /&gt;
    height: 528px;&lt;br /&gt;
    background-image: url(&#039;img/board.jpg&#039;);&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Important: refresh your page.&#039;&#039;&#039; Here&#039;s your board:[[File:reversi1.jpg]]&lt;br /&gt;
&lt;br /&gt;
If the board does not appear, refresh the page (always do this when you update the CSS file), and check the image filename. Remember file names are case sensitive!&lt;br /&gt;
&lt;br /&gt;
==== Code the Grid ====&lt;br /&gt;
Now, we need to create some invisible HTML elements where squares are. These elements will be used as position references for the white and black tokens. &lt;br /&gt;
&lt;br /&gt;
===== Build the grid of squares =====&lt;br /&gt;
The board is 8 squares by 8 squares. This means we need 64 squares. To avoid writing 64 individual &amp;lt;code&amp;gt;div&amp;lt;/code&amp;gt; elements on our template, we are going to generate the squares on JS &amp;lt;code&amp;gt;setup&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
We&#039;ll do this in our Javascript &amp;lt;code&amp;gt;setup&amp;lt;/code&amp;gt; method under &amp;lt;code&amp;gt;// TODO: Set up your game interface here, according to &amp;quot;gamedatas&amp;quot;&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
const board = document.getElementById(&#039;board&#039;);&lt;br /&gt;
const hor_scale = 64.8;&lt;br /&gt;
const ver_scale = 64.4;&lt;br /&gt;
for (let x=1; x&amp;lt;=8; x++) {&lt;br /&gt;
    for (let y=1; y&amp;lt;=8; y++) {&lt;br /&gt;
        const left = Math.round((x - 1) * hor_scale + 10);&lt;br /&gt;
        const top = Math.round((y - 1) * ver_scale + 7);&lt;br /&gt;
        // we use afterbegin to make sure squares are placed before discs&lt;br /&gt;
        board.insertAdjacentHTML(`afterbegin`, `&amp;lt;div id=&amp;quot;square_${x}_${y}&amp;quot; class=&amp;quot;square&amp;quot; style=&amp;quot;left: ${left}px; top: ${top}px;&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;`);&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note: as you can see, squares in our &amp;lt;code&amp;gt;board.jpg&amp;lt;/code&amp;gt; files do not have an exact width/height in pixels, and that&#039;s the reason we are using floating point numbers here.&lt;br /&gt;
&lt;br /&gt;
===== Style Those Squares =====&lt;br /&gt;
Now, to finish our work and check if everything works fine, we are going to style our square a little bit in our CSS stylesheet:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#board {&lt;br /&gt;
    width: 536px;&lt;br /&gt;
    height: 528px;&lt;br /&gt;
    background-image: url(&#039;img/board.jpg&#039;);&lt;br /&gt;
    position: relative;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.square {&lt;br /&gt;
    width: 62px;&lt;br /&gt;
    height: 62px;&lt;br /&gt;
    position: absolute;&lt;br /&gt;
    background-color: red;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Explanations:&lt;br /&gt;
* With &amp;quot;&amp;lt;code&amp;gt;position: relative&amp;lt;/code&amp;gt;&amp;quot; on board, we ensure square elements are positioned relatively to board.&lt;br /&gt;
* &amp;lt;code&amp;gt;background-color: red;&amp;lt;/code&amp;gt; is used for testing. This allows us to see the invisible elements. (You could instead do something like &amp;lt;code&amp;gt;outline: 2px solid orange;&amp;lt;/code&amp;gt; have fun and be creative)&lt;br /&gt;
&lt;br /&gt;
Let&#039;s refresh and check our (beautiful) squares:&lt;br /&gt;
&lt;br /&gt;
[[File:reversi2.jpg]]&lt;br /&gt;
&lt;br /&gt;
Now that you know the squares are there, you can remove the test line &amp;lt;code&amp;gt;background-color: red;&amp;lt;/code&amp;gt;  from your &amp;lt;code&amp;gt;.square&amp;lt;/code&amp;gt; class in the CSS stylesheet.&lt;br /&gt;
&lt;br /&gt;
===== Not Working? =====&lt;br /&gt;
If the styled squares do not appear, inspect and check your css (Chrome DevTools: Application &amp;gt; Frames &amp;gt; top &amp;gt; Stylesheets &amp;gt; reversi.css). &lt;br /&gt;
&lt;br /&gt;
== The Tokens ==&lt;br /&gt;
&lt;br /&gt;
Now, our board is ready for some tokens!&lt;br /&gt;
&lt;br /&gt;
[Note: Throughout this tutorial, sometimes &amp;quot;tokens&amp;quot; is used, and sometimes &amp;quot;discs&amp;quot; is used. They are often swapped if you&#039;re looking at code in the reversi example project.]&lt;br /&gt;
&lt;br /&gt;
=== Build the Token ===&lt;br /&gt;
There are quite a few steps before the tokens will appear. You may be used to testing after every change, but that won&#039;t work well here. The token will &#039;&#039;&#039;not&#039;&#039;&#039; show until you have add styles to the css, js template to the tpl, utility method in the js,  adjusted the php file, and added the token to the board in the js file.&lt;br /&gt;
&lt;br /&gt;
==== HTML in the .tpl file ====&lt;br /&gt;
At first, we introduce a new &#039;div&#039; element as a child of &amp;quot;board&amp;quot; to host all these tokens (in our template):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;div id=&amp;quot;board&amp;quot;&amp;gt;&lt;br /&gt;
    &lt;br /&gt;
    &amp;lt;div id=&amp;quot;discs&amp;quot;&amp;gt;&lt;br /&gt;
    &amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note: &amp;lt;code&amp;gt;discs&amp;lt;/code&amp;gt; is plural. This div will be used to hold the token divs. Shortly, we will use javascript to add individual tokens to the board.&lt;br /&gt;
&lt;br /&gt;
==== Add Token to img directory ====&lt;br /&gt;
Here&#039;s a new piece of art with the tokens. We need transparency here so we are using a png file:&lt;br /&gt;
&lt;br /&gt;
[[File:tokens.png]]&lt;br /&gt;
&lt;br /&gt;
Upload this image file &amp;lt;code&amp;gt;tokens.png&amp;lt;/code&amp;gt; in your &amp;lt;code&amp;gt;img/&amp;lt;/code&amp;gt; directory.&lt;br /&gt;
&lt;br /&gt;
Important Fun Fact: we are using ONE file for both tokens. It is really important to use a minimum number of graphic files for your game. This is called the &amp;quot;CSS sprite&amp;quot; technique, because it makes the game load faster and more reliable. [http://www.w3schools.com/css/css_image_sprites.asp Read more about CSS sprites].&lt;br /&gt;
&lt;br /&gt;
==== Style the Tokens in .css file ====&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
.disc {&lt;br /&gt;
    width: 56px;&lt;br /&gt;
    height: 56px;&lt;br /&gt;
    position: absolute;&lt;br /&gt;
    background-image: url(&#039;img/tokens.png&#039;);&lt;br /&gt;
    background-size: auto 100%;&lt;br /&gt;
}&lt;br /&gt;
.disc[data-color=&amp;quot;ffffff&amp;quot;] { background-position-x: 0%; }&lt;br /&gt;
.disc[data-color=&amp;quot;000000&amp;quot;] { background-position-x: 100%; }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
With this CSS code, we can set and change the token color by changing the &amp;lt;code&amp;gt;data-color&amp;lt;/code&amp;gt; attribute. Using data instead of a class ensures it can be only one of them (the disc cannot be black and white at the same time).&lt;br /&gt;
&lt;br /&gt;
Note the &amp;quot;&amp;lt;code&amp;gt;position: absolute&amp;lt;/code&amp;gt;&amp;quot; which allows us to position tokens on the board and make them &amp;quot;slide&amp;quot; to their positions.&lt;br /&gt;
&lt;br /&gt;
==== Add Token Utility Method in .js file ====&lt;br /&gt;
Now, let&#039;s make the first token appear on our board. Tokens are not visible at the beginning of the game: they appear dynamically during the game. For this reason, we are going to make them appear from our Javascript code, using a template string&lt;br /&gt;
&lt;br /&gt;
Let&#039;s create a method in our Javascript code (in the &amp;lt;code&amp;gt;reversi.js&amp;lt;/code&amp;gt; file) that will make a token appear on the board, using this template. Add under the section &amp;lt;code&amp;gt;//// Utility methods&amp;lt;/code&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
addDiscOnBoard: function( x, y, player )&lt;br /&gt;
{&lt;br /&gt;
    var color = this.gamedatas.players[ player ].color;&lt;br /&gt;
    &lt;br /&gt;
    document.getElementById(&#039;discs&#039;).insertAdjacentHTML(&#039;beforeend&#039;, `&amp;lt;div class=&amp;quot;disc&amp;quot; data-color=&amp;quot;${color}&amp;quot; id=&amp;quot;disc_${x}${y}&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;`);&lt;br /&gt;
    &lt;br /&gt;
    this.placeOnObject( `disc_${x}${y}`, &#039;overall_player_board_&#039;+player );&lt;br /&gt;
    this.slideToObject( `disc_${x}${y}`, &#039;square_&#039;+x+&#039;_&#039;+y ).play();&lt;br /&gt;
},  &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===== Utility Method Explanation =====&lt;br /&gt;
* with &amp;lt;code&amp;gt;element.insertAdjacentHTML&amp;lt;/code&amp;gt; method, we create a HTML piece of code and insert it as a new child of &amp;lt;code&amp;gt;tokens&amp;lt;/code&amp;gt; div element.&lt;br /&gt;
* with &amp;lt;code&amp;gt;this.placeOnObject&amp;lt;/code&amp;gt; BGA method, we place this element over the panel of some player. &lt;br /&gt;
* Immediately after, using &amp;lt;code&amp;gt;this.slideToObject&amp;lt;/code&amp;gt; BGA method, we make the token slide to the &amp;lt;code&amp;gt;square&amp;lt;/code&amp;gt; element, its final destination.&lt;br /&gt;
* &amp;lt;code&amp;gt;&#039;overall_player_board_&#039;+player&amp;lt;/code&amp;gt; refers to the div element that contains each player&#039;s information and avatar. By initially placing the token here, it gives the effect that the player&#039;s avatar is throwing the token onto the board.&lt;br /&gt;
&lt;br /&gt;
Note: don&#039;t forget to call the &amp;lt;code&amp;gt;play()&amp;lt;/code&amp;gt;, otherwise the token will remain at its original location.&lt;br /&gt;
&lt;br /&gt;
Note: during this process, the parent of the new token HTML element will stay &amp;lt;code&amp;gt;tokens&amp;lt;/code&amp;gt;. &amp;lt;code&amp;gt;placeOnObject&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;slideToObject&amp;lt;/code&amp;gt; methods are &#039;&#039;only&#039;&#039; moving the position of elements on screen, and they are &#039;&#039;not&#039;&#039; modifying the HTML tree.&lt;br /&gt;
&lt;br /&gt;
==== Set Token Colors in setupNewGame in .game.php file ====&lt;br /&gt;
Before we can show a token, we need to set the player colors in the &amp;lt;code&amp;gt;setupNewGame&amp;lt;/code&amp;gt; function in &amp;lt;code&amp;gt;reversi.game.php&amp;lt;/code&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
Replace &amp;lt;code&amp;gt;$default_colors = $gameinfos[&#039;player_colors&#039;];&amp;lt;/code&amp;gt; with the following line:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$default_colors = array( &amp;quot;ffffff&amp;quot;, &amp;quot;000000&amp;quot; );&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note: A few lines below, you may have to remove the line &amp;lt;code&amp;gt;this-&amp;gt;reattributeColorsBasedOnPreferences( $players, $gameinfos[&#039;player_colors&#039;] );&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Test the Token ===&lt;br /&gt;
Now, to test if everything works fine&lt;br /&gt;
&lt;br /&gt;
==== &amp;lt;code&amp;gt;addTokenOnBoard()&amp;lt;/code&amp;gt; in .js file to Test ====&lt;br /&gt;
In &amp;lt;code&amp;gt;reversi.js&amp;lt;/code&amp;gt;, in &amp;lt;code&amp;gt;setup: function&amp;lt;/code&amp;gt;, under the code we added to generate the squares. &lt;br /&gt;
 this.addDiscOnBoard( 2, 2, this.player_id );&lt;br /&gt;
Now restart the game.&lt;br /&gt;
&lt;br /&gt;
A token should appear and slide immediately to its position, like this:&lt;br /&gt;
&lt;br /&gt;
[[File:reversi3.jpg]]&lt;br /&gt;
&lt;br /&gt;
== The database ==&lt;br /&gt;
&lt;br /&gt;
We did most of the client-side programming, so let&#039;s have a look on the other side now. To design the database model of our game, you will need to access the database. You won&#039;t need to do anything in database UI, yet.&lt;br /&gt;
&lt;br /&gt;
=== Accessing the Database ===&lt;br /&gt;
To access the database, start a game, then click &amp;quot;Go to game database&amp;quot; link at the bottom of our game, to access the database directly with a PhpMyAdmin instance.&lt;br /&gt;
&lt;br /&gt;
After the first time you&#039;ve access the database, you could skip opening a game and instead, go to https://studio.boardgamearena.com/db/ . Your PhpMyAdmin username/password is in your welcome email.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note&#039;&#039;&#039;: do not remove existing tables&lt;br /&gt;
&lt;br /&gt;
=== Create Table in .sql file ===&lt;br /&gt;
Now, you are able to create the table(s) you need for your game, and report every SQL command used in your &amp;lt;code&amp;gt;dbmodel.sql&amp;lt;/code&amp;gt; file. &lt;br /&gt;
&lt;br /&gt;
The database model of Reversi is short: just one table with the squares of the board. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
CREATE TABLE IF NOT EXISTS `board` (&lt;br /&gt;
  `board_x` smallint(5) unsigned NOT NULL,&lt;br /&gt;
  `board_y` smallint(5) unsigned NOT NULL,&lt;br /&gt;
  `board_player` int(10) unsigned DEFAULT NULL,&lt;br /&gt;
  PRIMARY KEY (`board_x`,`board_y`)&lt;br /&gt;
) ENGINE=InnoDB DEFAULT CHARSET=utf8;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Add the above SQL to &amp;lt;code&amp;gt;dbmodel.sql&amp;lt;/code&amp;gt;. Pay special attention to the backtick &amp;lt;code&amp;gt;`&amp;lt;/code&amp;gt; character vs. the single quote &amp;lt;code&amp;gt;&#039;&amp;lt;/code&amp;gt; when working with SQL. &lt;br /&gt;
&lt;br /&gt;
=== Test the Table ===&lt;br /&gt;
Now, a new database with a &amp;lt;code&amp;gt;board&amp;lt;/code&amp;gt; table will be created each time we start a Reversi game. This is why after modifying our &amp;lt;code&amp;gt;dbmodel.sql&amp;lt;/code&amp;gt; it&#039;s a good time to stop your current game &amp;amp; start a new game.&lt;br /&gt;
&lt;br /&gt;
Start a new game and verify a table is created.&lt;br /&gt;
&lt;br /&gt;
== Setup the initial game position ==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note&#039;&#039;&#039;: From now on, you must launch the game with &#039;&#039;&#039;two players&#039;&#039;&#039; to get two &amp;lt;code&amp;gt;player_id&amp;lt;/code&amp;gt;s within the database. Otherwise, the game will crash.&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;setupNewGame&amp;lt;/code&amp;gt; method of our &amp;lt;code&amp;gt;reversi.game.php&amp;lt;/code&amp;gt; is called during initial setup. This initializes our data and places the starting tokens on the board. At the beginning of the game, there should be 4 tokens on the board.&lt;br /&gt;
&lt;br /&gt;
=== Initialize the Board in .game.php file ===&lt;br /&gt;
Under &amp;lt;code&amp;gt;// TODO: setup the initial game situation here&amp;lt;/code&amp;gt;, initialize the board&amp;lt;pre&amp;gt;&lt;br /&gt;
// Init the board&lt;br /&gt;
$sql = &amp;quot;INSERT INTO board (board_x,board_y,board_player) VALUES &amp;quot;;&lt;br /&gt;
$sql_values = array();&lt;br /&gt;
list( $blackplayer_id, $whiteplayer_id ) = array_keys( $players );&lt;br /&gt;
for( $x=1; $x&amp;lt;=8; $x++ )&lt;br /&gt;
{&lt;br /&gt;
	for( $y=1; $y&amp;lt;=8; $y++ )&lt;br /&gt;
	{&lt;br /&gt;
	$token_value = &amp;quot;NULL&amp;quot;;&lt;br /&gt;
	if( ($x==4 &amp;amp;&amp;amp; $y==4) || ($x==5 &amp;amp;&amp;amp; $y==5) )  // Initial positions of white player&lt;br /&gt;
	$token_value = &amp;quot;&#039;$whiteplayer_id&#039;&amp;quot;;&lt;br /&gt;
	else if( ($x==4 &amp;amp;&amp;amp; $y==5) || ($x==5 &amp;amp;&amp;amp; $y==4) )  // Initial positions of black player&lt;br /&gt;
	$token_value = &amp;quot;&#039;$blackplayer_id&#039;&amp;quot;;&lt;br /&gt;
                    &lt;br /&gt;
	$sql_values[] = &amp;quot;(&#039;$x&#039;,&#039;$y&#039;,$token_value)&amp;quot;;&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
$sql .= implode( &#039;,&#039;, $sql_values );&lt;br /&gt;
$this-&amp;gt;DbQuery( $sql );&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Board Initialization Explanation ====&lt;br /&gt;
&lt;br /&gt;
* We create one table entry for each square, with a &amp;lt;code&amp;gt;NULL&amp;lt;/code&amp;gt; value which means &amp;quot;empty square&amp;quot;&lt;br /&gt;
* On 4 of the squares, we place an initial token.&lt;br /&gt;
&lt;br /&gt;
After this, we set &amp;lt;code&amp;gt;activeNextPlayer&amp;lt;/code&amp;gt; to make the first player active at the beginning of the game (this line is already present in the default code template).&lt;br /&gt;
&lt;br /&gt;
If you didn&#039;t do it earlier, you need to remove the call to &amp;lt;code&amp;gt;this-&amp;gt;reattributeColorsBasedOnPreferences()&amp;lt;/code&amp;gt; in &amp;lt;code&amp;gt;SetupNewGame()&amp;lt;/code&amp;gt;. If you don&#039;t, player color preferences will try (and fail) to override the two colors supported here.&lt;br /&gt;
&lt;br /&gt;
=== Show the Initial Token Setup ===&lt;br /&gt;
Now, we need to make these tokens appear on the client side. The first step is to return the token positions with our &amp;lt;code&amp;gt;getAllDatas()&amp;lt;/code&amp;gt; PHP method. &amp;lt;code&amp;gt;getAllDatas()&amp;lt;/code&amp;gt; is called during each page reload.&lt;br /&gt;
&lt;br /&gt;
In the &amp;lt;code&amp;gt;getAllDatas()&amp;lt;/code&amp;gt; method, after &amp;lt;code&amp;gt;// TODO: Gather all information about current game situation (visible by player $current_player_id)&amp;lt;/code&amp;gt;, add the following lines:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
// Get reversi board token&lt;br /&gt;
$result[&#039;board&#039;] = self::getObjectListFromDB( &amp;quot;SELECT board_x x, board_y y, board_player player&lt;br /&gt;
	FROM board&lt;br /&gt;
	WHERE board_player IS NOT NULL&amp;quot; );&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Next, you may need to modify the query that gets player information to also get the player&#039;s colors. This is in the variable &amp;lt;code&amp;gt;$sql&amp;lt;/code&amp;gt;, above the lines you just inserted in &amp;lt;code&amp;gt;getAllDatas()&amp;lt;/code&amp;gt;. Below is what the line will look like. Notice how we&#039;ve added &amp;lt;code&amp;gt;player_color color&amp;lt;/code&amp;gt; to the sql query.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$sql = &amp;quot;SELECT player_id id, player_score score, player_color color FROM player &amp;quot;;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We are using the BGA framework&#039;s &amp;lt;code&amp;gt;getObjectListFromDB()&amp;lt;/code&amp;gt; that formats the result of this SQL query in a PHP array with x, y and player attributes. We add it to the result associative array with the key &amp;lt;code&amp;gt;board&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Last, we process this array client side. Let&#039;s place a token on the board for each array item. We&#039;ll do this in our Javascript &amp;lt;code&amp;gt;setup&amp;lt;/code&amp;gt; method under the code we added to generate the squares. &lt;br /&gt;
&lt;br /&gt;
This will result in a removal or edit of the previously added line &amp;lt;code&amp;gt;this.addDiscOnBoard(2, 2, this.player_id);&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
for( var i in gamedatas.board )&lt;br /&gt;
{&lt;br /&gt;
    var square = gamedatas.board[i];&lt;br /&gt;
    &lt;br /&gt;
    if( square.player !== null )&lt;br /&gt;
    {&lt;br /&gt;
        this.addDiscOnBoard( square.x, square.y, square.player );&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;board&amp;lt;/code&amp;gt; entry created in &amp;lt;code&amp;gt;getAllDatas()&amp;lt;/code&amp;gt; is used here as &amp;lt;code&amp;gt;gamedatas.board&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Test the Game Start ===&lt;br /&gt;
Reload... and here we are:&lt;br /&gt;
&lt;br /&gt;
[[File:reversi5.jpg]]&lt;br /&gt;
&lt;br /&gt;
It starts to feel like Reversi here...&lt;br /&gt;
&lt;br /&gt;
== The game state machine ==&lt;br /&gt;
&lt;br /&gt;
Stop your game, again. You&#039;re about to start the core game logic.&lt;br /&gt;
&lt;br /&gt;
You already read [http://www.slideshare.net/boardgamearena/bga-studio-focus-on-bga-game-state-machine Focus on BGA game state machine], so you know that this is the heart of your game logic. For reversi, it&#039;s relatively simple. Here&#039;s a diagram of our game state machine:&lt;br /&gt;
&lt;br /&gt;
[[File:reversi6.jpg]]&lt;br /&gt;
&lt;br /&gt;
=== Build your States ===&lt;br /&gt;
And here&#039;s our &amp;lt;code&amp;gt;states.inc.php&amp;lt;/code&amp;gt;, according to this diagram:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$machinestates = array(&lt;br /&gt;
&lt;br /&gt;
    ST_BGA_GAME_SETUP =&amp;gt; array(&lt;br /&gt;
        &amp;quot;name&amp;quot; =&amp;gt; &amp;quot;gameSetup&amp;quot;,&lt;br /&gt;
        &amp;quot;description&amp;quot; =&amp;gt; clienttranslate(&amp;quot;Game setup&amp;quot;),&lt;br /&gt;
        &amp;quot;type&amp;quot; =&amp;gt; &amp;quot;manager&amp;quot;,&lt;br /&gt;
        &amp;quot;action&amp;quot; =&amp;gt; &amp;quot;stGameSetup&amp;quot;,&lt;br /&gt;
        &amp;quot;transitions&amp;quot; =&amp;gt; array( &amp;quot;&amp;quot; =&amp;gt; ST_PLAYER_PLAY_DISC )&lt;br /&gt;
    ),&lt;br /&gt;
    &lt;br /&gt;
    ST_PLAYER_PLAY_DISC =&amp;gt; array(&lt;br /&gt;
        &amp;quot;name&amp;quot; =&amp;gt; &amp;quot;playerTurn&amp;quot;,&lt;br /&gt;
		&amp;quot;description&amp;quot; =&amp;gt; clienttranslate(&#039;${actplayer} must play a disc&#039;),&lt;br /&gt;
		&amp;quot;descriptionmyturn&amp;quot; =&amp;gt; clienttranslate(&#039;${you} must play a disc&#039;),&lt;br /&gt;
        &amp;quot;type&amp;quot; =&amp;gt; &amp;quot;activeplayer&amp;quot;,&lt;br /&gt;
        &amp;quot;args&amp;quot; =&amp;gt; &amp;quot;argPlayerTurn&amp;quot;,&lt;br /&gt;
        &amp;quot;possibleactions&amp;quot; =&amp;gt; array( &#039;actPlayDisc&#039; ),&lt;br /&gt;
        &amp;quot;transitions&amp;quot; =&amp;gt; array( &amp;quot;playDisc&amp;quot; =&amp;gt; ST_NEXT_PLAYER, &amp;quot;zombiePass&amp;quot; =&amp;gt; ST_NEXT_PLAYER )&lt;br /&gt;
    ),&lt;br /&gt;
    &lt;br /&gt;
    ST_NEXT_PLAYER =&amp;gt; array(&lt;br /&gt;
        &amp;quot;name&amp;quot; =&amp;gt; &amp;quot;nextPlayer&amp;quot;,&lt;br /&gt;
        &amp;quot;type&amp;quot; =&amp;gt; &amp;quot;game&amp;quot;,&lt;br /&gt;
        &amp;quot;action&amp;quot; =&amp;gt; &amp;quot;stNextPlayer&amp;quot;,&lt;br /&gt;
        &amp;quot;updateGameProgression&amp;quot; =&amp;gt; true,        &lt;br /&gt;
        &amp;quot;transitions&amp;quot; =&amp;gt; array( &amp;quot;nextTurn&amp;quot; =&amp;gt; ST_PLAYER_PLAY_DISC, &amp;quot;cantPlay&amp;quot; =&amp;gt; ST_NEXT_PLAYER, &amp;quot;endGame&amp;quot; =&amp;gt; ST_END_GAME )&lt;br /&gt;
    ),&lt;br /&gt;
   &lt;br /&gt;
    ST_END_GAME =&amp;gt; array(&lt;br /&gt;
        &amp;quot;name&amp;quot; =&amp;gt; &amp;quot;gameEnd&amp;quot;,&lt;br /&gt;
        &amp;quot;description&amp;quot; =&amp;gt; clienttranslate(&amp;quot;End of game&amp;quot;),&lt;br /&gt;
        &amp;quot;type&amp;quot; =&amp;gt; &amp;quot;manager&amp;quot;,&lt;br /&gt;
        &amp;quot;action&amp;quot; =&amp;gt; &amp;quot;stGameEnd&amp;quot;,&lt;br /&gt;
        &amp;quot;args&amp;quot; =&amp;gt; &amp;quot;argGameEnd&amp;quot;&lt;br /&gt;
    )&lt;br /&gt;
&lt;br /&gt;
);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We used constants to give an index to the different states. This is to avoid mistakes when we reuse these indexes on the transitions array.&lt;br /&gt;
&lt;br /&gt;
Let&#039;s create a file you&#039;ll put in &amp;lt;code&amp;gt;modules/php/constants.inc.php&amp;lt;/code&amp;gt; :&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;?php&lt;br /&gt;
&lt;br /&gt;
/*&lt;br /&gt;
 * State constants&lt;br /&gt;
 */&lt;br /&gt;
const ST_BGA_GAME_SETUP = 1;&lt;br /&gt;
&lt;br /&gt;
const ST_PLAYER_PLAY_DISC = 10;&lt;br /&gt;
const ST_NEXT_PLAYER = 11;&lt;br /&gt;
&lt;br /&gt;
const ST_END_GAME = 99;&lt;br /&gt;
&lt;br /&gt;
?&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You will also need to add &amp;lt;code&amp;gt;require_once(&amp;quot;modules/php/constants.inc.php&amp;quot;);&amp;lt;/code&amp;gt; at the beginning of the state.inc.php to load these constants.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Now, in &amp;lt;code&amp;gt;reversi.game.php&amp;lt;/code&amp;gt; let&#039;s create the methods that are declared in this game states description file:&lt;br /&gt;
* &amp;lt;code&amp;gt;argPlayerTurn&amp;lt;/code&amp;gt;: referenced in the &amp;lt;code&amp;gt;args&amp;lt;/code&amp;gt; property of the &amp;lt;code&amp;gt;playerTurn&amp;lt;/code&amp;gt; state; this is the name of the method to call to retrieve arguments for this gamestate. Arguments are sent to the client side to be used on &amp;lt;code&amp;gt;onEnteringState&amp;lt;/code&amp;gt; or to set arguments in the gamestate description.&lt;br /&gt;
* &amp;lt;code&amp;gt;stNextPlayer&amp;lt;/code&amp;gt;: referenced in the &amp;lt;code&amp;gt;action&amp;lt;/code&amp;gt; property of the &amp;lt;code&amp;gt;nextPlayer&amp;lt;/code&amp;gt; state; this is the name of the method to call when this game state become the current game state.&lt;br /&gt;
&lt;br /&gt;
=== Test Your States ===&lt;br /&gt;
... and start a new Reversi game.&lt;br /&gt;
&lt;br /&gt;
As you can see on the screen capture below, the BGA framework makes the game jump to our first game state &amp;lt;code&amp;gt;playerTurn&amp;lt;/code&amp;gt; right after the initial setup. That&#039;s why the status bar contains the description of &amp;lt;code&amp;gt;playerTurn&amp;lt;/code&amp;gt; state (&amp;quot;XXXX must play a disc&amp;quot;):&lt;br /&gt;
&lt;br /&gt;
[[File:reversi7.jpg]]&lt;br /&gt;
&lt;br /&gt;
== The rules ==&lt;br /&gt;
&lt;br /&gt;
We will use the &amp;lt;code&amp;gt;getPossibleMoves&amp;lt;/code&amp;gt; PHP method to:&lt;br /&gt;
* Indicate to the current player where she is allowed to play by returning a list of coordinates&lt;br /&gt;
* Check if the player has the right to play in the spot they choose&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;&lt;br /&gt;
Example of getPossibleMoves here https://gist.github.com/leocaseiro/a8bc2851bd0caddd06685b5035937d15&lt;br /&gt;
&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This is pure PHP programming here, and there are no special things from the BGA framework that can be used. This is why we won&#039;t go into details here. The overall idea is:&lt;br /&gt;
* Create a &amp;lt;code&amp;gt;getTurnedOverDiscs(x,y)&amp;lt;/code&amp;gt; method that returns coordinates of discs that would be turned over if a token would be played at &amp;lt;code&amp;gt;x&amp;lt;/code&amp;gt;,&amp;lt;code&amp;gt;y&amp;lt;/code&amp;gt;.&lt;br /&gt;
* Loop through all free squares of the board and call the &amp;lt;code&amp;gt;getTurnedOverDiscs&amp;lt;/code&amp;gt; method on each of them. If at least 1 token is turned over, this is a valid move.&lt;br /&gt;
&lt;br /&gt;
IMPORTANT: Making a database query is slow! Please don&#039;t load the entire game board with a SQL query multiple times. In our implementation, we load the entire board once at the beginning of &amp;lt;code&amp;gt;getPossibleMoves&amp;lt;/code&amp;gt;, and then pass the board as an argument to all methods.&lt;br /&gt;
&lt;br /&gt;
If you want to look into details, please look at the &amp;quot;utility method&amp;quot; sections of &amp;lt;code&amp;gt;reversi.game.php&amp;lt;/code&amp;gt;. If building the tutorial yourself, copy the functions under &amp;quot;Utility functions&amp;quot; comment from the Reversi tutorial.&lt;br /&gt;
&lt;br /&gt;
== Display allowed moves ==&lt;br /&gt;
&lt;br /&gt;
Now we want to highlight the squares where the player can place a disc.&lt;br /&gt;
&lt;br /&gt;
To do this, we add a &amp;lt;code&amp;gt;argPlayerTurn&amp;lt;/code&amp;gt; method in &amp;lt;code&amp;gt;reversi.game.php&amp;lt;/code&amp;gt;. This method is called on the server each time we enter into &amp;lt;code&amp;gt;playerTurn&amp;lt;/code&amp;gt; game state, and its result is transferred automatically to the client-side:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
function argPlayerTurn(): array&lt;br /&gt;
{&lt;br /&gt;
    return [&lt;br /&gt;
        &#039;possibleMoves&#039; =&amp;gt; $this-&amp;gt;getPossibleMoves( intval($this-&amp;gt;getActivePlayerId()) )&lt;br /&gt;
    ];&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We use the &amp;lt;code&amp;gt;getPossibleMoves&amp;lt;/code&amp;gt; method we just developed.&lt;br /&gt;
&lt;br /&gt;
Each time we enter into a new game state, we use the &amp;lt;code&amp;gt;onEnteringState&amp;lt;/code&amp;gt; Javascript method (in the &amp;lt;code&amp;gt;reversi.js&amp;lt;/code&amp;gt; file, under &amp;quot;Game &amp;amp; client states&amp;quot;). This lets us use the data returned by the method above on the client side.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        onEnteringState: function( stateName, args )&lt;br /&gt;
        {&lt;br /&gt;
           console.log( &#039;Entering state: &#039;+stateName );&lt;br /&gt;
            &lt;br /&gt;
            switch( stateName )&lt;br /&gt;
            {&lt;br /&gt;
            case &#039;playerTurn&#039;:&lt;br /&gt;
                this.updatePossibleMoves( args.args.possibleMoves );&lt;br /&gt;
                break;&lt;br /&gt;
            }&lt;br /&gt;
        },&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
So, when we enter into &amp;lt;code&amp;gt;playerTurn&amp;lt;/code&amp;gt; game state, we call our &amp;lt;code&amp;gt;updatePossibleMoves&amp;lt;/code&amp;gt; method (under the &amp;quot;Utility methods&amp;quot; section). This method looks like this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
updatePossibleMoves: function( possibleMoves )&lt;br /&gt;
{&lt;br /&gt;
    // Remove current possible moves&lt;br /&gt;
    document.querySelectorAll(&#039;.possibleMove&#039;).forEach(div =&amp;gt; div.classList.remove(&#039;possibleMove&#039;));&lt;br /&gt;
&lt;br /&gt;
    for( var x in possibleMoves )&lt;br /&gt;
    {&lt;br /&gt;
        for( var y in possibleMoves[ x ] )&lt;br /&gt;
        {&lt;br /&gt;
            // x,y is a possible move&lt;br /&gt;
            document.getElementById(`square_${x}_${y}`).classList.add(&#039;possibleMove&#039;);&lt;br /&gt;
        }            &lt;br /&gt;
    }&lt;br /&gt;
                &lt;br /&gt;
    this.addTooltipToClass( &#039;possibleMove&#039;, &#039;&#039;, _(&#039;Place a disc here&#039;) );&lt;br /&gt;
},&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Here&#039;s what this does. At first, it removes all &amp;lt;code&amp;gt;possibleMove&amp;lt;/code&amp;gt; classes currently applied with the very useful &amp;lt;code&amp;gt;document.querySelectorAll&amp;lt;/code&amp;gt; method.&lt;br /&gt;
&lt;br /&gt;
Then it loops through all possible moves our PHP &amp;lt;code&amp;gt;updatePossibleMoves&amp;lt;/code&amp;gt; function created for us, and adds the &amp;lt;code&amp;gt;possibleMove&amp;lt;/code&amp;gt; class to each corresponding square.&lt;br /&gt;
&lt;br /&gt;
Finally, it uses the BGA framework &amp;lt;code&amp;gt;addTooltipToClass&amp;lt;/code&amp;gt; method to associate a tooltip to all those highlighted squares so that players can understand their meaning.&lt;br /&gt;
&lt;br /&gt;
To see the possible moves we need to create a CSS class (&amp;lt;code&amp;gt;possibleMove&amp;lt;/code&amp;gt;) that can be applied to a &amp;lt;code&amp;gt;square&amp;lt;/code&amp;gt; element to highlight it:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
.possibleMove {&lt;br /&gt;
    background-color: white;&lt;br /&gt;
    opacity: 0.2; &lt;br /&gt;
    cursor: pointer;  &lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
And here we are:&lt;br /&gt;
&lt;br /&gt;
[[File:reversi8.jpg.jpg]]&lt;br /&gt;
&lt;br /&gt;
== Let&#039;s play ==&lt;br /&gt;
&lt;br /&gt;
From now, it&#039;s better to restart a game with 2 players, because we are going to implement a complete Reversi turn. The summary of what we are going to do is:&lt;br /&gt;
* When we click on a &amp;lt;code&amp;gt;possibleMove&amp;lt;/code&amp;gt; square, send the move to the server.&lt;br /&gt;
* Server side, check the move is correct, apply Reversi rules and jump to next player.&lt;br /&gt;
* Client side, change the token position to reflect the move.&lt;br /&gt;
&lt;br /&gt;
First we associate each click on a square to one of our methods using our Javascript &amp;lt;code&amp;gt;setup&amp;lt;/code&amp;gt; method:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
document.querySelectorAll(&#039;.square&#039;).forEach(square =&amp;gt; square.addEventListener(&#039;click&#039;, e =&amp;gt; this.onPlayDisc(e)));&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note the use of the &amp;quot;dojo.query&amp;quot; method to get all HTML elements with &amp;quot;square&amp;quot; class in just one function call. Now, our &amp;quot;onPlayDisc&amp;quot; method is called each time someone clicks on a square.&lt;br /&gt;
&lt;br /&gt;
Here&#039;s our &amp;quot;onPlayDisc&amp;quot; method below:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
onPlayDisc: function( evt )&lt;br /&gt;
{&lt;br /&gt;
    // Stop this event propagation&lt;br /&gt;
    evt.preventDefault();&lt;br /&gt;
    evt.stopPropagation();&lt;br /&gt;
&lt;br /&gt;
    // Get the cliqued square x and y&lt;br /&gt;
    // Note: square id format is &amp;quot;square_X_Y&amp;quot;&lt;br /&gt;
    var coords = evt.currentTarget.id.split(&#039;_&#039;);&lt;br /&gt;
    var x = coords[1];&lt;br /&gt;
    var y = coords[2];&lt;br /&gt;
&lt;br /&gt;
    if(!document.getElementById(`square_${x}_${y}`).classList.contains(&#039;possibleMove&#039;)) {&lt;br /&gt;
        // This is not a possible move =&amp;gt; the click does nothing&lt;br /&gt;
        return ;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    this.bgaPerformAction(&amp;quot;actPlayDisc&amp;quot;, {&lt;br /&gt;
        x:x,&lt;br /&gt;
        y:y&lt;br /&gt;
    });&lt;br /&gt;
},&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
What we do here is:&lt;br /&gt;
* We stop the propagation of the Javascript &amp;lt;code&amp;gt;onclick&amp;lt;/code&amp;gt; event. Otherwise, it can lead to random behavior so it&#039;s always a good idea.&lt;br /&gt;
* We get the x/y coordinates of the square by using &amp;lt;code&amp;gt;evt.currentTarget.id&amp;lt;/code&amp;gt;&lt;br /&gt;
* We check that clicked square has the &amp;lt;code&amp;gt;possibleMove&amp;lt;/code&amp;gt; class, otherwise we know for sure that we can&#039;t play there.&lt;br /&gt;
* Finally, we make a call to the server using BGA &amp;lt;code&amp;gt;bgaPerformAction&amp;lt;/code&amp;gt; method with argument x and y. This call will check that &amp;lt;code&amp;gt;actPlayDisc&amp;lt;/code&amp;gt; action is possible, according to current game state (see &amp;lt;code&amp;gt;possibleactions&amp;lt;/code&amp;gt; entry in our &amp;lt;code&amp;gt;playerTurn&amp;lt;/code&amp;gt; game state defined above). This check is important to avoid issues if a player double clicks on a square.&lt;br /&gt;
&lt;br /&gt;
Now, we have to manage this &amp;lt;code&amp;gt;actPlayDisc&amp;lt;/code&amp;gt; action on the server side. Add a corresponding &amp;lt;code&amp;gt;actPlayDisc&amp;lt;/code&amp;gt; method in our game logic (&amp;lt;code&amp;gt;reversi.game.php&amp;lt;/code&amp;gt;):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
function actPlayDisc( int $x, int $y )&lt;br /&gt;
{&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
(The function will be called when the front-side action is triggered using the Autowire mechanism, if you want to see how it works in details check https://en.doc.boardgamearena.com/Main_game_logic:_yourgamename.game.php#Actions_%28autowired%29 )&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        $player_id = intval($this-&amp;gt;getActivePlayerId()); &lt;br /&gt;
        &lt;br /&gt;
        // Now, check if this is a possible move&lt;br /&gt;
        $board = $this-&amp;gt;getBoard();&lt;br /&gt;
        $turnedOverDiscs = $this-&amp;gt;getTurnedOverDiscs( $x, $y, $player_id, $board );&lt;br /&gt;
        &lt;br /&gt;
        if( count( $turnedOverDiscs ) &amp;gt; 0 )&lt;br /&gt;
        {&lt;br /&gt;
            // This move is possible!&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
...now, we are using the &amp;lt;code&amp;gt;getTurnedOverDiscs&amp;lt;/code&amp;gt; method again to check that this move is possible.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
            // Let&#039;s place a disc at x,y and return all &amp;quot;$returned&amp;quot; discs to the active player&lt;br /&gt;
            &lt;br /&gt;
            $sql = &amp;quot;UPDATE board SET board_player=&#039;$player_id&#039;&lt;br /&gt;
                    WHERE ( board_x, board_y) IN ( &amp;quot;;&lt;br /&gt;
            &lt;br /&gt;
            foreach( $turnedOverDiscs as $turnedOver )&lt;br /&gt;
            {&lt;br /&gt;
                $sql .= &amp;quot;(&#039;&amp;quot;.$turnedOver[&#039;x&#039;].&amp;quot;&#039;,&#039;&amp;quot;.$turnedOver[&#039;y&#039;].&amp;quot;&#039;),&amp;quot;;&lt;br /&gt;
            }&lt;br /&gt;
            $sql .= &amp;quot;(&#039;$x&#039;,&#039;$y&#039;) ) &amp;quot;;&lt;br /&gt;
                       &lt;br /&gt;
            $this-&amp;gt;DbQuery( $sql );&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
... we update the database to change the color of all turned over disc + the disc we just placed.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
            // Update scores according to the number of disc on board&lt;br /&gt;
            $sql = &amp;quot;UPDATE player&lt;br /&gt;
                    SET player_score = (&lt;br /&gt;
                    SELECT COUNT( board_x ) FROM board WHERE board_player=player_id&lt;br /&gt;
                    )&amp;quot;;&lt;br /&gt;
            $this-&amp;gt;DbQuery( $sql );&lt;br /&gt;
            &lt;br /&gt;
            // Statistics&lt;br /&gt;
            $this-&amp;gt;incStat( count( $turnedOverDiscs ), &amp;quot;turnedOver&amp;quot;, $player_id );&lt;br /&gt;
            if( ($x==1 &amp;amp;&amp;amp; $y==1) || ($x==8 &amp;amp;&amp;amp; $y==1) || ($x==1 &amp;amp;&amp;amp; $y==8) || ($x==8 &amp;amp;&amp;amp; $y==8) )&lt;br /&gt;
                $this-&amp;gt;incStat( 1, &#039;discPlayedOnCorner&#039;, $player_id );&lt;br /&gt;
            else if( $x==1 || $x==8 || $y==1 || $y==8 )&lt;br /&gt;
                $this-&amp;gt;incStat( 1, &#039;discPlayedOnBorder&#039;, $player_id );&lt;br /&gt;
            else if( $x&amp;gt;=3 &amp;amp;&amp;amp; $x&amp;lt;=6 &amp;amp;&amp;amp; $y&amp;gt;=3 &amp;amp;&amp;amp; $y&amp;lt;=6 )&lt;br /&gt;
                $this-&amp;gt;incStat( 1, &#039;discPlayedOnCenter&#039;, $player_id );&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
... now, we update both player score by counting all disc, and we manage game statistics.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
            // Notify&lt;br /&gt;
            $this-&amp;gt;notifyAllPlayers( &amp;quot;playDisc&amp;quot;, clienttranslate( &#039;${player_name} plays a disc and turns over ${returned_nbr} disc(s)&#039; ), array(&lt;br /&gt;
                &#039;player_id&#039; =&amp;gt; $player_id,&lt;br /&gt;
                &#039;player_name&#039; =&amp;gt; $this-&amp;gt;getActivePlayerName(),&lt;br /&gt;
                &#039;returned_nbr&#039; =&amp;gt; count( $turnedOverDiscs ),&lt;br /&gt;
                &#039;x&#039; =&amp;gt; $x,&lt;br /&gt;
                &#039;y&#039; =&amp;gt; $y&lt;br /&gt;
            ) );&lt;br /&gt;
&lt;br /&gt;
            $this-&amp;gt;notifyAllPlayers( &amp;quot;turnOverDiscs&amp;quot;, &#039;&#039;, array(&lt;br /&gt;
                &#039;player_id&#039; =&amp;gt; $player_id,&lt;br /&gt;
                &#039;turnedOver&#039; =&amp;gt; $turnedOverDiscs&lt;br /&gt;
            ) );&lt;br /&gt;
            &lt;br /&gt;
            $newScores = $this-&amp;gt;getCollectionFromDb( &amp;quot;SELECT player_id, player_score FROM player&amp;quot;, true );&lt;br /&gt;
            $this-&amp;gt;notifyAllPlayers( &amp;quot;newScores&amp;quot;, &amp;quot;&amp;quot;, array(&lt;br /&gt;
                &amp;quot;scores&amp;quot; =&amp;gt; $newScores&lt;br /&gt;
            ) );&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
... then we notify about all these changes. We are using for that 3 notifications (&amp;lt;code&amp;gt;playDisc&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;turnOverDiscs&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;newScores&amp;lt;/code&amp;gt; that we are going to implement on client side later). Note that the description of the &amp;lt;code&amp;gt;playDisc&amp;lt;/code&amp;gt; notification will be logged in the game log.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
            // Then, go to the next state&lt;br /&gt;
            $this-&amp;gt;gamestate-&amp;gt;nextState( &#039;playDisc&#039; );&lt;br /&gt;
        }&lt;br /&gt;
        else&lt;br /&gt;
            throw new BgaSystemException( &amp;quot;Impossible move&amp;quot; );&lt;br /&gt;
    }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
... finally, we jump to the next game state if everything goes fine (&amp;lt;code&amp;gt;playDisc&amp;lt;/code&amp;gt; is the name of a transition in the &amp;lt;code&amp;gt;playerTurn&amp;lt;/code&amp;gt; game state description above which leads to state 11 which is &amp;lt;code&amp;gt;nextPlayer&amp;lt;/code&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
To make the statistics work, we have to initialize them in &amp;lt;code&amp;gt;stats.json&amp;lt;/code&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
  &amp;quot;player&amp;quot;: {&lt;br /&gt;
    &amp;quot;discPlayedOnCorner&amp;quot;: {&lt;br /&gt;
      &amp;quot;id&amp;quot;: 10,&lt;br /&gt;
      &amp;quot;name&amp;quot;: &amp;quot;Discs played on a corner&amp;quot;,&lt;br /&gt;
      &amp;quot;type&amp;quot;: &amp;quot;int&amp;quot;&lt;br /&gt;
    },&lt;br /&gt;
    &amp;quot;discPlayedOnBorder&amp;quot;: {&lt;br /&gt;
      &amp;quot;id&amp;quot;: 11,&lt;br /&gt;
      &amp;quot;name&amp;quot;: &amp;quot;Discs played on a border&amp;quot;,&lt;br /&gt;
      &amp;quot;type&amp;quot;: &amp;quot;int&amp;quot;&lt;br /&gt;
    },&lt;br /&gt;
    &amp;quot;discPlayedOnCenter&amp;quot;: {&lt;br /&gt;
      &amp;quot;id&amp;quot;: 12,&lt;br /&gt;
      &amp;quot;name&amp;quot;: &amp;quot;Discs played on board center part&amp;quot;,&lt;br /&gt;
      &amp;quot;type&amp;quot;: &amp;quot;int&amp;quot;&lt;br /&gt;
    },&lt;br /&gt;
    &amp;quot;turnedOver&amp;quot;: {&lt;br /&gt;
      &amp;quot;id&amp;quot;: 13,&lt;br /&gt;
      &amp;quot;name&amp;quot;: &amp;quot;Number of discs turned over&amp;quot;,&lt;br /&gt;
      &amp;quot;type&amp;quot;: &amp;quot;int&amp;quot;&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
A last thing to do on the server side is to activate the next player when we enter the &amp;lt;code&amp;gt;nextPlayer&amp;lt;/code&amp;gt; game state (in the &amp;lt;code&amp;gt;reversi.game.php&amp;lt;/code&amp;gt; file, under &amp;quot;Game state reactions&amp;quot;):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    function stNextPlayer(): void&lt;br /&gt;
    {&lt;br /&gt;
        // Active next player&lt;br /&gt;
        $player_id = intval($this-&amp;gt;activeNextPlayer());&lt;br /&gt;
&lt;br /&gt;
        // Check if both player has at least 1 discs, and if there are free squares to play&lt;br /&gt;
        $player_to_discs = $this-&amp;gt;getCollectionFromDb( &amp;quot;SELECT board_player, COUNT( board_x )&lt;br /&gt;
                                                       FROM board&lt;br /&gt;
                                                       GROUP BY board_player&amp;quot;, true );&lt;br /&gt;
&lt;br /&gt;
        if( ! isset( $player_to_discs[ null ] ) )&lt;br /&gt;
        {&lt;br /&gt;
            // Index 0 has not been set =&amp;gt; there&#039;s no more free place on the board !&lt;br /&gt;
            // =&amp;gt; end of the game&lt;br /&gt;
            $this-&amp;gt;gamestate-&amp;gt;nextState( &#039;endGame&#039; );&lt;br /&gt;
            return ;&lt;br /&gt;
        }&lt;br /&gt;
        else if( ! isset( $player_to_discs[ $player_id ] ) )&lt;br /&gt;
        {&lt;br /&gt;
            // Active player has no more disc on the board =&amp;gt; he looses immediately&lt;br /&gt;
            $this-&amp;gt;gamestate-&amp;gt;nextState( &#039;endGame&#039; );&lt;br /&gt;
            return ;&lt;br /&gt;
        }&lt;br /&gt;
        &lt;br /&gt;
        // Can this player play?&lt;br /&gt;
&lt;br /&gt;
        $possibleMoves = $this-&amp;gt;getPossibleMoves( $player_id );&lt;br /&gt;
        if( count( $possibleMoves ) == 0 )&lt;br /&gt;
        {&lt;br /&gt;
&lt;br /&gt;
            // This player can&#039;t play&lt;br /&gt;
            // Can his opponent play ?&lt;br /&gt;
            $opponent_id = (int)$this-&amp;gt;getUniqueValueFromDb( &amp;quot;SELECT player_id FROM player WHERE player_id!=&#039;$player_id&#039; &amp;quot; );&lt;br /&gt;
            if( count( $this-&amp;gt;getPossibleMoves( $opponent_id ) ) == 0 )&lt;br /&gt;
            {&lt;br /&gt;
                // Nobody can move =&amp;gt; end of the game&lt;br /&gt;
                $this-&amp;gt;gamestate-&amp;gt;nextState( &#039;endGame&#039; );&lt;br /&gt;
            }&lt;br /&gt;
            else&lt;br /&gt;
            {            &lt;br /&gt;
                // =&amp;gt; pass his turn&lt;br /&gt;
                $this-&amp;gt;gamestate-&amp;gt;nextState( &#039;cantPlay&#039; );&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
        else&lt;br /&gt;
        {&lt;br /&gt;
            // This player can play. Give him some extra time&lt;br /&gt;
            $this-&amp;gt;giveExtraTime( $player_id );&lt;br /&gt;
            $this-&amp;gt;gamestate-&amp;gt;nextState( &#039;nextTurn&#039; );&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Now, when we play a token, the rules are checked and the token appears in the database.&lt;br /&gt;
&lt;br /&gt;
[[File:reversi9.jpg]]&lt;br /&gt;
&lt;br /&gt;
Of course, as we don&#039;t manage notifications on client side, we need to press F5 after each move to see the changes on the board.&lt;br /&gt;
&lt;br /&gt;
== Make the move appear automatically ==&lt;br /&gt;
&lt;br /&gt;
Now, what we have to do is process the notifications sent by the server and make the move appear on the interface.&lt;br /&gt;
&lt;br /&gt;
In our &amp;lt;code&amp;gt;setupNotifications&amp;lt;/code&amp;gt; method in &amp;lt;code&amp;gt;reversi.js&amp;lt;/code&amp;gt;, we register 2 methods for the 2 notifications we created at the previous step (&amp;lt;code&amp;gt;playDisc&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;turnOverDiscs&amp;lt;/code&amp;gt;):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
            const notifs = [&lt;br /&gt;
                [&#039;playDisc&#039;, 500],&lt;br /&gt;
                [&#039;turnOverDiscs&#039;, 1500],&lt;br /&gt;
                [&#039;newScores&#039;, 1],&lt;br /&gt;
            ];&lt;br /&gt;
    &lt;br /&gt;
            notifs.forEach((notif) =&amp;gt; {&lt;br /&gt;
                dojo.subscribe(notif[0], this, `notif_${notif[0]}`);&lt;br /&gt;
                this.notifqueue.setSynchronous(notif[0], notif[1]);&lt;br /&gt;
            });&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We will associate each of our 3 notifications with a method prefixed with &amp;lt;code&amp;gt;notif_&amp;lt;/code&amp;gt;. We also define these notifications as &amp;quot;synchronous&amp;quot;, with a duration in millisecond. It tells the user interface to wait some time after executing the notification, to let the animation end before starting the next notification. In our specific case, the animation will be the following:&lt;br /&gt;
* Make a disc slide from the player panel to its place on the board&lt;br /&gt;
* (wait 500ms)&lt;br /&gt;
* Make all turned over discs blink (and of course turned them over)&lt;br /&gt;
* (wait 1500ms)&lt;br /&gt;
* Update the player scores&lt;br /&gt;
* (no real delay on this one)&lt;br /&gt;
&lt;br /&gt;
The second part of the code is a generic thing to automatically bind the notifs we configured to the &amp;lt;code&amp;gt;notif_&amp;lt;notifName&amp;gt;&amp;lt;/code&amp;gt; functions we are about to create.&lt;br /&gt;
&lt;br /&gt;
Let&#039;s have a look now on the &amp;lt;code&amp;gt;playDisc&amp;lt;/code&amp;gt; notification handler method:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
notif_playDisc: function( notif )&lt;br /&gt;
{&lt;br /&gt;
    // Remove current possible moves (makes the board more clear)&lt;br /&gt;
    document.querySelectorAll(&#039;.possibleMove&#039;).forEach(div =&amp;gt; div.classList.remove(&#039;possibleMove&#039;));&lt;br /&gt;
&lt;br /&gt;
    this.addDiscOnBoard( notif.args.x, notif.args.y, notif.args.player_id );&lt;br /&gt;
},&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
No surprise here, we re-used some existing stuff to:&lt;br /&gt;
* Remove the highlighted squares.&lt;br /&gt;
* Add a new disc on board, coming from player panel.&lt;br /&gt;
&lt;br /&gt;
Now, here&#039;s the method that handles the &amp;lt;code&amp;gt;turnOverDiscs&amp;lt;/code&amp;gt; notification:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
notif_turnOverDiscs: function( notif )&lt;br /&gt;
{&lt;br /&gt;
    // Get the color of the player who is returning the discs&lt;br /&gt;
    var targetColor = this.gamedatas.players[ notif.args.player_id ].color;&lt;br /&gt;
&lt;br /&gt;
    // Made these discs blinking and set them to the specified color&lt;br /&gt;
    for( var i in notif.args.turnedOver )&lt;br /&gt;
    {&lt;br /&gt;
        var disc = notif.args.turnedOver[ i ];&lt;br /&gt;
        &lt;br /&gt;
        // Make the disc blink 2 times&lt;br /&gt;
        var anim = dojo.fx.chain( [&lt;br /&gt;
            dojo.fadeOut( { node: &#039;disc_&#039;+disc.x+&#039;&#039;+disc.y } ),&lt;br /&gt;
            dojo.fadeIn( { node: &#039;disc_&#039;+disc.x+&#039;&#039;+disc.y } ),&lt;br /&gt;
            dojo.fadeOut( { &lt;br /&gt;
                            node: &#039;disc_&#039;+disc.x+&#039;&#039;+disc.y,&lt;br /&gt;
                            onEnd: node =&amp;gt; $(node).dataset.color = targetColor,&lt;br /&gt;
                            } ),&lt;br /&gt;
            dojo.fadeIn( { node: &#039;disc_&#039;+disc.x+&#039;&#039;+disc.y  } )&lt;br /&gt;
                            &lt;br /&gt;
        ] ); // end of dojo.fx.chain&lt;br /&gt;
&lt;br /&gt;
        // ... and launch the animation&lt;br /&gt;
        anim.play();                &lt;br /&gt;
    }&lt;br /&gt;
},&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The list of the discs to be turned over has been made available by our server side code in &amp;lt;code&amp;gt;notif.args.turnedOver&amp;lt;/code&amp;gt; (see previous paragraph). We loop through all these discs, and create a complex animation using &amp;lt;code&amp;gt;dojo.Animation&amp;lt;/code&amp;gt; for each of them. The complete documentation on dojo animations [http://dojotoolkit.org/documentation/tutorials/1.6/animation/ can be found here].&lt;br /&gt;
&lt;br /&gt;
In few words: we create a chain of 4 animations to make the disc fade out, fade in, fade out again, and fade in again. At the end of the second fade out, we change the color of the disc. Finally, we launch the animation with &amp;lt;code&amp;gt;play()&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
And Also the notification to update the scores:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
notif_newScores: function( notif )&lt;br /&gt;
        {&lt;br /&gt;
            for( var player_id in notif.args.scores )&lt;br /&gt;
            {&lt;br /&gt;
                var newScore = notif.args.scores[ player_id ];&lt;br /&gt;
                this.scoreCtrl[ player_id ].toValue( newScore );&lt;br /&gt;
            }&lt;br /&gt;
        },&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Category:Studio]]&lt;/div&gt;</summary>
		<author><name>Sguzzer Gunayer</name></author>
	</entry>
	<entry>
		<id>https://en.doc.boardgamearena.com/index.php?title=Tutorial_reversi&amp;diff=22809</id>
		<title>Tutorial reversi</title>
		<link rel="alternate" type="text/html" href="https://en.doc.boardgamearena.com/index.php?title=Tutorial_reversi&amp;diff=22809"/>
		<updated>2024-09-29T08:34:06Z</updated>

		<summary type="html">&lt;p&gt;Sguzzer Gunayer: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&#039;&#039;&#039;Check out an updated version&#039;&#039;&#039; of the [[BGA Type Safe Template: Reversi|Reversi Tutorial]] which uses the [[BGA Type Safe Template]]. {{Studio_Framework_Navigation}}&lt;br /&gt;
&lt;br /&gt;
== Introduction ==&lt;br /&gt;
&lt;br /&gt;
Using this tutorial, you can build a complete working game on the BGA environment: Reversi.&lt;br /&gt;
&lt;br /&gt;
Before you read this tutorial, you must:&lt;br /&gt;
* Read the overall presentations of the BGA Framework ([[Studio|see here]]).&lt;br /&gt;
* Know the [http://en.wikipedia.org/wiki/Reversi#Rules rules of Reversi].&lt;br /&gt;
* Know the languages used on BGA: PHP, SQL, HTML, CSS, Javascript&lt;br /&gt;
* &#039;&#039;&#039;Setup your development environment&#039;&#039;&#039; [http://en.doc.boardgamearena.com/First_steps_with_BGA_Studio First Steps with BGA Studio]&lt;br /&gt;
&lt;br /&gt;
== Create your first game ==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Note: you should already have created a project following instructions in [[First_steps_with_BGA_Studio#Create_a_new_game_project|Create a new game project]]. While you will find a &#039;&#039;&#039;reversi&#039;&#039;&#039; directory in your SFTP folder, do not use it for this tutorial. Instead, use the project you have created as an (empty) starting point.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
With the initial skeleton of code provided in your project, you can already start a game from the BGA Studio:&lt;br /&gt;
* Go to your [https://studio.boardgamearena.com/controlpanel studio Control panel], then Manage games and select your initial project. &#039;&#039;Note: there are warnings displayed about a missing BGG_ID and presentation text. You can ignore that for now.&#039;&#039;&lt;br /&gt;
* Click the Play link next to your project name. This will open the Play page and offer to create a new table for your project. &#039;&#039;Optional: click the Heart icon to add your project to your favorite games list.&#039;&#039;&lt;br /&gt;
* On the Play page, on the top of the page, make sure that your settings are &amp;quot;Simple game&amp;quot;, &amp;quot;Real time&amp;quot; and &amp;quot;Manual&amp;quot;.&lt;br /&gt;
* Click &amp;quot;Create table&amp;quot; to create a table of your project. &lt;br /&gt;
* For now, we are going to work with one player only, so use the (-) button to set the number of players to 1. Most of the time it is simpler to proceed with only one player during the early phase of development of your game, as it&#039;s easy and fast to start/stop games. If you choose to start with 2 players, you should see two names on the right: testdude0 and testdude1. To switch between them, press the red arrow button near their names; it will open another tab. This way you don&#039;t need to login and logout from multiple accounts.) &lt;br /&gt;
* Reminder: Always use the &amp;quot;Express Start&amp;quot; button to start the game.&lt;br /&gt;
&lt;br /&gt;
Thus, you can start a &amp;quot;Reversi&amp;quot; game, and arrive on a void, empty game. Yeah.&lt;br /&gt;
&lt;br /&gt;
End the game by clicking on the game options icon on the top right, and then on &amp;quot;Express Stop&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
== Editing the game information (Optional) ==&lt;br /&gt;
&lt;br /&gt;
This step is optional and will fix the warnings on the project page (missing BGG_ID and presentation).&lt;br /&gt;
&lt;br /&gt;
==== Edits to fix Errors ====&lt;br /&gt;
* Edit your local copy of the &amp;lt;code&amp;gt;gameinfos.inc.php&amp;lt;/code&amp;gt; file:&lt;br /&gt;
** Change the &amp;lt;code&amp;gt;bgg_id&amp;lt;/code&amp;gt; value from &amp;lt;code&amp;gt;0&amp;lt;/code&amp;gt; to &amp;lt;code&amp;gt;2389&amp;lt;/code&amp;gt; - that&#039;s around line 37.&lt;br /&gt;
** Add &amp;lt;code&amp;gt;1,&amp;lt;/code&amp;gt; to the players array - that&#039;s around line 41.&lt;br /&gt;
** Change the presentation array content - that&#039;s around line 134. Uncomment one line and change the text. Remove the final comma if you keep only one line!&lt;br /&gt;
* Upload the &amp;lt;code&amp;gt;gameinfos.inc.php&amp;lt;/code&amp;gt; file to the SFTP server (see [[First_steps_with_BGA_Studio#Connect_to_your_SFTP_folder|Connect to your SFTP folder]]).&lt;br /&gt;
&lt;br /&gt;
==== Test your Edits ====&lt;br /&gt;
* Go back to your project page, and in the &amp;quot;Game Information&amp;quot; section, click &amp;quot;Reload game informations&amp;quot;.&lt;br /&gt;
* Finally, refresh the project page in your browser (usually CTRL-F5).&lt;br /&gt;
&lt;br /&gt;
===== Not working? =====&lt;br /&gt;
Some changes will require bypassing the cache. It is often worth doing a hard refresh to make sure the&lt;br /&gt;
&lt;br /&gt;
Sometimes the cache will keep your changes from showing. Since this is a possibility, it will be useful to know how to bypass the cache. To do so you may manually clear cache or use a shortcut to refresh and ignore the cached version of the page. Here&#039;s how&lt;br /&gt;
&lt;br /&gt;
====== Windows ======&lt;br /&gt;
Chrome, Firefox, or Edge: Press &amp;lt;code&amp;gt;Ctrl+F5&amp;lt;/code&amp;gt; or &amp;lt;code&amp;gt;Shift+F5&amp;lt;/code&amp;gt; or &amp;lt;code&amp;gt;Ctrl+Shift+R&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====== Mac ======&lt;br /&gt;
Chrome or Firefox: Press &amp;lt;code&amp;gt;Shift+Command+R&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Safari for Mac: Press &amp;lt;code&amp;gt;Command+Option+E&amp;lt;/code&amp;gt; to empty the cache, then hold down Shift and click Reload in the toolbar&lt;br /&gt;
&lt;br /&gt;
== Make it look like Reversi ==&lt;br /&gt;
&lt;br /&gt;
Let&#039;s start with the board. This will give you a good idea of how things will look and where tokens should go.&lt;br /&gt;
&lt;br /&gt;
Be careful designing the layout of your game: you must always keep in mind that players with a 1024px screen width must be able to play. Usually, it means that the width of the play area can be 750px (in the worst case).&lt;br /&gt;
&lt;br /&gt;
For Reversi, it&#039;s useless to have a 750x750px board - much too big, so we chose this one which fit perfectly (536x528):&lt;br /&gt;
&lt;br /&gt;
[[File:Board.jpg]]&lt;br /&gt;
&lt;br /&gt;
Note that we are using a jpg file. Jpg files are lighter than png, so they are faster to load. Later, we are going to use PNGs for tokens because they allow for transparency.&lt;br /&gt;
&lt;br /&gt;
==== Add the board ====&lt;br /&gt;
use lowercase file names&lt;br /&gt;
* upload &amp;lt;code&amp;gt;board.jpg&amp;lt;/code&amp;gt; in your &amp;lt;code&amp;gt;img/&amp;lt;/code&amp;gt; directory. &lt;br /&gt;
* edit &amp;lt;code&amp;gt;reversi_reversi.tpl&amp;lt;/code&amp;gt; to add a &amp;lt;code&amp;gt;div&amp;lt;/code&amp;gt; for your board.&lt;br /&gt;
&lt;br /&gt;
Note: If you are building this game by following the tutorial, you will have a different project name than &amp;lt;code&amp;gt;reversi&amp;lt;/code&amp;gt; (i.e. &amp;lt;code&amp;gt;mygame_mygame.tpl&amp;lt;/code&amp;gt;). The file names in your project will be different than shown in this tutorial, replacing &amp;lt;code&amp;gt;reversi&amp;lt;/code&amp;gt; with your project name. Be sure that any code (other than comments) that references &amp;lt;code&amp;gt;reversi&amp;lt;/code&amp;gt; is changed to your actual project name.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;div id=&amp;quot;board&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* edit your &amp;lt;code&amp;gt;reversi.css&amp;lt;/code&amp;gt; file to transform it into a visible board:&lt;br /&gt;
&lt;br /&gt;
 #board {&lt;br /&gt;
    width: 536px;&lt;br /&gt;
    height: 528px;&lt;br /&gt;
    background-image: url(&#039;img/board.jpg&#039;);&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Important: refresh your page.&#039;&#039;&#039; Here&#039;s your board:[[File:reversi1.jpg]]&lt;br /&gt;
&lt;br /&gt;
If the board does not appear, refresh the page (always do this when you update the CSS file), and check the image filename. Remember file names are case sensitive!&lt;br /&gt;
&lt;br /&gt;
==== Code the Grid ====&lt;br /&gt;
Now, we need to create some invisible HTML elements where squares are. These elements will be used as position references for the white and black tokens. &lt;br /&gt;
&lt;br /&gt;
===== Build the grid of squares =====&lt;br /&gt;
The board is 8 squares by 8 squares. This means we need 64 squares. To avoid writing 64 individual &amp;lt;code&amp;gt;div&amp;lt;/code&amp;gt; elements on our template, we are going to generate the squares on JS setup.&lt;br /&gt;
&lt;br /&gt;
We&#039;ll do this in our Javascript &amp;lt;code&amp;gt;setup&amp;lt;/code&amp;gt; method under &amp;lt;code&amp;gt;// TODO: Set up your game interface here, according to &amp;quot;gamedatas&amp;quot;&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
const board = document.getElementById(&#039;board&#039;);&lt;br /&gt;
const hor_scale = 64.8;&lt;br /&gt;
const ver_scale = 64.4;&lt;br /&gt;
for (let x=1; x&amp;lt;=8; x++) {&lt;br /&gt;
    for (let y=1; y&amp;lt;=8; y++) {&lt;br /&gt;
        const left = Math.round((x - 1) * hor_scale + 10);&lt;br /&gt;
        const top = Math.round((y - 1) * ver_scale + 7);&lt;br /&gt;
        // we use afterbegin to make sure squares are placed before discs&lt;br /&gt;
        board.insertAdjacentHTML(`afterbegin`, `&amp;lt;div id=&amp;quot;square_${x}_${y}&amp;quot; class=&amp;quot;square&amp;quot; style=&amp;quot;left: ${left}px; top: ${top}px;&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;`);&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note: as you can see, squares in our &amp;lt;code&amp;gt;board.jpg&amp;lt;/code&amp;gt; files do not have an exact width/height in pixels, and that&#039;s the reason we are using floating point numbers here.&lt;br /&gt;
&lt;br /&gt;
===== Style Those Squares =====&lt;br /&gt;
Now, to finish our work and check if everything works fine, we are going to style our square a little bit in our CSS stylesheet:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#board {&lt;br /&gt;
    width: 536px;&lt;br /&gt;
    height: 528px;&lt;br /&gt;
    background-image: url(&#039;img/board.jpg&#039;);&lt;br /&gt;
    position: relative;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.square {&lt;br /&gt;
    width: 62px;&lt;br /&gt;
    height: 62px;&lt;br /&gt;
    position: absolute;&lt;br /&gt;
    background-color: red;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Explanations:&lt;br /&gt;
* With &amp;quot;position: relative&amp;quot; on board, we ensure square elements are positioned relatively to board.&lt;br /&gt;
* &amp;lt;code&amp;gt;background-color: red;&amp;lt;/code&amp;gt; is used for testing. This allows us to see the invisible elements. (You could instead do something like &amp;lt;code&amp;gt;outline: 2px solid orange;&amp;lt;/code&amp;gt; have fun and be creative)&lt;br /&gt;
&lt;br /&gt;
Let&#039;s refresh and check our (beautiful) squares:&lt;br /&gt;
&lt;br /&gt;
[[File:reversi2.jpg]]&lt;br /&gt;
&lt;br /&gt;
Now that you know the squares are there, you can remove the test line &amp;lt;code&amp;gt;background-color: red;&amp;lt;/code&amp;gt;  from your &amp;lt;code&amp;gt;.square&amp;lt;/code&amp;gt; class in the CSS stylesheet.&lt;br /&gt;
&lt;br /&gt;
===== Not Working? =====&lt;br /&gt;
If the styled squares do not appear, inspect and check your css (Chrome DevTools: Application &amp;gt; Frames &amp;gt; top &amp;gt; Stylesheets &amp;gt; reversi.css). &lt;br /&gt;
&lt;br /&gt;
== The Tokens ==&lt;br /&gt;
&lt;br /&gt;
Now, our board is ready for some tokens!&lt;br /&gt;
&lt;br /&gt;
[Note: Throughout this tutorial, sometimes &amp;quot;tokens&amp;quot; is used, and sometimes &amp;quot;discs&amp;quot; is used. They are often swapped if you&#039;re looking at code in the reversi example project.]&lt;br /&gt;
&lt;br /&gt;
=== Build the Token ===&lt;br /&gt;
There are quite a few steps before the tokens will appear. You may be used to testing after every change, but that won&#039;t work well here. The token will &#039;&#039;&#039;not&#039;&#039;&#039; show until you have add styles to the css, js template to the tpl, utility method in the js,  adjusted the php file, and added the token to the board in the js file.&lt;br /&gt;
&lt;br /&gt;
==== HTML in the .tpl file ====&lt;br /&gt;
At first, we introduce a new &#039;div&#039; element as a child of &amp;quot;board&amp;quot; to host all these tokens (in our template):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;div id=&amp;quot;board&amp;quot;&amp;gt;&lt;br /&gt;
    &lt;br /&gt;
    &amp;lt;div id=&amp;quot;discs&amp;quot;&amp;gt;&lt;br /&gt;
    &amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note: &amp;lt;code&amp;gt;discs&amp;lt;/code&amp;gt; is plural. This div will be used to hold the token divs. Shortly, we will use javascript to add individual tokens to the board.&lt;br /&gt;
&lt;br /&gt;
==== Add Token to img directory ====&lt;br /&gt;
Here&#039;s a new piece of art with the tokens. We need transparency here so we are using a png file:&lt;br /&gt;
&lt;br /&gt;
[[File:tokens.png]]&lt;br /&gt;
&lt;br /&gt;
Upload this image file &amp;lt;code&amp;gt;tokens.png&amp;lt;/code&amp;gt; in your &amp;lt;code&amp;gt;img/&amp;lt;/code&amp;gt; directory.&lt;br /&gt;
&lt;br /&gt;
Important Fun Fact: we are using ONE file for both tokens. It is really important to use a minimum number of graphic files for your game. This is called the &amp;quot;CSS sprite&amp;quot; technique, because it makes the game load faster and more reliable. [http://www.w3schools.com/css/css_image_sprites.asp Read more about CSS sprites].&lt;br /&gt;
&lt;br /&gt;
==== Style the Tokens in .css file ====&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
.disc {&lt;br /&gt;
    width: 56px;&lt;br /&gt;
    height: 56px;&lt;br /&gt;
    position: absolute;&lt;br /&gt;
    background-image: url(&#039;img/tokens.png&#039;);&lt;br /&gt;
    background-size: auto 100%;&lt;br /&gt;
}&lt;br /&gt;
.disc[data-color=&amp;quot;ffffff&amp;quot;] { background-position-x: 0%; }&lt;br /&gt;
.disc[data-color=&amp;quot;000000&amp;quot;] { background-position-x: 100%; }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
With this CSS code, we can set and change the token color by changing the data-color attribute. Using data instead of a class ensures it can be only one of them (the disc cannot be black and white at the same time).&lt;br /&gt;
&lt;br /&gt;
Note the &amp;quot;&amp;lt;code&amp;gt;position: absolute&amp;lt;/code&amp;gt;&amp;quot; which allows us to position tokens on the board and make them &amp;quot;slide&amp;quot; to their positions.&lt;br /&gt;
&lt;br /&gt;
==== Add Token Utility Method in .js file ====&lt;br /&gt;
Now, let&#039;s make the first token appear on our board. Tokens are not visible at the beginning of the game: they appear dynamically during the game. For this reason, we are going to make them appear from our Javascript code, using a template string&lt;br /&gt;
&lt;br /&gt;
Let&#039;s create a method in our Javascript code (in the &amp;lt;code&amp;gt;reversi.js&amp;lt;/code&amp;gt; file) that will make a token appear on the board, using this template. Add under the section //// Utility methods:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
addDiscOnBoard: function( x, y, player )&lt;br /&gt;
{&lt;br /&gt;
    var color = this.gamedatas.players[ player ].color;&lt;br /&gt;
    &lt;br /&gt;
    document.getElementById(&#039;discs&#039;).insertAdjacentHTML(&#039;beforeend&#039;, `&amp;lt;div class=&amp;quot;disc&amp;quot; data-color=&amp;quot;${color}&amp;quot; id=&amp;quot;disc_${x}${y}&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;`);&lt;br /&gt;
    &lt;br /&gt;
    this.placeOnObject( `disc_${x}${y}`, &#039;overall_player_board_&#039;+player );&lt;br /&gt;
    this.slideToObject( `disc_${x}${y}`, &#039;square_&#039;+x+&#039;_&#039;+y ).play();&lt;br /&gt;
},  &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===== Utility Method Explanation =====&lt;br /&gt;
* with &amp;lt;code&amp;gt;element.insertAdjacentHTML&amp;lt;/code&amp;gt; method, we create a HTML piece of code and insert it as a new child of &amp;lt;code&amp;gt;tokens&amp;lt;/code&amp;gt; div element.&lt;br /&gt;
* with &amp;lt;code&amp;gt;this.placeOnObject&amp;lt;/code&amp;gt; BGA method, we place this element over the panel of some player. &lt;br /&gt;
* Immediately after, using &amp;lt;code&amp;gt;this.slideToObject&amp;lt;/code&amp;gt; BGA method, we make the token slide to the &amp;lt;code&amp;gt;square&amp;lt;/code&amp;gt; element, its final destination.&lt;br /&gt;
* &amp;lt;code&amp;gt;&#039;overall_player_board_&#039;+player&amp;lt;/code&amp;gt; refers to the div element that contains each player&#039;s information and avatar. By initially placing the token here, it gives the effect that the player&#039;s avatar is throwing the token onto the board.&lt;br /&gt;
&lt;br /&gt;
Note: don&#039;t forget to call the &amp;lt;code&amp;gt;play()&amp;lt;/code&amp;gt;, otherwise the token will remain at its original location.&lt;br /&gt;
&lt;br /&gt;
Note: during this process, the parent of the new token HTML element will stay &amp;lt;code&amp;gt;tokens&amp;lt;/code&amp;gt;. &amp;lt;code&amp;gt;placeOnObject&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;slideToObject&amp;lt;/code&amp;gt; methods are &#039;&#039;only&#039;&#039; moving the position of elements on screen, and they are &#039;&#039;not&#039;&#039; modifying the HTML tree.&lt;br /&gt;
&lt;br /&gt;
==== Set Token Colors in setupNewGame in .game.php file ====&lt;br /&gt;
Before we can show a token, we need to set the player colors in the &amp;lt;code&amp;gt;setupNewGame&amp;lt;/code&amp;gt; function in &amp;lt;code&amp;gt;reversi.game.php&amp;lt;/code&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
Replace &amp;lt;code&amp;gt;$default_colors = $gameinfos[&#039;player_colors&#039;];&amp;lt;/code&amp;gt; with the following line:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        $default_colors = array( &amp;quot;ffffff&amp;quot;, &amp;quot;000000&amp;quot; );&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note: A few lines below, you may have to remove the line &amp;lt;code&amp;gt;this-&amp;gt;reattributeColorsBasedOnPreferences( $players, $gameinfos[&#039;player_colors&#039;] );&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Test the Token ===&lt;br /&gt;
Now, to test if everything works fine&lt;br /&gt;
&lt;br /&gt;
==== addTokenOnBoard() in .js file to Test ====&lt;br /&gt;
In &amp;lt;code&amp;gt;reversi.js&amp;lt;/code&amp;gt;, in &amp;lt;code&amp;gt;setup: function&amp;lt;/code&amp;gt;, under the code we added to generate the squares. &lt;br /&gt;
 this.addDiscOnBoard( 2, 2, this.player_id );&lt;br /&gt;
Now restart the game.&lt;br /&gt;
&lt;br /&gt;
A token should appear and slide immediately to its position, like this:&lt;br /&gt;
&lt;br /&gt;
[[File:reversi3.jpg]]&lt;br /&gt;
&lt;br /&gt;
== The database ==&lt;br /&gt;
&lt;br /&gt;
We did most of the client-side programming, so let&#039;s have a look on the other side now. To design the database model of our game, you will need to access the database. You won&#039;t need to do anything in database UI, yet.&lt;br /&gt;
&lt;br /&gt;
=== Accessing the Database ===&lt;br /&gt;
To access the database, start a game, then click &amp;quot;Go to game database&amp;quot; link at the bottom of our game, to access the database directly with a PhpMyAdmin instance.&lt;br /&gt;
&lt;br /&gt;
After the first time you&#039;ve acess the database, you could skip opening a game and instead, go to https://studio.boardgamearena.com/db/ . Your PhpMyAdmin username/password is in your welcome email.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note&#039;&#039;&#039;: do not remove existing tables&lt;br /&gt;
&lt;br /&gt;
=== Create Table in .sql file ===&lt;br /&gt;
Now, you are able to create the table(s) you need for your game, and report every SQL command used in your &amp;lt;code&amp;gt;dbmodel.sql&amp;lt;/code&amp;gt; file. &lt;br /&gt;
&lt;br /&gt;
The database model of Reversi is short: just one table with the squares of the board. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
CREATE TABLE IF NOT EXISTS `board` (&lt;br /&gt;
  `board_x` smallint(5) unsigned NOT NULL,&lt;br /&gt;
  `board_y` smallint(5) unsigned NOT NULL,&lt;br /&gt;
  `board_player` int(10) unsigned DEFAULT NULL,&lt;br /&gt;
  PRIMARY KEY (`board_x`,`board_y`)&lt;br /&gt;
) ENGINE=InnoDB DEFAULT CHARSET=utf8;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Add the above SQL to &amp;lt;code&amp;gt;dbmodel.sql&amp;lt;/code&amp;gt;. Pay special attention to the backtick &amp;lt;code&amp;gt;`&amp;lt;/code&amp;gt; character vs. the single quote &amp;lt;code&amp;gt;&#039;&amp;lt;/code&amp;gt; when working with SQL. &lt;br /&gt;
&lt;br /&gt;
=== Test the Table ===&lt;br /&gt;
Now, a new database with a &amp;lt;code&amp;gt;board&amp;lt;/code&amp;gt; table will be created each time we start a Reversi game. This is why after modifying our &amp;lt;code&amp;gt;dbmodel.sql&amp;lt;/code&amp;gt; it&#039;s a good time to stop your current game &amp;amp; start a new game.&lt;br /&gt;
&lt;br /&gt;
Start a new game and verify a table is created.&lt;br /&gt;
&lt;br /&gt;
== Setup the initial game position ==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note&#039;&#039;&#039;: From now on, you must launch the game with &#039;&#039;&#039;two players&#039;&#039;&#039; to get two &amp;lt;code&amp;gt;player_id&amp;lt;/code&amp;gt;s within the database. Otherwise, the game will crash.&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;setupNewGame&amp;lt;/code&amp;gt; method of our &amp;lt;code&amp;gt;reversi.game.php&amp;lt;/code&amp;gt; is called during initial setup. This initializes our data and places the starting tokens on the board. At the beginning of the game, there should be 4 tokens on the board.&lt;br /&gt;
&lt;br /&gt;
=== Initialize the Board in .game.php file ===&lt;br /&gt;
Under &amp;lt;code&amp;gt;// TODO: setup the initial game situation here&amp;lt;/code&amp;gt;, initialize the board&amp;lt;pre&amp;gt;&lt;br /&gt;
        // Init the board&lt;br /&gt;
        $sql = &amp;quot;INSERT INTO board (board_x,board_y,board_player) VALUES &amp;quot;;&lt;br /&gt;
        $sql_values = array();&lt;br /&gt;
        list( $blackplayer_id, $whiteplayer_id ) = array_keys( $players );&lt;br /&gt;
        for( $x=1; $x&amp;lt;=8; $x++ )&lt;br /&gt;
        {&lt;br /&gt;
            for( $y=1; $y&amp;lt;=8; $y++ )&lt;br /&gt;
            {&lt;br /&gt;
                $token_value = &amp;quot;NULL&amp;quot;;&lt;br /&gt;
                if( ($x==4 &amp;amp;&amp;amp; $y==4) || ($x==5 &amp;amp;&amp;amp; $y==5) )  // Initial positions of white player&lt;br /&gt;
                    $token_value = &amp;quot;&#039;$whiteplayer_id&#039;&amp;quot;;&lt;br /&gt;
                else if( ($x==4 &amp;amp;&amp;amp; $y==5) || ($x==5 &amp;amp;&amp;amp; $y==4) )  // Initial positions of black player&lt;br /&gt;
                    $token_value = &amp;quot;&#039;$blackplayer_id&#039;&amp;quot;;&lt;br /&gt;
                    &lt;br /&gt;
                $sql_values[] = &amp;quot;(&#039;$x&#039;,&#039;$y&#039;,$token_value)&amp;quot;;&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
        $sql .= implode( &#039;,&#039;, $sql_values );&lt;br /&gt;
        $this-&amp;gt;DbQuery( $sql );&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Board Initialization Explanation ====&lt;br /&gt;
&lt;br /&gt;
* We create one table entry for each square, with a &amp;lt;code&amp;gt;NULL&amp;lt;/code&amp;gt; value which means &amp;quot;empty square&amp;quot;&lt;br /&gt;
* On 4 of the squares, we place an initial token.&lt;br /&gt;
&lt;br /&gt;
After this, we set &amp;lt;code&amp;gt;activeNextPlayer&amp;lt;/code&amp;gt; to make the first player active at the beginning of the game (this line is already present in the default code template).&lt;br /&gt;
&lt;br /&gt;
If you didn&#039;t do it earlier, you need to remove the call to &amp;lt;code&amp;gt;this-&amp;gt;reattributeColorsBasedOnPreferences()&amp;lt;/code&amp;gt; in &amp;lt;code&amp;gt;SetupNewGame()&amp;lt;/code&amp;gt;. If you don&#039;t, player color preferences will try (and fail) to override the two colors supported here.&lt;br /&gt;
&lt;br /&gt;
=== Show the Initial Token Setup ===&lt;br /&gt;
Now, we need to make these tokens appear on the client side. The first step is to return the token positions with our &amp;lt;code&amp;gt;getAllDatas()&amp;lt;/code&amp;gt; PHP method. &amp;lt;code&amp;gt;getAllDatas()&amp;lt;/code&amp;gt; is called during each page reload.&lt;br /&gt;
&lt;br /&gt;
In the &amp;lt;code&amp;gt;getAllDatas()&amp;lt;/code&amp;gt; method, after &amp;lt;code&amp;gt;// TODO: Gather all information about current game situation (visible by player $current_player_id)&amp;lt;/code&amp;gt;, add the following lines:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        // Get reversi board token&lt;br /&gt;
        $result[&#039;board&#039;] = self::getObjectListFromDB( &amp;quot;SELECT board_x x, board_y y, board_player player&lt;br /&gt;
                                                       FROM board&lt;br /&gt;
                                                       WHERE board_player IS NOT NULL&amp;quot; );&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Next, you may need to modify the query that gets player information to also get the player&#039;s colors. This is in the variable &amp;lt;code&amp;gt;$sql&amp;lt;/code&amp;gt;, above the lines you just inserted in &amp;lt;code&amp;gt;getAllDatas()&amp;lt;/code&amp;gt;. Below is what the line will look like. Notice how we&#039;ve added &amp;lt;code&amp;gt;player_color color&amp;lt;/code&amp;gt; to the sql query.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$sql = &amp;quot;SELECT player_id id, player_score score, player_color color FROM player &amp;quot;;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
We are using the BGA framework&#039;s &amp;lt;code&amp;gt;getObjectListFromDB()&amp;lt;/code&amp;gt; that formats the result of this SQL query in a PHP array with x, y and player attributes. We add it to the result associative array with the key &amp;lt;code&amp;gt;board&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Last, we process this array client side. Let&#039;s place a token on the board for each array item. We&#039;ll do this in our Javascript &amp;lt;code&amp;gt;setup&amp;lt;/code&amp;gt; method under the code we added to generate the squares. &lt;br /&gt;
&lt;br /&gt;
This will result in a removal or edit of the previously added line &amp;lt;code&amp;gt;this.addDiscOnBoard(2, 2, this.player_id);&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
for( var i in gamedatas.board )&lt;br /&gt;
{&lt;br /&gt;
    var square = gamedatas.board[i];&lt;br /&gt;
    &lt;br /&gt;
    if( square.player !== null )&lt;br /&gt;
    {&lt;br /&gt;
        this.addDiscOnBoard( square.x, square.y, square.player );&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;board&amp;lt;/code&amp;gt; entry created in &amp;lt;code&amp;gt;getAllDatas()&amp;lt;/code&amp;gt; is used here as &amp;lt;code&amp;gt;gamedatas.board&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Test the Game Start ===&lt;br /&gt;
Reload... and here we are:&lt;br /&gt;
&lt;br /&gt;
[[File:reversi5.jpg]]&lt;br /&gt;
&lt;br /&gt;
It starts to feel like Reversi here...&lt;br /&gt;
&lt;br /&gt;
== The game state machine ==&lt;br /&gt;
&lt;br /&gt;
Stop your game, again. You&#039;re about to start the core game logic.&lt;br /&gt;
&lt;br /&gt;
You already read [http://www.slideshare.net/boardgamearena/bga-studio-focus-on-bga-game-state-machine Focus on BGA game state machine], so you know that this is the heart of your game logic. For reversi, it&#039;s relatively simple. Here&#039;s a diagram of our game state machine:&lt;br /&gt;
&lt;br /&gt;
[[File:reversi6.jpg]]&lt;br /&gt;
&lt;br /&gt;
=== Build your States ===&lt;br /&gt;
And here&#039;s our &amp;lt;code&amp;gt;states.inc.php&amp;lt;/code&amp;gt;, according to this diagram:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$machinestates = array(&lt;br /&gt;
&lt;br /&gt;
    ST_BGA_GAME_SETUP =&amp;gt; array(&lt;br /&gt;
        &amp;quot;name&amp;quot; =&amp;gt; &amp;quot;gameSetup&amp;quot;,&lt;br /&gt;
        &amp;quot;description&amp;quot; =&amp;gt; clienttranslate(&amp;quot;Game setup&amp;quot;),&lt;br /&gt;
        &amp;quot;type&amp;quot; =&amp;gt; &amp;quot;manager&amp;quot;,&lt;br /&gt;
        &amp;quot;action&amp;quot; =&amp;gt; &amp;quot;stGameSetup&amp;quot;,&lt;br /&gt;
        &amp;quot;transitions&amp;quot; =&amp;gt; array( &amp;quot;&amp;quot; =&amp;gt; ST_PLAYER_PLAY_DISC )&lt;br /&gt;
    ),&lt;br /&gt;
    &lt;br /&gt;
    ST_PLAYER_PLAY_DISC =&amp;gt; array(&lt;br /&gt;
        &amp;quot;name&amp;quot; =&amp;gt; &amp;quot;playerTurn&amp;quot;,&lt;br /&gt;
		&amp;quot;description&amp;quot; =&amp;gt; clienttranslate(&#039;${actplayer} must play a disc&#039;),&lt;br /&gt;
		&amp;quot;descriptionmyturn&amp;quot; =&amp;gt; clienttranslate(&#039;${you} must play a disc&#039;),&lt;br /&gt;
        &amp;quot;type&amp;quot; =&amp;gt; &amp;quot;activeplayer&amp;quot;,&lt;br /&gt;
        &amp;quot;args&amp;quot; =&amp;gt; &amp;quot;argPlayerTurn&amp;quot;,&lt;br /&gt;
        &amp;quot;possibleactions&amp;quot; =&amp;gt; array( &#039;actPlayDisc&#039; ),&lt;br /&gt;
        &amp;quot;transitions&amp;quot; =&amp;gt; array( &amp;quot;playDisc&amp;quot; =&amp;gt; ST_NEXT_PLAYER, &amp;quot;zombiePass&amp;quot; =&amp;gt; ST_NEXT_PLAYER )&lt;br /&gt;
    ),&lt;br /&gt;
    &lt;br /&gt;
    ST_NEXT_PLAYER =&amp;gt; array(&lt;br /&gt;
        &amp;quot;name&amp;quot; =&amp;gt; &amp;quot;nextPlayer&amp;quot;,&lt;br /&gt;
        &amp;quot;type&amp;quot; =&amp;gt; &amp;quot;game&amp;quot;,&lt;br /&gt;
        &amp;quot;action&amp;quot; =&amp;gt; &amp;quot;stNextPlayer&amp;quot;,&lt;br /&gt;
        &amp;quot;updateGameProgression&amp;quot; =&amp;gt; true,        &lt;br /&gt;
        &amp;quot;transitions&amp;quot; =&amp;gt; array( &amp;quot;nextTurn&amp;quot; =&amp;gt; ST_PLAYER_PLAY_DISC, &amp;quot;cantPlay&amp;quot; =&amp;gt; ST_NEXT_PLAYER, &amp;quot;endGame&amp;quot; =&amp;gt; ST_END_GAME )&lt;br /&gt;
    ),&lt;br /&gt;
   &lt;br /&gt;
    ST_END_GAME =&amp;gt; array(&lt;br /&gt;
        &amp;quot;name&amp;quot; =&amp;gt; &amp;quot;gameEnd&amp;quot;,&lt;br /&gt;
        &amp;quot;description&amp;quot; =&amp;gt; clienttranslate(&amp;quot;End of game&amp;quot;),&lt;br /&gt;
        &amp;quot;type&amp;quot; =&amp;gt; &amp;quot;manager&amp;quot;,&lt;br /&gt;
        &amp;quot;action&amp;quot; =&amp;gt; &amp;quot;stGameEnd&amp;quot;,&lt;br /&gt;
        &amp;quot;args&amp;quot; =&amp;gt; &amp;quot;argGameEnd&amp;quot;&lt;br /&gt;
    )&lt;br /&gt;
&lt;br /&gt;
);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We used constants to give an index to the different states. This is to avoid mistakes when we reuse these indexes on the transitions array.&lt;br /&gt;
&lt;br /&gt;
Let&#039;s create a file you&#039;ll put in &amp;lt;code&amp;gt;modules/php/constants.inc.php&amp;lt;/code&amp;gt; :&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;?php&lt;br /&gt;
&lt;br /&gt;
/*&lt;br /&gt;
 * State constants&lt;br /&gt;
 */&lt;br /&gt;
const ST_BGA_GAME_SETUP = 1;&lt;br /&gt;
&lt;br /&gt;
const ST_PLAYER_PLAY_DISC = 10;&lt;br /&gt;
const ST_NEXT_PLAYER = 11;&lt;br /&gt;
&lt;br /&gt;
const ST_END_GAME = 99;&lt;br /&gt;
&lt;br /&gt;
?&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You will also need to add &amp;lt;code&amp;gt;require_once(&amp;quot;modules/php/constants.inc.php&amp;quot;);&amp;lt;/code&amp;gt; at the beginning of the state.inc.php to load these constants.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Now, in &amp;lt;code&amp;gt;reversi.game.php&amp;lt;/code&amp;gt; let&#039;s create the methods that are declared in this game states description file:&lt;br /&gt;
* &amp;lt;code&amp;gt;argPlayerTurn&amp;lt;/code&amp;gt;: referenced in the &amp;lt;code&amp;gt;args&amp;lt;/code&amp;gt; property of the &amp;lt;code&amp;gt;playerTurn&amp;lt;/code&amp;gt; state; this is the name of the method to call to retrieve arguments for this gamestate. Arguments are sent to the client side to be used on &amp;lt;code&amp;gt;onEnteringState&amp;lt;/code&amp;gt; or to set arguments in the gamestate description.&lt;br /&gt;
* &amp;lt;code&amp;gt;stNextPlayer&amp;lt;/code&amp;gt;: referenced in the &amp;lt;code&amp;gt;action&amp;lt;/code&amp;gt; property of the &amp;lt;code&amp;gt;nextPlayer&amp;lt;/code&amp;gt; state; this is the name of the method to call when this game state become the current game state.&lt;br /&gt;
&lt;br /&gt;
=== Test Your States ===&lt;br /&gt;
... and start a new Reversi game.&lt;br /&gt;
&lt;br /&gt;
As you can see on the screen capture below, the BGA framework makes the game jump to our first game state &amp;lt;code&amp;gt;playerTurn&amp;lt;/code&amp;gt; right after the initial setup. That&#039;s why the status bar contains the description of &amp;lt;code&amp;gt;playerTurn&amp;lt;/code&amp;gt; state (&amp;quot;XXXX must play a disc&amp;quot;):&lt;br /&gt;
&lt;br /&gt;
[[File:reversi7.jpg]]&lt;br /&gt;
&lt;br /&gt;
== The rules ==&lt;br /&gt;
&lt;br /&gt;
We will use the &amp;lt;code&amp;gt;getPossibleMoves&amp;lt;/code&amp;gt; PHP method to:&lt;br /&gt;
* Indicate to the current player where she is allowed to play by returning a list of coordinates&lt;br /&gt;
* Check if the player has the right to play in the spot they choose&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;&lt;br /&gt;
Example of getPossibleMoves here https://gist.github.com/leocaseiro/a8bc2851bd0caddd06685b5035937d15&lt;br /&gt;
&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This is pure PHP programming here, and there are no special things from the BGA framework that can be used. This is why we won&#039;t go into details here. The overall idea is:&lt;br /&gt;
* Create a &amp;lt;code&amp;gt;getTurnedOverDiscs(x,y)&amp;lt;/code&amp;gt; method that returns coordinates of discs that would be turned over if a token would be played at &amp;lt;code&amp;gt;x&amp;lt;/code&amp;gt;,&amp;lt;code&amp;gt;y&amp;lt;/code&amp;gt;.&lt;br /&gt;
* Loop through all free squares of the board and call the &amp;lt;code&amp;gt;getTurnedOverDiscs&amp;lt;/code&amp;gt; method on each of them. If at least 1 token is turned over, this is a valid move.&lt;br /&gt;
&lt;br /&gt;
IMPORTANT: Making a database query is slow! Please don&#039;t load the entire game board with a SQL query multiple times. In our implementation, we load the entire board once at the beginning of &amp;lt;code&amp;gt;getPossibleMoves&amp;lt;/code&amp;gt;, and then pass the board as an argument to all methods.&lt;br /&gt;
&lt;br /&gt;
If you want to look into details, please look at the &amp;quot;utility method&amp;quot; sections of &amp;lt;code&amp;gt;reversi.game.php&amp;lt;/code&amp;gt;. If building the tutorial yourself, copy the functions under &amp;quot;Utility functions&amp;quot; comment from the Reversi tutorial.&lt;br /&gt;
&lt;br /&gt;
== Display allowed moves ==&lt;br /&gt;
&lt;br /&gt;
Now we want to highlight the squares where the player can place a disc.&lt;br /&gt;
&lt;br /&gt;
To do this, we add a &amp;lt;code&amp;gt;argPlayerTurn&amp;lt;/code&amp;gt; method in &amp;lt;code&amp;gt;reversi.game.php&amp;lt;/code&amp;gt;. This method is called on the server each time we enter into &amp;lt;code&amp;gt;playerTurn&amp;lt;/code&amp;gt; game state, and its result is transferred automatically to the client-side:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
function argPlayerTurn(): array&lt;br /&gt;
{&lt;br /&gt;
    return [&lt;br /&gt;
        &#039;possibleMoves&#039; =&amp;gt; $this-&amp;gt;getPossibleMoves( intval($this-&amp;gt;getActivePlayerId()) )&lt;br /&gt;
    ];&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We use the &amp;lt;code&amp;gt;getPossibleMoves&amp;lt;/code&amp;gt; method we just developed.&lt;br /&gt;
&lt;br /&gt;
Each time we enter into a new game state, we use the &amp;lt;code&amp;gt;onEnteringState&amp;lt;/code&amp;gt; Javascript method (in the &amp;lt;code&amp;gt;reversi.js&amp;lt;/code&amp;gt; file, under &amp;quot;Game &amp;amp; client states&amp;quot;). This lets us use the data returned by the method above on the client side.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        onEnteringState: function( stateName, args )&lt;br /&gt;
        {&lt;br /&gt;
           console.log( &#039;Entering state: &#039;+stateName );&lt;br /&gt;
            &lt;br /&gt;
            switch( stateName )&lt;br /&gt;
            {&lt;br /&gt;
            case &#039;playerTurn&#039;:&lt;br /&gt;
                this.updatePossibleMoves( args.args.possibleMoves );&lt;br /&gt;
                break;&lt;br /&gt;
            }&lt;br /&gt;
        },&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
So, when we enter into &amp;lt;code&amp;gt;playerTurn&amp;lt;/code&amp;gt; game state, we call our &amp;lt;code&amp;gt;updatePossibleMoves&amp;lt;/code&amp;gt; method (under the &amp;quot;Utility methods&amp;quot; section). This method looks like this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
updatePossibleMoves: function( possibleMoves )&lt;br /&gt;
{&lt;br /&gt;
    // Remove current possible moves&lt;br /&gt;
    document.querySelectorAll(&#039;.possibleMove&#039;).forEach(div =&amp;gt; div.classList.remove(&#039;possibleMove&#039;));&lt;br /&gt;
&lt;br /&gt;
    for( var x in possibleMoves )&lt;br /&gt;
    {&lt;br /&gt;
        for( var y in possibleMoves[ x ] )&lt;br /&gt;
        {&lt;br /&gt;
            // x,y is a possible move&lt;br /&gt;
            document.getElementById(`square_${x}_${y}`).classList.add(&#039;possibleMove&#039;);&lt;br /&gt;
        }            &lt;br /&gt;
    }&lt;br /&gt;
                &lt;br /&gt;
    this.addTooltipToClass( &#039;possibleMove&#039;, &#039;&#039;, _(&#039;Place a disc here&#039;) );&lt;br /&gt;
},&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Here&#039;s what this does. At first, it removes all &amp;lt;code&amp;gt;possibleMove&amp;lt;/code&amp;gt; classes currently applied with the very useful &amp;lt;code&amp;gt;document.querySelectorAll&amp;lt;/code&amp;gt; method.&lt;br /&gt;
&lt;br /&gt;
Then it loops through all possible moves our PHP &amp;lt;code&amp;gt;updatePossibleMoves&amp;lt;/code&amp;gt; function created for us, and adds the &amp;lt;code&amp;gt;possibleMove&amp;lt;/code&amp;gt; class to each corresponding square.&lt;br /&gt;
&lt;br /&gt;
Finally, it uses the BGA framework &amp;lt;code&amp;gt;addTooltipToClass&amp;lt;/code&amp;gt; method to associate a tooltip to all those highlighted squares so that players can understand their meaning.&lt;br /&gt;
&lt;br /&gt;
To see the possible moves we need to create a CSS class (&amp;lt;code&amp;gt;possibleMove&amp;lt;/code&amp;gt;) that can be applied to a &amp;lt;code&amp;gt;square&amp;lt;/code&amp;gt; element to highlight it:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
.possibleMove {&lt;br /&gt;
    background-color: white;&lt;br /&gt;
    opacity: 0.2; &lt;br /&gt;
    cursor: pointer;  &lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
And here we are:&lt;br /&gt;
&lt;br /&gt;
[[File:reversi8.jpg.jpg]]&lt;br /&gt;
&lt;br /&gt;
== Let&#039;s play ==&lt;br /&gt;
&lt;br /&gt;
From now, it&#039;s better to restart a game with 2 players, because we are going to implement a complete Reversi turn. The summary of what we are going to do is:&lt;br /&gt;
* When we click on a &amp;lt;code&amp;gt;possibleMove&amp;lt;/code&amp;gt; square, send the move to the server.&lt;br /&gt;
* Server side, check the move is correct, apply Reversi rules and jump to next player.&lt;br /&gt;
* Client side, change the token position to reflect the move.&lt;br /&gt;
&lt;br /&gt;
First we associate each click on a square to one of our methods using our Javascript &amp;lt;code&amp;gt;setup&amp;lt;/code&amp;gt; method:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
document.querySelectorAll(&#039;.square&#039;).forEach(square =&amp;gt; square.addEventListener(&#039;click&#039;, e =&amp;gt; this.onPlayDisc(e)));&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note the use of the &amp;quot;dojo.query&amp;quot; method to get all HTML elements with &amp;quot;square&amp;quot; class in just one function call. Now, our &amp;quot;onPlayDisc&amp;quot; method is called each time someone clicks on a square.&lt;br /&gt;
&lt;br /&gt;
Here&#039;s our &amp;quot;onPlayDisc&amp;quot; method below:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
onPlayDisc: function( evt )&lt;br /&gt;
{&lt;br /&gt;
    // Stop this event propagation&lt;br /&gt;
    evt.preventDefault();&lt;br /&gt;
    evt.stopPropagation();&lt;br /&gt;
&lt;br /&gt;
    // Get the cliqued square x and y&lt;br /&gt;
    // Note: square id format is &amp;quot;square_X_Y&amp;quot;&lt;br /&gt;
    var coords = evt.currentTarget.id.split(&#039;_&#039;);&lt;br /&gt;
    var x = coords[1];&lt;br /&gt;
    var y = coords[2];&lt;br /&gt;
&lt;br /&gt;
    if(!document.getElementById(`square_${x}_${y}`).classList.contains(&#039;possibleMove&#039;)) {&lt;br /&gt;
        // This is not a possible move =&amp;gt; the click does nothing&lt;br /&gt;
        return ;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    this.bgaPerformAction(&amp;quot;actPlayDisc&amp;quot;, {&lt;br /&gt;
        x:x,&lt;br /&gt;
        y:y&lt;br /&gt;
    });&lt;br /&gt;
},&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
What we do here is:&lt;br /&gt;
* We stop the propagation of the Javascript &amp;lt;code&amp;gt;onclick&amp;lt;/code&amp;gt; event. Otherwise, it can lead to random behavior so it&#039;s always a good idea.&lt;br /&gt;
* We get the x/y coordinates of the square by using &amp;lt;code&amp;gt;evt.currentTarget.id&amp;lt;/code&amp;gt;&lt;br /&gt;
* We check that clicked square has the &amp;lt;code&amp;gt;possibleMove&amp;lt;/code&amp;gt; class, otherwise we know for sure that we can&#039;t play there.&lt;br /&gt;
* Finally, we make a call to the server using BGA &amp;lt;code&amp;gt;bgaPerformAction&amp;lt;/code&amp;gt; method with argument x and y. This call will check that &amp;lt;code&amp;gt;actPlayDisc&amp;lt;/code&amp;gt; action is possible, according to current game state (see &amp;lt;code&amp;gt;possibleactions&amp;lt;/code&amp;gt; entry in our &amp;lt;code&amp;gt;playerTurn&amp;lt;/code&amp;gt; game state defined above). This check is important to avoid issues if a player double clicks on a square.&lt;br /&gt;
&lt;br /&gt;
Now, we have to manage this &amp;lt;code&amp;gt;actPlayDisc&amp;lt;/code&amp;gt; action on the server side. Add a corresponding &amp;lt;code&amp;gt;actPlayDisc&amp;lt;/code&amp;gt; method in our game logic (&amp;lt;code&amp;gt;reversi.game.php&amp;lt;/code&amp;gt;):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
function actPlayDisc( int $x, int $y )&lt;br /&gt;
{&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
(The function will be called when the front-side action is triggered using the Autowire mechanism, if you want to see how it works in details check https://en.doc.boardgamearena.com/Main_game_logic:_yourgamename.game.php#Actions_%28autowired%29 )&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        $player_id = intval($this-&amp;gt;getActivePlayerId()); &lt;br /&gt;
        &lt;br /&gt;
        // Now, check if this is a possible move&lt;br /&gt;
        $board = $this-&amp;gt;getBoard();&lt;br /&gt;
        $turnedOverDiscs = $this-&amp;gt;getTurnedOverDiscs( $x, $y, $player_id, $board );&lt;br /&gt;
        &lt;br /&gt;
        if( count( $turnedOverDiscs ) &amp;gt; 0 )&lt;br /&gt;
        {&lt;br /&gt;
            // This move is possible!&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
...now, we are using the &amp;lt;code&amp;gt;getTurnedOverDiscs&amp;lt;/code&amp;gt; method again to check that this move is possible.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
            // Let&#039;s place a disc at x,y and return all &amp;quot;$returned&amp;quot; discs to the active player&lt;br /&gt;
            &lt;br /&gt;
            $sql = &amp;quot;UPDATE board SET board_player=&#039;$player_id&#039;&lt;br /&gt;
                    WHERE ( board_x, board_y) IN ( &amp;quot;;&lt;br /&gt;
            &lt;br /&gt;
            foreach( $turnedOverDiscs as $turnedOver )&lt;br /&gt;
            {&lt;br /&gt;
                $sql .= &amp;quot;(&#039;&amp;quot;.$turnedOver[&#039;x&#039;].&amp;quot;&#039;,&#039;&amp;quot;.$turnedOver[&#039;y&#039;].&amp;quot;&#039;),&amp;quot;;&lt;br /&gt;
            }&lt;br /&gt;
            $sql .= &amp;quot;(&#039;$x&#039;,&#039;$y&#039;) ) &amp;quot;;&lt;br /&gt;
                       &lt;br /&gt;
            $this-&amp;gt;DbQuery( $sql );&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
... we update the database to change the color of all turned over disc + the disc we just placed.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
            // Update scores according to the number of disc on board&lt;br /&gt;
            $sql = &amp;quot;UPDATE player&lt;br /&gt;
                    SET player_score = (&lt;br /&gt;
                    SELECT COUNT( board_x ) FROM board WHERE board_player=player_id&lt;br /&gt;
                    )&amp;quot;;&lt;br /&gt;
            $this-&amp;gt;DbQuery( $sql );&lt;br /&gt;
            &lt;br /&gt;
            // Statistics&lt;br /&gt;
            $this-&amp;gt;incStat( count( $turnedOverDiscs ), &amp;quot;turnedOver&amp;quot;, $player_id );&lt;br /&gt;
            if( ($x==1 &amp;amp;&amp;amp; $y==1) || ($x==8 &amp;amp;&amp;amp; $y==1) || ($x==1 &amp;amp;&amp;amp; $y==8) || ($x==8 &amp;amp;&amp;amp; $y==8) )&lt;br /&gt;
                $this-&amp;gt;incStat( 1, &#039;discPlayedOnCorner&#039;, $player_id );&lt;br /&gt;
            else if( $x==1 || $x==8 || $y==1 || $y==8 )&lt;br /&gt;
                $this-&amp;gt;incStat( 1, &#039;discPlayedOnBorder&#039;, $player_id );&lt;br /&gt;
            else if( $x&amp;gt;=3 &amp;amp;&amp;amp; $x&amp;lt;=6 &amp;amp;&amp;amp; $y&amp;gt;=3 &amp;amp;&amp;amp; $y&amp;lt;=6 )&lt;br /&gt;
                $this-&amp;gt;incStat( 1, &#039;discPlayedOnCenter&#039;, $player_id );&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
... now, we update both player score by counting all disc, and we manage game statistics.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
            // Notify&lt;br /&gt;
            $this-&amp;gt;notifyAllPlayers( &amp;quot;playDisc&amp;quot;, clienttranslate( &#039;${player_name} plays a disc and turns over ${returned_nbr} disc(s)&#039; ), array(&lt;br /&gt;
                &#039;player_id&#039; =&amp;gt; $player_id,&lt;br /&gt;
                &#039;player_name&#039; =&amp;gt; $this-&amp;gt;getActivePlayerName(),&lt;br /&gt;
                &#039;returned_nbr&#039; =&amp;gt; count( $turnedOverDiscs ),&lt;br /&gt;
                &#039;x&#039; =&amp;gt; $x,&lt;br /&gt;
                &#039;y&#039; =&amp;gt; $y&lt;br /&gt;
            ) );&lt;br /&gt;
&lt;br /&gt;
            $this-&amp;gt;notifyAllPlayers( &amp;quot;turnOverDiscs&amp;quot;, &#039;&#039;, array(&lt;br /&gt;
                &#039;player_id&#039; =&amp;gt; $player_id,&lt;br /&gt;
                &#039;turnedOver&#039; =&amp;gt; $turnedOverDiscs&lt;br /&gt;
            ) );&lt;br /&gt;
            &lt;br /&gt;
            $newScores = $this-&amp;gt;getCollectionFromDb( &amp;quot;SELECT player_id, player_score FROM player&amp;quot;, true );&lt;br /&gt;
            $this-&amp;gt;notifyAllPlayers( &amp;quot;newScores&amp;quot;, &amp;quot;&amp;quot;, array(&lt;br /&gt;
                &amp;quot;scores&amp;quot; =&amp;gt; $newScores&lt;br /&gt;
            ) );&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
... then we notify about all these changes. We are using for that 3 notifications (&amp;lt;code&amp;gt;playDisc&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;turnOverDiscs&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;newScores&amp;lt;/code&amp;gt; that we are going to implement on client side later). Note that the description of the &amp;lt;code&amp;gt;playDisc&amp;lt;/code&amp;gt; notification will be logged in the game log.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
            // Then, go to the next state&lt;br /&gt;
            $this-&amp;gt;gamestate-&amp;gt;nextState( &#039;playDisc&#039; );&lt;br /&gt;
        }&lt;br /&gt;
        else&lt;br /&gt;
            throw new BgaSystemException( &amp;quot;Impossible move&amp;quot; );&lt;br /&gt;
    }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
... finally, we jump to the next game state if everything goes fine (&amp;lt;code&amp;gt;playDisc&amp;lt;/code&amp;gt; is the name of a transition in the &amp;lt;code&amp;gt;playerTurn&amp;lt;/code&amp;gt; game state description above which leads to state 11 which is &amp;lt;code&amp;gt;nextPlayer&amp;lt;/code&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
To make the statistics work, we have to initialize them in &amp;lt;code&amp;gt;stats.json&amp;lt;/code&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
  &amp;quot;player&amp;quot;: {&lt;br /&gt;
    &amp;quot;discPlayedOnCorner&amp;quot;: {&lt;br /&gt;
      &amp;quot;id&amp;quot;: 10,&lt;br /&gt;
      &amp;quot;name&amp;quot;: &amp;quot;Discs played on a corner&amp;quot;,&lt;br /&gt;
      &amp;quot;type&amp;quot;: &amp;quot;int&amp;quot;&lt;br /&gt;
    },&lt;br /&gt;
    &amp;quot;discPlayedOnBorder&amp;quot;: {&lt;br /&gt;
      &amp;quot;id&amp;quot;: 11,&lt;br /&gt;
      &amp;quot;name&amp;quot;: &amp;quot;Discs played on a border&amp;quot;,&lt;br /&gt;
      &amp;quot;type&amp;quot;: &amp;quot;int&amp;quot;&lt;br /&gt;
    },&lt;br /&gt;
    &amp;quot;discPlayedOnCenter&amp;quot;: {&lt;br /&gt;
      &amp;quot;id&amp;quot;: 12,&lt;br /&gt;
      &amp;quot;name&amp;quot;: &amp;quot;Discs played on board center part&amp;quot;,&lt;br /&gt;
      &amp;quot;type&amp;quot;: &amp;quot;int&amp;quot;&lt;br /&gt;
    },&lt;br /&gt;
    &amp;quot;turnedOver&amp;quot;: {&lt;br /&gt;
      &amp;quot;id&amp;quot;: 13,&lt;br /&gt;
      &amp;quot;name&amp;quot;: &amp;quot;Number of discs turned over&amp;quot;,&lt;br /&gt;
      &amp;quot;type&amp;quot;: &amp;quot;int&amp;quot;&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
A last thing to do on the server side is to activate the next player when we enter the &amp;lt;code&amp;gt;nextPlayer&amp;lt;/code&amp;gt; game state (in the &amp;lt;code&amp;gt;reversi.game.php&amp;lt;/code&amp;gt; file, under &amp;quot;Game state reactions&amp;quot;):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    function stNextPlayer(): void&lt;br /&gt;
    {&lt;br /&gt;
        // Active next player&lt;br /&gt;
        $player_id = intval($this-&amp;gt;activeNextPlayer());&lt;br /&gt;
&lt;br /&gt;
        // Check if both player has at least 1 discs, and if there are free squares to play&lt;br /&gt;
        $player_to_discs = $this-&amp;gt;getCollectionFromDb( &amp;quot;SELECT board_player, COUNT( board_x )&lt;br /&gt;
                                                       FROM board&lt;br /&gt;
                                                       GROUP BY board_player&amp;quot;, true );&lt;br /&gt;
&lt;br /&gt;
        if( ! isset( $player_to_discs[ null ] ) )&lt;br /&gt;
        {&lt;br /&gt;
            // Index 0 has not been set =&amp;gt; there&#039;s no more free place on the board !&lt;br /&gt;
            // =&amp;gt; end of the game&lt;br /&gt;
            $this-&amp;gt;gamestate-&amp;gt;nextState( &#039;endGame&#039; );&lt;br /&gt;
            return ;&lt;br /&gt;
        }&lt;br /&gt;
        else if( ! isset( $player_to_discs[ $player_id ] ) )&lt;br /&gt;
        {&lt;br /&gt;
            // Active player has no more disc on the board =&amp;gt; he looses immediately&lt;br /&gt;
            $this-&amp;gt;gamestate-&amp;gt;nextState( &#039;endGame&#039; );&lt;br /&gt;
            return ;&lt;br /&gt;
        }&lt;br /&gt;
        &lt;br /&gt;
        // Can this player play?&lt;br /&gt;
&lt;br /&gt;
        $possibleMoves = $this-&amp;gt;getPossibleMoves( $player_id );&lt;br /&gt;
        if( count( $possibleMoves ) == 0 )&lt;br /&gt;
        {&lt;br /&gt;
&lt;br /&gt;
            // This player can&#039;t play&lt;br /&gt;
            // Can his opponent play ?&lt;br /&gt;
            $opponent_id = (int)$this-&amp;gt;getUniqueValueFromDb( &amp;quot;SELECT player_id FROM player WHERE player_id!=&#039;$player_id&#039; &amp;quot; );&lt;br /&gt;
            if( count( $this-&amp;gt;getPossibleMoves( $opponent_id ) ) == 0 )&lt;br /&gt;
            {&lt;br /&gt;
                // Nobody can move =&amp;gt; end of the game&lt;br /&gt;
                $this-&amp;gt;gamestate-&amp;gt;nextState( &#039;endGame&#039; );&lt;br /&gt;
            }&lt;br /&gt;
            else&lt;br /&gt;
            {            &lt;br /&gt;
                // =&amp;gt; pass his turn&lt;br /&gt;
                $this-&amp;gt;gamestate-&amp;gt;nextState( &#039;cantPlay&#039; );&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
        else&lt;br /&gt;
        {&lt;br /&gt;
            // This player can play. Give him some extra time&lt;br /&gt;
            $this-&amp;gt;giveExtraTime( $player_id );&lt;br /&gt;
            $this-&amp;gt;gamestate-&amp;gt;nextState( &#039;nextTurn&#039; );&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Now, when we play a token, the rules are checked and the token appears in the database.&lt;br /&gt;
&lt;br /&gt;
[[File:reversi9.jpg]]&lt;br /&gt;
&lt;br /&gt;
Of course, as we don&#039;t manage notifications on client side, we need to press F5 after each move to see the changes on the board.&lt;br /&gt;
&lt;br /&gt;
== Make the move appear automatically ==&lt;br /&gt;
&lt;br /&gt;
Now, what we have to do is process the notifications sent by the server and make the move appear on the interface.&lt;br /&gt;
&lt;br /&gt;
In our &amp;lt;code&amp;gt;setupNotifications&amp;lt;/code&amp;gt; method in &amp;lt;code&amp;gt;reversi.js&amp;lt;/code&amp;gt;, we register 2 methods for the 2 notifications we created at the previous step (&amp;lt;code&amp;gt;playDisc&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;turnOverDiscs&amp;lt;/code&amp;gt;):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
            const notifs = [&lt;br /&gt;
                [&#039;playDisc&#039;, 500],&lt;br /&gt;
                [&#039;turnOverDiscs&#039;, 1500],&lt;br /&gt;
                [&#039;newScores&#039;, 1],&lt;br /&gt;
            ];&lt;br /&gt;
    &lt;br /&gt;
            notifs.forEach((notif) =&amp;gt; {&lt;br /&gt;
                dojo.subscribe(notif[0], this, `notif_${notif[0]}`);&lt;br /&gt;
                this.notifqueue.setSynchronous(notif[0], notif[1]);&lt;br /&gt;
            });&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We will associate each of our 3 notifications with a method prefixed with &amp;lt;code&amp;gt;notif_&amp;lt;/code&amp;gt;. We also define these notifications as &amp;quot;synchronous&amp;quot;, with a duration in millisecond. It tells the user interface to wait some time after executing the notification, to let the animation end before starting the next notification. In our specific case, the animation will be the following:&lt;br /&gt;
* Make a disc slide from the player panel to its place on the board&lt;br /&gt;
* (wait 500ms)&lt;br /&gt;
* Make all turned over discs blink (and of course turned them over)&lt;br /&gt;
* (wait 1500ms)&lt;br /&gt;
* Update the player scores&lt;br /&gt;
* (no real delay on this one)&lt;br /&gt;
&lt;br /&gt;
The second part of the code is a generic thing to automatically bind the notifs we configured to the &amp;lt;code&amp;gt;notif_&amp;lt;notifName&amp;gt;&amp;lt;/code&amp;gt; functions we are about to create.&lt;br /&gt;
&lt;br /&gt;
Let&#039;s have a look now on the &amp;lt;code&amp;gt;playDisc&amp;lt;/code&amp;gt; notification handler method:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
notif_playDisc: function( notif )&lt;br /&gt;
{&lt;br /&gt;
    // Remove current possible moves (makes the board more clear)&lt;br /&gt;
    document.querySelectorAll(&#039;.possibleMove&#039;).forEach(div =&amp;gt; div.classList.remove(&#039;possibleMove&#039;));&lt;br /&gt;
&lt;br /&gt;
    this.addDiscOnBoard( notif.args.x, notif.args.y, notif.args.player_id );&lt;br /&gt;
},&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
No surprise here, we re-used some existing stuff to:&lt;br /&gt;
* Remove the highlighted squares.&lt;br /&gt;
* Add a new disc on board, coming from player panel.&lt;br /&gt;
&lt;br /&gt;
Now, here&#039;s the method that handles the &amp;lt;code&amp;gt;turnOverDiscs&amp;lt;/code&amp;gt; notification:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
notif_turnOverDiscs: function( notif )&lt;br /&gt;
{&lt;br /&gt;
    // Get the color of the player who is returning the discs&lt;br /&gt;
    var targetColor = this.gamedatas.players[ notif.args.player_id ].color;&lt;br /&gt;
&lt;br /&gt;
    // Made these discs blinking and set them to the specified color&lt;br /&gt;
    for( var i in notif.args.turnedOver )&lt;br /&gt;
    {&lt;br /&gt;
        var disc = notif.args.turnedOver[ i ];&lt;br /&gt;
        &lt;br /&gt;
        // Make the disc blink 2 times&lt;br /&gt;
        var anim = dojo.fx.chain( [&lt;br /&gt;
            dojo.fadeOut( { node: &#039;disc_&#039;+disc.x+&#039;&#039;+disc.y } ),&lt;br /&gt;
            dojo.fadeIn( { node: &#039;disc_&#039;+disc.x+&#039;&#039;+disc.y } ),&lt;br /&gt;
            dojo.fadeOut( { &lt;br /&gt;
                            node: &#039;disc_&#039;+disc.x+&#039;&#039;+disc.y,&lt;br /&gt;
                            onEnd: node =&amp;gt; $(node).dataset.color = targetColor,&lt;br /&gt;
                            } ),&lt;br /&gt;
            dojo.fadeIn( { node: &#039;disc_&#039;+disc.x+&#039;&#039;+disc.y  } )&lt;br /&gt;
                            &lt;br /&gt;
        ] ); // end of dojo.fx.chain&lt;br /&gt;
&lt;br /&gt;
        // ... and launch the animation&lt;br /&gt;
        anim.play();                &lt;br /&gt;
    }&lt;br /&gt;
},&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The list of the discs to be turned over has been made available by our server side code in &amp;lt;code&amp;gt;notif.args.turnedOver&amp;lt;/code&amp;gt; (see previous paragraph). We loop through all these discs, and create a complex animation using &amp;lt;code&amp;gt;dojo.Animation&amp;lt;/code&amp;gt; for each of them. The complete documentation on dojo animations [http://dojotoolkit.org/documentation/tutorials/1.6/animation/ can be found here].&lt;br /&gt;
&lt;br /&gt;
In few words: we create a chain of 4 animations to make the disc fade out, fade in, fade out again, and fade in again. At the end of the second fade out, we change the color of the disc. Finally, we launch the animation with &amp;lt;code&amp;gt;play()&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
And Also the notification to update the scores:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
notif_newScores: function( notif )&lt;br /&gt;
        {&lt;br /&gt;
            for( var player_id in notif.args.scores )&lt;br /&gt;
            {&lt;br /&gt;
                var newScore = notif.args.scores[ player_id ];&lt;br /&gt;
                this.scoreCtrl[ player_id ].toValue( newScore );&lt;br /&gt;
            }&lt;br /&gt;
        },&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Category:Studio]]&lt;/div&gt;</summary>
		<author><name>Sguzzer Gunayer</name></author>
	</entry>
	<entry>
		<id>https://en.doc.boardgamearena.com/index.php?title=Create_a_game_in_BGA_Studio:_Complete_Walkthrough&amp;diff=22784</id>
		<title>Create a game in BGA Studio: Complete Walkthrough</title>
		<link rel="alternate" type="text/html" href="https://en.doc.boardgamearena.com/index.php?title=Create_a_game_in_BGA_Studio:_Complete_Walkthrough&amp;diff=22784"/>
		<updated>2024-09-27T15:40:05Z</updated>

		<summary type="html">&lt;p&gt;Sguzzer Gunayer: /* Create Database Schema */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Introduction ==&lt;br /&gt;
&lt;br /&gt;
This document is not a tutorial, but step by step instructions on how to build your own first game adaptation using the BGA Studio framework.&lt;br /&gt;
&lt;br /&gt;
Before you read this material, you must:&lt;br /&gt;
* Read the overall presentations of the [[Studio|BGA Studio]].&lt;br /&gt;
* Know (at least somewhat) the languages used by BGA Studio: PHP, SQL, HTML, CSS, JavaScript&lt;br /&gt;
* Set up your development environment: [http://en.doc.boardgamearena.com/First_steps_with_BGA_Studio First Steps with BGA Studio]&lt;br /&gt;
* Create a game using one of the available tutorials. Don&#039;t bother trying to create a new game until you have completed at least one of the tutorials.&lt;br /&gt;
&lt;br /&gt;
If you&#039;re stuck or have questions about this page post on [https://forum.boardgamearena.com/viewforum.php?f=12 BGA Developers forum].&lt;br /&gt;
If you&#039;re uncomfortable posting on the public forum you can send messages directly to developers who post answers on that forum but NOT the BGA admins.&lt;br /&gt;
If you find typos in this wiki, fix them.&lt;br /&gt;
&lt;br /&gt;
== Select a First Game ==&lt;br /&gt;
&lt;br /&gt;
For your first &#039;&#039;&#039;real&#039;&#039;&#039; game (after you&#039;ve completed at least one tutorial), you must select a game from one of these options:&lt;br /&gt;
* [https://studio.boardgamearena.com/licensing Available Licenses]&lt;br /&gt;
* Public Domain&lt;br /&gt;
&lt;br /&gt;
But what if the game you want isn&#039;t in either of those categories? If you&#039;re able to successfully publish another game, you may gain the trust of the BGA admins, and they will then be happy to assist you in obtaining a license for a game you really want to do. Alternatively, you can request a license yourself. For more about game licenses, see the [[BGA Game licenses]] page.&lt;br /&gt;
&lt;br /&gt;
After you choose a game, but before creating a new project, take a few seconds to [http://studio.boardgamearena.com/#!projects check the list of current projects], to make sure that someone is not already developing that game. If they are, consider asking to join the project rather than starting a new project yourself.&lt;br /&gt;
&lt;br /&gt;
But even if you see a few projects with the name of the game in question, they may not be active. There are a lot of abandoned game projects. If it&#039;s not clear by the status of the project, then post to the Developers forum asking if anybody is actively working on the project, or send a message to the developers listed for the abandoned projects. At the same time, ask admins on the same forum to send you graphics for that game if they have them. (There&#039;s a button on the [https://studio.boardgamearena.com/licensing Available Licenses] page to request graphics, but that button just sends an email.)&lt;br /&gt;
&lt;br /&gt;
If your goal was to fix bugs in an existing project, first try to locate it on Studio, but note that projects developed by BGA admins are not in Studio. Then get read-only access to the project, and create your own as a copy of the existing one. Contact a project admin about getting write access to the original project, or ask if they are willing to apply your patches.&lt;br /&gt;
&lt;br /&gt;
If you want to take over an existing project, first ask on the forum to see if the project is abandoned, then get read-only access (via project list) and see if it&#039;s worth using the existing project. If it has no code or graphics, then just start from the scratch. Don&#039;t worry about the project name; it can be renamed later.&lt;br /&gt;
&lt;br /&gt;
== Create a project ==&lt;br /&gt;
&lt;br /&gt;
If you have not already, you have to create a project in BGA Studio for this game. If the original game name is taken use gamenameYOURINITIALS&lt;br /&gt;
template, i.e.&amp;quot;heartsla&amp;quot;. Don&#039;t worry too much about the name, if the game is good enough to publish, it will be renamed to its original name. &lt;br /&gt;
&lt;br /&gt;
Find and start the game in turn based mode, make sure it works.&lt;br /&gt;
&lt;br /&gt;
Second, modify the text in .tpl file, reload the page in the browser and make sure your ftp sync works as expected.&lt;br /&gt;
Note: if you have not setup [http://en.doc.boardgamearena.com/Tools_and_tips_of_BGA_Studio#File_Sync FTP auto-sync] yet, do it now, manually copying files is a no-starter.&lt;br /&gt;
&lt;br /&gt;
Update your project status on [http://studio.boardgamearena.com/#!studio Control Panel &amp;gt; Manage games] page, you can say &amp;quot;development started&amp;quot; or &amp;quot;waiting for the license&amp;quot; or &amp;quot;waiting for graphics&amp;quot; or a combination of those.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Development Tools ==&lt;br /&gt;
&lt;br /&gt;
At some point, you need to setup your development environment which consists of multiple tools, such as&lt;br /&gt;
* Editor or IDE&lt;br /&gt;
* Browser with dev tools&lt;br /&gt;
* File sync tools&lt;br /&gt;
* BGA Web tools&lt;br /&gt;
* Image manipulation tools&lt;br /&gt;
* Version control tools&lt;br /&gt;
&lt;br /&gt;
Please scan through articles from [[Studio#BGA_Studio_user_guide]] especially those related to debugging and tools, there is a lot of useful info there.&lt;br /&gt;
&lt;br /&gt;
== Hook version control system ==&lt;br /&gt;
&lt;br /&gt;
If it&#039;s a real game, I would commit the code to version control right at the start. You are going to find yourself in a situation where the game does not even start anymore and there is no way of debugging it unless you have a way to revert. That is where version control becomes very handy.&lt;br /&gt;
If you don&#039;t know what I am talking about then at least back-up your files after each of the major steps. Starting now.&lt;br /&gt;
You can also create a project on github, but make sure &#039;&#039;&#039;you don&#039;t commit original publisher graphics files&#039;&#039;&#039; and &#039;&#039;&#039;you don&#039;t include a file with your sftp password&#039;&#039;&#039; (github is automatically crawled for passwords by hackers; a hacking attempt occurred on BGA studio for this reason in June 2020).&lt;br /&gt;
You can (and should) also commit your modification periodically via Studio Control Panel.&lt;br /&gt;
&lt;br /&gt;
== Obtain game graphics ==&lt;br /&gt;
&lt;br /&gt;
If you developing a game from the Available Licenses section, ask the admins to send you graphics by using the &#039;&#039;&#039;Request Art Files&#039;&#039;&#039; button available on the studio license page. While that request is being processed (it can take time, as it often requires some back and forth between the admins and the publishers) you can proceed to the next step - project creation.&lt;br /&gt;
&lt;br /&gt;
If you don&#039;t get original graphics you go to &#039;&#039;&#039;Scavenger Hunt&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
* If you developing a public domain card game you can borrow standard cards from BGA generic assets, see [[Common_board_game_elements_image_resources]]&lt;br /&gt;
* Standard game pieces - meeples, cubes, dice can be found here as well [[Common_board_game_elements_image_resources]]&lt;br /&gt;
* Go to boardgamegeek.com find your game and obtain 3D game box image, 2D box image, and if you are lucky they also sometimes have boards and token scans in &amp;quot;Game Pieces&amp;quot; section of Images&lt;br /&gt;
* If that fails, google &amp;quot;boardgame &amp;lt;name&amp;gt;&amp;quot; and check the Images section&lt;br /&gt;
* Get the rules PDF as well, there&#039;re tools that allow you to extract graphics from PDF, which are usually good for meeples, cubes and such (can use pdfimages command line tool)&lt;br /&gt;
&lt;br /&gt;
Once you get the graphics one way or another you have to massage them to fit in the BGA criteria, which usually involves&lt;br /&gt;
* If the publisher sends graphics in one token/card per file mode, you have to stitch them in sprite and scale down&lt;br /&gt;
* For non square tiles and game pieces you need transparency&lt;br /&gt;
* Usually you chop off the scoring &amp;quot;ring&amp;quot; around the board of the game since the scoring track is not needed for online adaptation&lt;br /&gt;
&lt;br /&gt;
More details about graphics requirements can be found here [[Game art: img directory]].&lt;br /&gt;
&lt;br /&gt;
[[File:Rrr_search.png]]&lt;br /&gt;
&lt;br /&gt;
== Obtain game documentation ==&lt;br /&gt;
&lt;br /&gt;
Also at this time obtain an electronic copy of rules, such as PDF (English version). &lt;br /&gt;
&lt;br /&gt;
Also grab any other documents you may find on boardgamegeek such as FAQ, additional Reference books, and user created assistant documents, such&lt;br /&gt;
as cheat-sheets (may be easier to get data from these than trying to scrub pdf). You create and place them in the doc/ folder of the project then&lt;br /&gt;
exclude them from version control. There is also a misc/ folder now but it will hold up to 1 Mb of data files which would be checked in, so rules pdf&#039;s may not fit there.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Update game info and box graphics ==&lt;br /&gt;
&lt;br /&gt;
Even if is not playable yet, start with making sure the game looks descent in the game selector, meaning it has nice box graphics and the information is correct. &lt;br /&gt;
&lt;br /&gt;
For that we need to edit [[Game_meta-information: gameinfos.inc.php|gameinfos.inc.php]].&lt;br /&gt;
What you would do for the real game you would go to http://boardgamegeek.com find the game and use information from the website to fill the gameinfos.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The next step is to replace game_box.png with proper images, usually, you can find all images including the publisher logo on the boardgamegeek website.&lt;br /&gt;
&lt;br /&gt;
Game metadata images, such box image are now managed in separate tool.&lt;br /&gt;
&lt;br /&gt;
Details about images can be found here: [[Game art: img directory]].&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[File:Gamepanel_sharedcode.png]]&lt;br /&gt;
&lt;br /&gt;
Now try to start the game again. If you some-how introduced a syntax error in gameinfos file it may not actually work (game won&#039;t start).&lt;br /&gt;
Always use &amp;quot;Express Start&amp;quot; button to start the game. You should see a standard state prompt from template. You should see X players on the right, testdude0 .. testdudeX-1.&lt;br /&gt;
To switch between them press the red arrow button near their names, it will open another tab. This way you don&#039;t need to login and logout from multiple accounts!&lt;br /&gt;
&lt;br /&gt;
== Fix source copyright ==&lt;br /&gt;
&lt;br /&gt;
Now since you have your own project, you want to put your name in the copyright header, so replace&lt;br /&gt;
&lt;br /&gt;
  © &amp;lt;Your name here&amp;gt; &amp;lt;Your email address here&amp;gt;&lt;br /&gt;
with&lt;br /&gt;
  © John Snow &amp;lt;jsnow@gameofthrones.com&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Well not exactly this but whatever your real name is. For all files in the project directory, it&#039;s about 10 files. Make sure the project still starts after that :)&lt;br /&gt;
&lt;br /&gt;
== Reduce the Rules ==&lt;br /&gt;
&lt;br /&gt;
Programming a game will take a lot more time than you may think. Most of the projects in the studio are abandoned because of a lack of patience or skill.&lt;br /&gt;
To keep sane, start the game with *reduced* rules and try to complete that first.&lt;br /&gt;
&lt;br /&gt;
* If it has any expansions - do not even attempt to deal with them, not even - &amp;quot;I will just add graphics for them now and not use&amp;quot; - waste of time if you don&#039;t complete basic&lt;br /&gt;
* If it has advanced rules - start with basic rules only, i.e. &amp;quot;beginner game&amp;quot;&lt;br /&gt;
* If it has special rules for 2 players vs 4, start with the most basic form (i.e. 4), restrict to 4 players &lt;br /&gt;
* If it has 50 unique cards of 2 each - start with 2 unique cards with 25 each (just to keep it moving)&lt;br /&gt;
* Any sort of rules that you think can be removed and not included in base - set aside for now &lt;br /&gt;
* Ignore any sort of cool animations - dice rolling, card flipping, choo-choo sounds of the trains - all this fluff can be added later&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Design Game Elements ==&lt;br /&gt;
Technically game elements are already designed by a board game designer but your job is to map them to program space.&lt;br /&gt;
Each physical piece (card, token, cube) will leave footprints all over the code (unfortunately in multiple disconnected places).&lt;br /&gt;
To prepare the game you need to sort out these elements, i.e. categorize. I usually have the following categorization (in object oriented view):&lt;br /&gt;
* Instance - all individual pieces are instances, i.e. two red cubes are two instances of &#039;red cube&#039; type (class)&lt;br /&gt;
* Type - element type which distinctly represents that element in appearance (i.e. red cube is a different type than blue cube)&lt;br /&gt;
* Super Type - one of the more common types that similar properties (i.e. red OR cube)&lt;br /&gt;
* Player color - supertype specific for player color (sometimes there are no colors but like player 1 - but is conceptually the same, I use color because it&#039;s easier to track)&lt;br /&gt;
&lt;br /&gt;
Personally, I like to encode my elements in a string using reverse DNS notation listing all the properties above, i.e.&lt;br /&gt;
  meeple_ff0000_7 - this is instance #7 of type meeple_ff0000 (red meeple)&lt;br /&gt;
Or&lt;br /&gt;
  card_yellow_magic_2 - this is instance #2 of a yellow card (in this case yellow is the color of the deck, not related to player color) that can do magic&lt;br /&gt;
&lt;br /&gt;
So every game element would be in the&lt;br /&gt;
&lt;br /&gt;
1. Database - instances. The db record would be something like &lt;br /&gt;
  key|location|state&lt;br /&gt;
  meeple_ff0000_7|slot_action_2|1&lt;br /&gt;
  meeple_ff0000_2|tableau_ff0000|0&lt;br /&gt;
2. Material file - types and supertypes, we never need repeating info here, so never list individual instances but only types or supertypes, in this case, we don&#039;t really need to define red meeple vs blue meeple&lt;br /&gt;
  &#039;meeple&#039;=&amp;gt;{&#039;name&#039;=&amp;gt;totranslate(&#039;Meeple&#039;)}&lt;br /&gt;
3. Client (js, css, tpl, etc) - instances and types. For example my meeple will be like &lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  &amp;lt;div id=&amp;quot;meeple_ff0000_7&amp;quot; class=&amp;quot;meeple meeple_ff0000&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
with .css something like&lt;br /&gt;
  .meeple { background-image: url(img/tokens.png); width: 2em; height: 2em;}&lt;br /&gt;
  .meeple_ff0000 {background-position: 20% 0%;}&lt;br /&gt;
4. Game php - setup and logic. During setup, you have to generate all the pieces and place them in the right positions. Also sometimes you need to reference elements to code the logic (I usually try to encode all rules in the material file as much as possible)&lt;br /&gt;
&lt;br /&gt;
For complex card games, I think it is best to keep all these info and rules in a spreadsheet and generate other files such as material.inc.php.&lt;br /&gt;
See more info below about the design of the individual layers.&lt;br /&gt;
&lt;br /&gt;
== Create Initial Layout and Game Graphics ==&lt;br /&gt;
&lt;br /&gt;
Mentally it is easier to start with the game layout and graphics pieces. Even when nothing is working it gives you moral satisfaction!&lt;br /&gt;
&lt;br /&gt;
There are a few ways how the html could have been generated. You could have started with nothing and generate&lt;br /&gt;
it all by javascript, or you could have started with complete game markup in html and make javascript just hide and move pieces around. BGA framework also provides a third way, which is mix of both, plus a template engine to generate HTML using PHP. The only thing that is really annoying about the template engine is that you cannot put any translatable strings in the template (which means any visible text at all). If you are using the template approach all strings have to be extracted as variables and injected through PHP (.view.php). This page explains the template engine in great detail:[[Game_layout:_view_and_template:_yourgamename.view.php_and_yourgamename_yourgamename.tpl|Template Engine]].&lt;br /&gt;
&lt;br /&gt;
The other disadvantage of the template engine is you cannot run and debug it locally, in the beginning of development it&#039;s a lot faster run off local pages, &lt;br /&gt;
you can do it with some trickery described here [[Tools_and_tips_of_BGA_Studio#Speed_up_CSS_development_and_layout|Tools and Tips for BGA Studio]]&lt;br /&gt;
&lt;br /&gt;
During this step you have to decide what technical solutions you will be using, such as&lt;br /&gt;
* Use inline positioning of all moving pieces, controlled by JS. There are a few classes that already exist in Studio to help with that (see [[Studio#Game_interface_.28Client_side.29|Game Interface - Client Side]]). OR use html/css layout engine to position pieces (my personal choice).&lt;br /&gt;
* Use BGA template engine OR create all ui elements by JS OR manually write or generate complete html markup. The game usually contains 200-300 pieces, it seems wrong but actually its faster to type all of this up in html/css when trying write than debug code for page generator.&lt;br /&gt;
Static HTML markup also means you have to use players color or abstracted player number (such as red is 1, blue is 2) not player id&#039;s anywhere in JS, since player id is dynamic by nature.&lt;br /&gt;
&lt;br /&gt;
Start by creating and mapping all games assets, best way is probably to open rule book on &amp;quot;boardgame contents&amp;quot; page and go through every piece. Every piece of boardgame would have its &amp;quot;print&amp;quot; in multiple files in your game:&lt;br /&gt;
* Some sort of &amp;quot;div&amp;quot; in html, where id of element match id of element in database (easiest way)&lt;br /&gt;
* Css for the element (either unique or for class), usually with background property refering to part of sprite image&lt;br /&gt;
* Entry in material.inc.php referring to static properties of the element, i.e. name, tooltip, rules, etc&lt;br /&gt;
* Entry in .tpl file to represent a static or initial location on the table OR creation template&lt;br /&gt;
&lt;br /&gt;
Here are some specific examples:&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Game Board&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Create entry in .tpl file for the board, it will be static entry as we never need to create this dynamically&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  &amp;lt;div id=&amp;quot;board&amp;quot; class=&amp;quot;board shadow board4p&amp;quot;&amp;gt; ... &amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Create entry in .css file for this board and other board variants (in example below we have 4 ppl board which is diffrent than 2 ppl board)&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
.board {&lt;br /&gt;
	position: relative;&lt;br /&gt;
	width: 980px;&lt;br /&gt;
	height: 433px;&lt;br /&gt;
	margin-bottom: 5px;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.board4p {&lt;br /&gt;
	background-image: url(img/board4p.jpg);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
That would be pretty much it for the board itself, as it does not really need a tooltip so we don&#039;t need entry in material.inc.php&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Game Board Slots&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
These are interactive areas on the board, usually illustrated as such. In most cases you can get away with rectangular shapes, but sometimes you have to create circle or oval shapes (and in really advanced case would be some svg paths). For slots you can do the following:&lt;br /&gt;
&lt;br /&gt;
Entry in material.inc.php&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$this-&amp;gt;token_types = array(&lt;br /&gt;
...&lt;br /&gt;
&#039;slot_action_2&#039; =&amp;gt; array(&lt;br /&gt;
  &#039;type&#039; =&amp;gt; &#039;slot_action&#039;,&lt;br /&gt;
  &#039;name&#039; =&amp;gt; clienttranslate(&amp;quot;2 Gray Track Advancements&amp;quot;),&lt;br /&gt;
  &#039;tooltip&#039; =&amp;gt; clienttranslate(&amp;quot;This action gives you two advancements of gray track. You cannot use this action if you cannot complete all advancements.&amp;quot;),&lt;br /&gt;
  &#039;o&#039;=&amp;gt;&amp;quot;1,0,0,gg&amp;quot;, // automatic rules&lt;br /&gt;
),&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Entry in template inside the &amp;quot;board&amp;quot; div&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
	&amp;lt;div id=&amp;quot;slot_action_2&amp;quot; class=&amp;quot;slot_action_2 slot_action slot_w_1 slot&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Entry in .css with absolute position within the board (its actually better to use percentage - would be easier to scale later)&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
.slot_action_2 {&lt;br /&gt;
	top: 83px;&lt;br /&gt;
	left: 37px;&lt;br /&gt;
}&lt;br /&gt;
.slot_action {&lt;br /&gt;
	position: absolute;&lt;br /&gt;
	width: 46px;&lt;br /&gt;
	height: 26px;&lt;br /&gt;
	padding: 9px 7px 6px 4px;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Meeples&#039;&#039;&#039; - also cards, tokens, other mobile stuff&lt;br /&gt;
&lt;br /&gt;
In CSS these guys will use &amp;quot;sprite&amp;quot; images with transparency, so it will look like this this:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
.meeple {&lt;br /&gt;
	background-image: url(img/tokens.png);&lt;br /&gt;
	width: 25px;&lt;br /&gt;
	height: 25px;&lt;br /&gt;
}&lt;br /&gt;
.meeple_ff0000 { /* red */&lt;br /&gt;
	background-position: 14% 0%;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
As for creation you can either generate them using template (where whole thing wrapped in template block and {COLOR} replace with all possible colors in .view.php&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 &amp;lt;div id=&amp;quot;meeple_{COLOR}_1&amp;quot; class=&amp;quot;meeple meeple_{COLOR} meepleable&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
 &amp;lt;div id=&amp;quot;meeple_{COLOR}_2&amp;quot; class=&amp;quot;meeple meeple_{COLOR} meepleable&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
 ...&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Or you can declare a template js var in .tpl file &lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    var jstpl_mepple = &#039;&amp;lt;div id=&amp;quot;meeple_${color}_${num}&amp;quot; class=&amp;quot;meeple meeple_${color} meepleable&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&#039;; // this is in .tpl file at the bottom&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
and create in js, like this&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 var tokenDiv = this.format_block(&#039;jstpl_mepple&#039;, {&lt;br /&gt;
                                &amp;quot;color&amp;quot; : color,&lt;br /&gt;
                                &amp;quot;num&amp;quot; : i&lt;br /&gt;
                            }); // this in js code somewhere before placing it&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
If you dealing with cards and decks, there are pre-build components that can generate stuff for you.&lt;br /&gt;
&lt;br /&gt;
When do you create dom element matching game element?&lt;br /&gt;
* If you have static layout you create it in .tpl file and its always there, but during initial setup or during notification it moved in proper spot (including &amp;quot;removed from the game&amp;quot; spot)&lt;br /&gt;
* If you dynamically generated pieces you create the element during notification, and sometimes during animation. Also don&#039;t forgot to hook event listener to it if its interactive.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
One of the greatest parts about the web is all client side code can be viewed in your browser, so if you wondering how something is done in another BGA game just load the page and spy on it! In Chrome that would be right click and &amp;quot;Inspect Element&amp;quot;. That would immediately show html of the given element alongside with css used for it (on the right). Another great way to learn is you can add yourself to any BGA project as read only from the project page!&lt;br /&gt;
&lt;br /&gt;
So at the end of this stage you should complete the following (keeping in mind reduced rules/material for first iteration):&lt;br /&gt;
* Create a layout of the game, with positioning of main board, player areas, zones, other supporting areas, etc&lt;br /&gt;
* Create css and html snippets for all game pieces: boards, tokens, meeples, etc. Place them all in initial template (even if they&#039;re not supposed to be visible at start). I.e. create fake player&#039;s hand with cards, put meeples on the board&lt;br /&gt;
* Hook layout to number of players and colors picked by the game and test with multiple players&lt;br /&gt;
* Figure out what you want to display in mini-player boards and hook it up&lt;br /&gt;
* Create material.inc.php and populate with initial values (names, tooltips, rules) for all relevant game elements or classes of elements&lt;br /&gt;
&lt;br /&gt;
If at this time you don&#039;t have graphics yet create pieces with just CSS, you can use shape, background color and object text using css ::after construct to fake the pieces.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[File:Injected_text.png]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Create Database Schema ==&lt;br /&gt;
&lt;br /&gt;
At some point you have to design your game database. Do it sooner than later since it would be harder to change it later, since some code decisions would be based on that.&lt;br /&gt;
&lt;br /&gt;
If you have grid-based abstract game use template from reversi, if you have a card game use template from hearts (the cards one also commented out in generated template for your project). The cards database goes with php class called [[Deck]].&lt;br /&gt;
&lt;br /&gt;
In general make it as simple as possible. Think about it, your game has 300 pieces (likely less). Using database to store this amount of data is like shooting a mosquito with a tank. Anything more complex then one table with 5 columns or two tables will only going to make it harder to develop and not improve performance. You can forget about normalizing and any fancy stuff you learn about databases in school. String field for a primary key would be as fast as integer when we talking about this size of data. So don&#039;t over-optimize with trying to have integers field that have state based on bitmask!&lt;br /&gt;
&lt;br /&gt;
Also remember that static (non dynamic) information about the game does not need to be stored in the database, that all include everything that does not change, i.e. all token/card properties such as name, tooltips, &amp;quot;strength&amp;quot;, color, etc. This is stored in &amp;lt;code&amp;gt;material.inc.php&amp;lt;/code&amp;gt; and server has access to it from anywhere, as well as the client if you send it with &amp;lt;code&amp;gt;getAllDatas()&amp;lt;/code&amp;gt;. The only reason to store some of it in database is if it can affect your queries (i.e. type of token).&lt;br /&gt;
&lt;br /&gt;
Usually design process will contain the following steps:&lt;br /&gt;
* Design game model - model that represent your game in progress, such as at any given step you can restore the game from that model&lt;br /&gt;
* Mapping - now map real game to that model&lt;br /&gt;
* Encoding - now represent this model in database and material file with reasonable amount of fields&lt;br /&gt;
&lt;br /&gt;
Example: &#039;&#039;&#039;The card game&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
* In real word to &amp;quot;save&amp;quot; the game we take a picture of the play area, save cards from it, then put away draw deck, discard and hand of each player separately and mark it, also we will record current scoring (if any) and who&#039;s turn was it.&lt;br /&gt;
* Framework handles state machine transition, so you don&#039;t have to worry about database design for that (i.e. who&#039;s turn it is, what phase of the game we are at, you still have to design it but as part of state machine step).&lt;br /&gt;
* Also framework supports basic player information, color, order around the table, basic scoring, etc, so you don&#039;t have to worry about it either.&lt;br /&gt;
* The only thing you need in your database is state of the &amp;quot;board&amp;quot;, which is &amp;quot;where each pieces is, and in what state&amp;quot;, or (position,rotation) pair.&lt;br /&gt;
* The card state is very simple, it&#039;s usually &amp;quot;face up/face down&amp;quot;, &amp;quot;tapped/untapped&amp;quot;, &amp;quot;right side up/up side down&amp;quot;.&lt;br /&gt;
* As position go we never need real x,y,z. We need to know what &amp;quot;zone&amp;quot; card was, and depending on the zone it may sometimes need an extra &amp;quot;z&amp;quot; or &amp;quot;x&amp;quot; as card order. The zone position itself usually static or irrelevant.&lt;br /&gt;
* So our model is: we have cards, which have some attributes, at any given point in time they belong to a &amp;quot;zone&amp;quot;, and can also have order and state.&lt;br /&gt;
* Now for mapping we should consider what info changes and what info is static, static info is always candidate for material file or html.&lt;br /&gt;
* For dynamic stuff we should try to reduce amount of fields we need, i.e. we need a field for card, so its one, we need to know what zone cards belong to, its two, and we have possible few other fields, but if you look closely at you game you may find out that most of the zone only need one attribute at a time, i.e. draw pile always have cards face down, hand always face up, also for hand and discard order does not matter at all (but for draw it does matter). So in majority of cases we can get away with one single extra integer field representing state or order.&lt;br /&gt;
* In real database both card and zone will be integers as primary keys referring to additional tables, but in our case its total overkill, so they can be strings as easily&lt;br /&gt;
&lt;br /&gt;
You can also use cards database schema and [[Deck]] implementation for most purposes (even you not dealing with cards).&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
CREATE TABLE IF NOT EXISTS `card` (&lt;br /&gt;
  `card_id` int(10) unsigned NOT NULL AUTO_INCREMENT,&lt;br /&gt;
  `card_type` varchar(16) NOT NULL,&lt;br /&gt;
  `card_type_arg` int(11) NOT NULL,&lt;br /&gt;
  `card_location` varchar(16) NOT NULL,&lt;br /&gt;
  `card_location_arg` int(11) NOT NULL,&lt;br /&gt;
  PRIMARY KEY (`card_id`)&lt;br /&gt;
) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=1 ;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Another example: &#039;&#039;&#039;The euro game&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
See details on database design for euro game at [[BGA_Studio_Cookbook#Database_for_The_euro_game]]&lt;br /&gt;
&lt;br /&gt;
So the piece mapping for non-grid based games can be in most case represented by (string: token_key, string: location, int: state), example of such database schema can be found here: [https://github.com/elaskavaia/bga-sharedcode/blob/master/dbmodel.sql dbmodel.sql] and class implementing access to it here [https://github.com/elaskavaia/bga-sharedcode/blob/master/modules/tokens.php tokens.php].&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
CREATE TABLE IF NOT EXISTS `token` (&lt;br /&gt;
  `token_key` varchar(32) NOT NULL,&lt;br /&gt;
  `token_location` varchar(32) NOT NULL,&lt;br /&gt;
  `token_state` int(10),&lt;br /&gt;
  PRIMARY KEY (`token_key`)&lt;br /&gt;
) ENGINE=InnoDB DEFAULT CHARSET=utf8;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
See [[Game database model: dbmodel.sql]] for details about editing the file.&lt;br /&gt;
&lt;br /&gt;
Note: the simpler the database is the less debugging of database issues you have to deal with including database migration. The tokens database above - if you use it you never have to worry about migration because you don&#039;t need extra tables in 95% of the games. Here are some example of how real games are mapped to such database:&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Chess:&#039;&#039;&#039; &lt;br /&gt;
&lt;br /&gt;
chess is grid base game and normally you would use positional columns, but just for the sake of argument, the chess game will look like this&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+token&lt;br /&gt;
! token_key&lt;br /&gt;
! token_location&lt;br /&gt;
! token_state&lt;br /&gt;
|-&lt;br /&gt;
|Q_white&lt;br /&gt;
|f3&lt;br /&gt;
|0&lt;br /&gt;
|-&lt;br /&gt;
|P_black_2&lt;br /&gt;
|c6&lt;br /&gt;
|0&lt;br /&gt;
|-&lt;br /&gt;
|K_black&lt;br /&gt;
|e8&lt;br /&gt;
|1&lt;br /&gt;
|}&lt;br /&gt;
And the state in this case indicated that kind was moved for example (which means castling cannot be performed)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Classic card game&#039;&#039;&#039; &lt;br /&gt;
&lt;br /&gt;
Lets pretend we need 2 decks for that game&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+token&lt;br /&gt;
! token_key&lt;br /&gt;
! token_location&lt;br /&gt;
! token_state&lt;br /&gt;
|-&lt;br /&gt;
|Q_spades_1&lt;br /&gt;
|hand_ff0000&lt;br /&gt;
|0 /* state not used for hand */&lt;br /&gt;
|-&lt;br /&gt;
|10_hearts_2&lt;br /&gt;
|tableau_ff0000&lt;br /&gt;
|2 /* position */&lt;br /&gt;
|-&lt;br /&gt;
|10_hearts_1&lt;br /&gt;
|tableau_common&lt;br /&gt;
|1 /* face down */&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Eminent Domain (card game)&#039;&#039;&#039; &lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+token&lt;br /&gt;
! token_key&lt;br /&gt;
! token_location&lt;br /&gt;
! token_state&lt;br /&gt;
|-&lt;br /&gt;
|card_tech_23&lt;br /&gt;
|hand_ff0000&lt;br /&gt;
|0 /* state not used for hand */&lt;br /&gt;
|-&lt;br /&gt;
|card_planet_19&lt;br /&gt;
|tableau_ff0000&lt;br /&gt;
|1 /* face up */&lt;br /&gt;
|-&lt;br /&gt;
|reource_s_22 /* silicon */&lt;br /&gt;
|card_planet_19&lt;br /&gt;
|2 /*  production state */&lt;br /&gt;
|-&lt;br /&gt;
|fighter_F_1&lt;br /&gt;
|tableau_ff0000&lt;br /&gt;
|0&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
You can also look at other games that use Tokens database and access layer: Nippon, Dungeon Petz, Lewis &amp;amp; Clark, Battleship, Russian Railroads, Khronos.&lt;br /&gt;
&lt;br /&gt;
== Implement Game Setup ==&lt;br /&gt;
&lt;br /&gt;
Once you have your database schema you can do a proper game setup. Usually you open rulebook on the &amp;quot;Game Setup&amp;quot; page and implement these step by step populating the database (using database access API). Game initialization is performed in php method &amp;lt;code&amp;gt;setupNewGame&amp;lt;/code&amp;gt;, this method is called once when game table is created. Game notifications cannot be sent during this time.&lt;br /&gt;
&lt;br /&gt;
It very hard to debug this method, so this is how we recommend to structure it:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
protected function setupNewGame($players, $options = []) { &lt;br /&gt;
   &lt;br /&gt;
   // here is some generate code from template LEAVE IT UNTOUCHED&lt;br /&gt;
   ...&lt;br /&gt;
&lt;br /&gt;
   $this-&amp;gt;initTables(); // this is YOUR new method&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
function initTables() {&lt;br /&gt;
       try {&lt;br /&gt;
            $players = $this-&amp;gt;loadPlayersBasicInfos();&lt;br /&gt;
            // code the function&lt;br /&gt;
            $this-&amp;gt;activeNextPlayer(); // just in case so its not 0&lt;br /&gt;
            $this-&amp;gt;initStats(); // to be coded&lt;br /&gt;
            // Setup the initial game situation here&lt;br /&gt;
            $this-&amp;gt;initGameTables(); // to be coded&lt;br /&gt;
            // beggining of the turn for active player (if player state if first state)&lt;br /&gt;
            $player_id = $this-&amp;gt;getActivePlayerId();&lt;br /&gt;
            $this-&amp;gt;incStat(1, &#039;turns_number&#039;, $player_id);&lt;br /&gt;
            $this-&amp;gt;incStat(1, &#039;turns_number&#039;);&lt;br /&gt;
       } catch ( Exception $e ) {&lt;br /&gt;
           // logging does not actually work in game init :(&lt;br /&gt;
           // but if you calling from php chat it will work&lt;br /&gt;
           $this-&amp;gt;error(&amp;quot;Fatal error while creating game&amp;quot;);&lt;br /&gt;
           $this-&amp;gt;dump(&#039;err&#039;, $e);&lt;br /&gt;
       }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
For more tricks about debugging see this [https://en.doc.boardgamearena.com/Practical_debugging#Debugging_setupNewGame Debugging setupNewGame]&lt;br /&gt;
&lt;br /&gt;
For the &amp;lt;code&amp;gt;initStats()&amp;lt;/code&amp;gt; method, its likely that all of the stats are &amp;lt;code&amp;gt;int&amp;lt;/code&amp;gt; and you can just use this genetic initializer, but your stats have to start with &amp;lt;code&amp;gt;game_&amp;lt;/code&amp;gt; prefix (verbatim):&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    public function initStats()&lt;br /&gt;
    {&lt;br /&gt;
        // INIT GAME STATISTIC&lt;br /&gt;
        $all_stats = $this-&amp;gt;getStatTypes();&lt;br /&gt;
        $player_stats = $all_stats[&#039;player&#039;];&lt;br /&gt;
        // auto-initialize all stats that starts with game_&lt;br /&gt;
        // we need a prefix because there is some other system stuff&lt;br /&gt;
        foreach ($player_stats as $key =&amp;gt; $value) {&lt;br /&gt;
            if (str_starts_with($key, &#039;game_&#039;)) {&lt;br /&gt;
                $this-&amp;gt;initStat(&#039;player&#039;, $key, 0);&lt;br /&gt;
            }&lt;br /&gt;
            if ($key === &#039;turns_number&#039;) {&lt;br /&gt;
                $this-&amp;gt;initStat(&#039;player&#039;, $key, 0);&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
        $table_stats = $all_stats[&#039;table&#039;];&lt;br /&gt;
        foreach ($table_stats as $key =&amp;gt; $value) {&lt;br /&gt;
            if (str_starts_with($key, &#039;game_&#039;)) {&lt;br /&gt;
                $this-&amp;gt;initStat(&#039;table&#039;, $key, 0);&lt;br /&gt;
            }&lt;br /&gt;
            if ($key === &#039;turns_number&#039;) {&lt;br /&gt;
                $this-&amp;gt;initStat(&#039;table&#039;, $key, 0);&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
As for &amp;lt;code&amp;gt;initGameTables()&amp;lt;/code&amp;gt; - if you have a SQL layer you can use it to initialize everything, if not - the best would be to push everything in php &amp;lt;code&amp;gt;array&amp;lt;/code&amp;gt; and then do one &amp;lt;code&amp;gt;INSERT&amp;lt;/code&amp;gt; at the end (after all the fiddling and shuffling).&lt;br /&gt;
&lt;br /&gt;
For example for the token database above, I will push all data into an array, then at the end run &amp;lt;code&amp;gt;INSERT&amp;lt;/code&amp;gt;, i.e.&lt;br /&gt;
&lt;br /&gt;
        $values=[]; &lt;br /&gt;
        $values [] = &amp;quot;(&#039;meeple_ff0000_1&#039;, &#039;home_ff0000&#039;, 0)&amp;quot;; // this is actually string not array&lt;br /&gt;
        ...&lt;br /&gt;
        $sql = &amp;quot;INSERT INTO tokens (token_id, place_id, state) VALUES &amp;quot; . implode($values, &#039;,&#039;);&lt;br /&gt;
        $this-&amp;gt;DbQuery($sql);&lt;br /&gt;
&lt;br /&gt;
== Implement one time game model synchronization ==&lt;br /&gt;
&lt;br /&gt;
Now at any point in the game we need to make sure that database information can be reflected back in UI, so we fix &amp;lt;code&amp;gt;getAllDatas&amp;lt;/code&amp;gt; function to return all possible data we need to reconstruct the game. The template for &amp;lt;code&amp;gt;getAllDatas&amp;lt;/code&amp;gt; is already taking care of player info, but you  have to alter it to return all other data from database visible to the &amp;quot;current&amp;quot; player.&lt;br /&gt;
&lt;br /&gt;
After that on the client side we should display this data, so in your .js file in &amp;lt;code&amp;gt;setup&amp;lt;/code&amp;gt; function (which is the receiver of &amp;lt;code&amp;gt;getAllDatas&amp;lt;/code&amp;gt;) you add calls that handle data send by server, usually by calling animation function such as &amp;quot;&amp;lt;code&amp;gt;placeToken&amp;lt;/code&amp;gt;&amp;quot; or &amp;quot;&amp;lt;code&amp;gt;placeCard&amp;lt;/code&amp;gt;&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
So this is roughly what you need to include in &amp;lt;code&amp;gt;getAllDatas()&amp;lt;/code&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
* Extra player info.&lt;br /&gt;
* Material file variables as unfortunately they are not included automatically. Note - I strongly recommend using only one variable for generic data information, such as &amp;lt;code&amp;gt;$this-&amp;gt;token_types&amp;lt;/code&amp;gt;. If you start splitting it i.e. &amp;lt;code&amp;gt;card_types&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;meeple_types&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;building_types&amp;lt;/code&amp;gt; - it will be very hard to deal with this programmatically as it will be lots of switches. Also call it the same as in php - otherwise its really hard to correlate.&lt;br /&gt;
* Game options (if you know how to access them on client without passing via &amp;lt;code&amp;gt;getAllData()&amp;lt;/code&amp;gt; edit this wiki). Example has generic code to pass all options, but you can use custom individual options.&lt;br /&gt;
* Dump of database tables filtered by current player view.&lt;br /&gt;
* To be fancy you can also include php constants so you can access them in js as well, example not included.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    protected function getAllDatas() {&lt;br /&gt;
        $result = [];&lt;br /&gt;
&lt;br /&gt;
        // 1. Get information about players&lt;br /&gt;
        // Note: you can retrieve some extra field you added for &amp;quot;player&amp;quot; table in &amp;quot;dbmodel.sql&amp;quot; if you need it.&lt;br /&gt;
        // would have been much better if its just * but we not looking for easy solutions here! so it all have to be aliases&lt;br /&gt;
        $sql = &amp;quot;SELECT player_id id, player_score score, player_no no FROM player&amp;quot;; // note - the framework will all bunch of more fields&lt;br /&gt;
        $result [&#039;players&#039;] = self::getCollectionFromDb($sql);&lt;br /&gt;
&lt;br /&gt;
        // 2. Material data&lt;br /&gt;
        $result[&#039;token_types&#039;] = $this-&amp;gt;token_types;&lt;br /&gt;
        // 3. Game options&lt;br /&gt;
        $table_options = $this-&amp;gt;getTableOptions();&lt;br /&gt;
        $result [&#039;table_options&#039;] = [];&lt;br /&gt;
        foreach ( $table_options as $option_id =&amp;gt; $option ) {&lt;br /&gt;
            $value = 0;&lt;br /&gt;
            if (array_key_exists($option_id, $this-&amp;gt;gamestate-&amp;gt;table_globals)) {&lt;br /&gt;
                $value = (int) $this-&amp;gt;gamestate-&amp;gt;table_globals [$option_id];&lt;br /&gt;
            }&lt;br /&gt;
            $result [&#039;table_options&#039;] [$option_id] = $option;&lt;br /&gt;
            $result [&#039;table_options&#039;] [$option_id] [&#039;value&#039;] = $value;&lt;br /&gt;
        }&lt;br /&gt;
        // 4. Rest of the database filtered by current player&lt;br /&gt;
        $current_player_id = self::getCurrentPlayerId(); // !! We must only return informations visible by this player !!&lt;br /&gt;
        $result [&#039;tokens&#039;] = [];&lt;br /&gt;
        $players_basic = $this-&amp;gt;loadPlayersBasicInfos();&lt;br /&gt;
        foreach ( $players_basic as $player_id =&amp;gt; $player_info ) {&lt;br /&gt;
            $color = $player_info [&#039;player_color&#039;];&lt;br /&gt;
            // tableau is public info&lt;br /&gt;
            $result [&#039;tokens&#039;]+=$this-&amp;gt;tokens-&amp;gt;getTokensInLocation(&amp;quot;tableau_$color&amp;quot;); // this is sql access layer for tokens table but it can be just raw SQL query with getCollectionFromDb kind of call&lt;br /&gt;
            //  hand if private info&lt;br /&gt;
            if ($current_player_id==$player_id) {&lt;br /&gt;
                $result [&#039;tokens&#039;]+=$this-&amp;gt;tokens-&amp;gt;getTokensInLocation(&amp;quot;hand_$color&amp;quot;);&lt;br /&gt;
            } else {&lt;br /&gt;
                $result [&#039;counters&#039;][&amp;quot;hand_$color&amp;quot;]=$this-&amp;gt;tokens-&amp;gt;countTokensInLocation(&amp;quot;hand_$color&amp;quot;);&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
        $result [&#039;counters&#039;][&amp;quot;deck]=$this-&amp;gt;tokens-&amp;gt;countTokensInLocation(&amp;quot;deck&amp;quot;);&lt;br /&gt;
        $result [&#039;counters&#039;][&amp;quot;discard&amp;quot;]=$this-&amp;gt;tokens-&amp;gt;countTokensInLocation(&amp;quot;discard&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
        return $result;&lt;br /&gt;
    }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Create State Machine ==&lt;br /&gt;
&lt;br /&gt;
Now you need to create a game state machine. &lt;br /&gt;
&lt;br /&gt;
The state handling is spread across 4 files, so you have to make sure all the pieces are connected together. The state machine &amp;lt;code&amp;gt;states.inc.php&amp;lt;/code&amp;gt; defines all the states, and function handlers on php side in a form of string, and if any of these functions are not implemented it would be very hard to debug because it will break in random places.&lt;br /&gt;
&lt;br /&gt;
Please first watch this again [http://www.slideshare.net/boardgamearena/bga-studio-focus-on-bga-game-state-machine  BGA game state machine] and then please read [[Your game state machine: states.inc.php]].&lt;br /&gt;
&lt;br /&gt;
Now the state machine should be relatively simple. If you find yourself with machine with more than 20 states its probably not the way to go. Not all the player interactions need separate states, a lot of things can be implemented directly on client, i.e. if your player need to select a reward token, which offers choice of resource, instead of two states on server just have one state on server and possible few states on client (client side states) to collect this info.&lt;br /&gt;
&lt;br /&gt;
It is important to implement proper state handling on the client, usually it results in big &amp;lt;code&amp;gt;switch&amp;lt;/code&amp;gt; in &amp;lt;code&amp;gt;onUpdateActionButtons&amp;lt;/code&amp;gt; method.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
onUpdateActionButtons: function(stateName, args) {&lt;br /&gt;
	console.log(&#039;onUpdateActionButtons: &#039; + stateName + &amp;quot; &amp;quot; + this.isCurrentPlayerActive() + &amp;quot; args:&amp;quot;, args);&lt;br /&gt;
	if (!this.isCurrentPlayerActive()) return;&lt;br /&gt;
	switch (stateName) {&lt;br /&gt;
		case &#039;playerTurn&#039;:&lt;br /&gt;
	        dojo.query(&#039;.card&#039;).addClass(&#039;active_slot&#039;); // activate board elements, when using static connector, see user input below&lt;br /&gt;
		// add buttons&lt;br /&gt;
		this.addActionButton(&#039;button_pass&#039;, _(&#039;Pass&#039;), () =&amp;gt; { this.bgaPerformAction(&#039;pass&#039;); });&lt;br /&gt;
		// case...&lt;br /&gt;
	}&lt;br /&gt;
	if (this.on_client_state &amp;amp;&amp;amp; !$(&#039;button_cancel&#039;)) {&lt;br /&gt;
		this.addActionButton(&#039;button_cancel&#039;, _(&#039;Cancel&#039;), &#039;cancelLocalStateEffects&#039;, 0, 0, &#039;gray&#039;);&lt;br /&gt;
		this.addTooltip(&#039;button_cancel&#039;, _(&amp;quot;This means cancel current action and start thinking&amp;quot;), &#039;&#039;);&lt;br /&gt;
	}&lt;br /&gt;
},&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
I keep &amp;lt;code&amp;gt;onLeavingState&amp;lt;/code&amp;gt; pretty generic (and &amp;lt;code&amp;gt;onEnteringState&amp;lt;/code&amp;gt; just for logging)&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
onLeavingState: function (stateName) {&lt;br /&gt;
	console.log(&#039;Leaving state: &#039; + stateName);&lt;br /&gt;
	dojo.query(&#039;.active_slot&#039;).removeClass(&#039;active_slot&#039;);&lt;br /&gt;
	dojo.query(&#039;.selected&#039;).removeClass(&#039;selected&#039;);&lt;br /&gt;
},			&lt;br /&gt;
				&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
== Handle Turn Order ==&lt;br /&gt;
&lt;br /&gt;
If your game goes in clockwise order in natural sitting position nothing is really needed, you just use standard API and you are good. However if position is complicated it may require some trickery.&lt;br /&gt;
&lt;br /&gt;
Usually turn order is done by &amp;quot;game state&amp;quot; (see state machine above). Basically it would be two choices:&lt;br /&gt;
* Turn order depends on game situation (such as we take player with highest number of red cubes).&lt;br /&gt;
* Turn order is custom and assign on previous step - i.e. we not playing in clockwise order anymore. In this case you either need to extend player table with new order info (CANNOT use &amp;lt;code&amp;gt;player_no&amp;lt;/code&amp;gt; column) or use order markers that come with game (i.e. &amp;lt;code&amp;gt;marker_ff0000&amp;lt;/code&amp;gt; on &amp;lt;code&amp;gt;position_1&amp;lt;/code&amp;gt;). In this we can build player array in right order and pick next player based on previous player using existing helper function such as &amp;lt;code&amp;gt;$this-&amp;gt;createNextPlayerTable($player_ids)&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Handling turn order would go to the game state which is usually follows active player state.&lt;br /&gt;
&lt;br /&gt;
== Hook User Input  ==&lt;br /&gt;
&lt;br /&gt;
This step can be done before or after some of the server steps, or you go in iterations switching back and forward until you get it done, up to you.&lt;br /&gt;
&lt;br /&gt;
Usually all pieces will be hooked to &amp;lt;code&amp;gt;onclick&amp;lt;/code&amp;gt; during JS &amp;quot;&amp;lt;code&amp;gt;setup&amp;lt;/code&amp;gt;&amp;quot; method, in addition if you create elements during server notification they have to be hooked up at that time.&lt;br /&gt;
&lt;br /&gt;
Also its a good idea to give player a visual cues on what game elements are clickable now, usually it will be a style, such as &amp;quot;&amp;lt;code&amp;gt;active_slot&amp;lt;/code&amp;gt;&amp;quot;, with visual effect of white dashed outline (outline is better than border, because border changes will make piece slightly move since it changes the size) or &amp;lt;code&amp;gt;box-shadow&amp;lt;/code&amp;gt; (i.e. neon glow), that part is done in &amp;lt;code&amp;gt;onUpdateActionsButtons&amp;lt;/code&amp;gt; (see above).&lt;br /&gt;
&lt;br /&gt;
So classic is static handlers, means handler is added in setup method using framework connect function:&lt;br /&gt;
&lt;br /&gt;
  this.connect( $(&#039;my_element&#039;), &#039;onclick&#039;, &#039;onClickOnMyElement&#039; );&lt;br /&gt;
&lt;br /&gt;
This is what is advertised in tutorials, however this is best suited for static html model - where elements are not deleted and recreated. When elements created dynamically if you using this method please be aware of memory leaks - this method stores the pointer to DOM element in arrays of handlers (to be able to disconnect later), but if element is deleted you must call &amp;lt;code&amp;gt;this.disconnect&amp;lt;/code&amp;gt; before deleting with same node reference, or it will leak.&lt;br /&gt;
&lt;br /&gt;
If you using this method your handlers usually look like big ugly switch because it usually depending on state it will do right thing or deny action, typically it will look this this:&lt;br /&gt;
 onCard: function(event) {&lt;br /&gt;
 	dojo.stopEvent(event);&lt;br /&gt;
 	var id = event.currentTarget.id;&lt;br /&gt;
 	console.trace(&amp;quot;on slot &amp;quot; + id);&lt;br /&gt;
 	if (!id) return null;&lt;br /&gt;
 	// check player is active&lt;br /&gt;
 	if (!this.isCurrentPlayerActive()) {&lt;br /&gt;
 		this.showMessage(__(&amp;quot;lang_mainsite&amp;quot;, &amp;quot;This is not your turn&amp;quot;), &amp;quot;error&amp;quot;);&lt;br /&gt;
 		return false;&lt;br /&gt;
 	}&lt;br /&gt;
 	// check node is marked with &amp;quot;active_slot&amp;quot; class (class name is whatever you want)&lt;br /&gt;
 	if (!dojo.hasClass(id, &#039;active_slot&#039;)) {&lt;br /&gt;
 		this.showMoveUnauthorized();&lt;br /&gt;
 		return false;&lt;br /&gt;
 	}&lt;br /&gt;
 	switch (this.gamedatas.gamestate.name) {&lt;br /&gt;
 		case &#039;playerTurn&#039;: // in this case we directly sending data to the server&lt;br /&gt;
 			this.bgaPerformAction(&#039;playCard&#039;, { id }); // note that this wrapper also calls &#039;checkAction&#039; on action parameter&lt;br /&gt;
 			return true;&lt;br /&gt;
 		case &#039;playerDiscard&#039;:  // in this case we need to collect more information, so we using cient state for that&lt;br /&gt;
 			dojo.addClass(id,&#039;selected&#039;); // mark card&lt;br /&gt;
 			this.setClientState(&amp;quot;client_playerTurnSelectBonus&amp;quot;, {&lt;br /&gt;
 				descriptionmyturn: _(&#039;${you} must select bonus for discard&#039;),&lt;br /&gt;
 			});&lt;br /&gt;
 			return true;&lt;br /&gt;
 		default:&lt;br /&gt;
 			this.showMoveUnauthorized();&lt;br /&gt;
 			return false;&lt;br /&gt;
 	}&lt;br /&gt;
 },&lt;br /&gt;
&lt;br /&gt;
You can also manage listeners yourself (vanilla event listeners or dojo). In this case be aware of registering double listener. See more example in [[Game_interface_logic:_yourgamename.js#Players_input|Player&#039;s Input]].&lt;br /&gt;
&lt;br /&gt;
Alternative to static handler are dynamic handlers which are only installed on elements that are active for specific game state, given the example above we would register the listeners in &amp;lt;code&amp;gt;playerTurn&amp;lt;/code&amp;gt; state, i.e. in &amp;lt;code&amp;gt;onUpdateActionButtons&amp;lt;/code&amp;gt; for &amp;lt;code&amp;gt;playerTurn&amp;lt;/code&amp;gt;:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
dojo.query(&#039;.card&#039;).forEach((node) =&amp;gt; {&lt;br /&gt;
	dojo.addClass(node, &#039;active_slot&#039;);&lt;br /&gt;
	dojo.addClass(node, &#039;temp_click_handler&#039;);&lt;br /&gt;
	this.connect(node, &#039;click&#039;, event =&amp;gt; this.bgaPerformAction(&#039;playCard&#039;, { id: event.currentTarget.id }));&lt;br /&gt;
});&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Above we did not need to do the heavy validation because we only presumably added handler in right state to right node and right active player (and removed correctly in between!)&lt;br /&gt;
&lt;br /&gt;
And in &amp;lt;code&amp;gt;onLeavingState&amp;lt;/code&amp;gt; we will disconnect all of them (important!):&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
dojo.query(&#039;.temp_click_handler&#039;).forEach((node) =&amp;gt; {&lt;br /&gt;
	dojo.removeClass(node, &#039;active_slot&#039;);&lt;br /&gt;
	dojo.removeClass(node, &#039;temp_click_handler&#039;);&lt;br /&gt;
	this.disconnect(node, &#039;click&#039;);&lt;br /&gt;
});&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
When user clicks on something, client sends an ajax call to server, server processes it and updates database, server sends notification in response, client hooks animations to server notification. See [[Game_interface_logic:_yourgamename.js#Notifications|JS Notifications]].&lt;br /&gt;
&lt;br /&gt;
Exception to this is client states, if you need to process two step user interaction such as select meeple, place meeple, you may want to avoid sending data to server until step is complete (which may involve direct client side animation). See [[BGA_Studio_Cookbook#Multi_Step_Interactions:_Select_Worker.2FPlace_Worker_-_Using_Selection|Multi-Step Interactions]]&lt;br /&gt;
&lt;br /&gt;
Part of the sending notifications would be to update player&#039;s scoring, BGA uses standard control for score (on JS side), see [[Game_interface_logic:_yourgamename.js#Update_players_score|Update Player&#039;s Score]].&lt;br /&gt;
&lt;br /&gt;
In BGA there is only two ways interact with the server (officially)&lt;br /&gt;
* Initial data dump - when JS client starts it gets all current data via setup() method&lt;br /&gt;
* Game actions - &amp;lt;code&amp;gt;bgaPerformAction&amp;lt;/code&amp;gt;/ajaxcall from client, it returns error or ok (not data), then server send butch of notifications to client&lt;br /&gt;
&lt;br /&gt;
Note current ajaxcall is super vebosy, &amp;lt;code&amp;gt;bgaPerformAction&amp;lt;/code&amp;gt; should be used instead.&lt;br /&gt;
&lt;br /&gt;
When you insert a single action you have to update multiples files:&lt;br /&gt;
* in ggg.js add ajaxcall, i.e. something like &lt;br /&gt;
  this.addActionButton(&#039;pass&#039;, _(&#039;Pass&#039;), () =&amp;gt; this.bgaPerformAction(&#039;pass&#039;));&lt;br /&gt;
* in states.php - add action &#039;pass&#039; to list of possible actions&lt;br /&gt;
  &#039;possibleactions&#039; =&amp;gt; [&#039;pass&#039;,&#039;playCard&#039;]&lt;br /&gt;
* in &amp;lt;code&amp;gt;action.php&amp;lt;/code&amp;gt; - add action handler, see https://en.doc.boardgamearena.com/Players_actions:_yourgamename.action.php&lt;br /&gt;
* in &amp;lt;code&amp;gt;game.php&amp;lt;/code&amp;gt; - add action handler, there you must do the following:&lt;br /&gt;
** call &amp;lt;code&amp;gt;checkAction&amp;lt;/code&amp;gt; to validate the action.&lt;br /&gt;
** possible do more game specific check to validate what player doing is legal (even its not possible from your js side - player can cheat - not allow that).&lt;br /&gt;
** do some database manipulations, using access API.&lt;br /&gt;
** send notifications - this is the &amp;quot;reply&amp;quot; for action.&lt;br /&gt;
** transition to new state (it very rare that  user will remain in the same state, except for multi-active states).&lt;br /&gt;
* back to ggg.js add notification subscription and notification handler (two separate things).&lt;br /&gt;
&lt;br /&gt;
== Implement Notification handling and Animation ==&lt;br /&gt;
&lt;br /&gt;
To handle notification you have to subscribe to it and implement the handlers, see [[Game_interface_logic:_yourgamename.js#Notifications|JS Notifications]].&lt;br /&gt;
&lt;br /&gt;
You can play with animation effects you want put in place, in general all the pieces that move in real game should be moving, such as meeples, resources tokens/cubes, cards, vp tokens. Regular piece animation is provided by BGA framework, but if you use html layout positioning not inline positioning you have to remove absolute positions (inline position styling) after each move. The set of functions for relative position token animation can found in https://github.com/elaskavaia/bga-sharedcode/blob/master/sharedcode.js &lt;br /&gt;
&lt;br /&gt;
If you read [http://www.slideshare.net/boardgamearena/bga-studio-guidelines BGA developers guidelines] you know that you should not get carried away with animation, you are creating a board game not a video game... That also applies to sound effects (in general, you should not use any sounds effects beside already provided by framework).&lt;br /&gt;
&lt;br /&gt;
See  [[Game_interface_logic:_yourgamename.js#Access_and_manipulate_the_DOM|Animation and DOM Manipulation]] for JS reference.&lt;br /&gt;
== Wrap Up ==&lt;br /&gt;
&lt;br /&gt;
* Implement game progression (&amp;lt;code&amp;gt;getGameProgression()&amp;lt;/code&amp;gt; in php).&lt;br /&gt;
* Implement Zombie turn  (&amp;lt;code&amp;gt;zombieTurn()&amp;lt;/code&amp;gt; in php).&lt;br /&gt;
* Define and implemented some meaningful statistics for your game (i.e. total points, point from source A, B, C...).&lt;br /&gt;
* The games logs should explain what happened if player was not looking.&lt;br /&gt;
* You need to implemented tiebreaking (using aux score field) and updated tiebreaker description in meta-data.&lt;br /&gt;
* Make sure all UI strings are marked for translation.&lt;br /&gt;
* UI elements which are images (i.e. tokens, cards) should have tooltips.&lt;br /&gt;
&lt;br /&gt;
== Alpha ==&lt;br /&gt;
When you think you game is completely working there is still bunch of stuff you have to do/check before telling admin that game is ready, please go though this [[Pre-release checklist]].&lt;br /&gt;
&lt;br /&gt;
If you think its completely ready, create a build and click on the &amp;quot;Request ALPHA status&amp;quot; button and admins will check your game and push it to alpha.&lt;br /&gt;
&lt;br /&gt;
Finally, visit the game page for your alpha game (https://boardgamearena.com/gamepanel?game=…) to add the following information if you can:&lt;br /&gt;
* Links to the rules (in multiple languages if available).&lt;br /&gt;
* Links to teaching videos.&lt;br /&gt;
* In the &amp;quot;On the web&amp;quot; section, links to:&lt;br /&gt;
** The official website for the game (if there is one).&lt;br /&gt;
** The BoardGameGeek page for the game.&lt;br /&gt;
* Consider writing a summary of the rules.&lt;br /&gt;
&lt;br /&gt;
Note: later can be done by community members, you don&#039;t actually have to do it yourself&lt;br /&gt;
&lt;br /&gt;
== Level Up ==&lt;br /&gt;
&lt;br /&gt;
When you successfully created a basic game and you want more, it&#039;s time to make it fancy!&lt;br /&gt;
&lt;br /&gt;
* Add game extentions and variants using gameoptions file.&lt;br /&gt;
* Add user preferences for customizations.&lt;br /&gt;
* Use theming! That involves replacing hardwood background, changing tooltips, using different sounds, different fonts, changing state prompt and logs.&lt;br /&gt;
* You can use fancy scoring board at the end of game instead of default nothing.&lt;br /&gt;
* And finally super cool dice rolling, card flipping and victory points evaporating effects.&lt;br /&gt;
&lt;br /&gt;
[[Category:Studio]]&lt;/div&gt;</summary>
		<author><name>Sguzzer Gunayer</name></author>
	</entry>
	<entry>
		<id>https://en.doc.boardgamearena.com/index.php?title=Tutorial_hearts&amp;diff=22768</id>
		<title>Tutorial hearts</title>
		<link rel="alternate" type="text/html" href="https://en.doc.boardgamearena.com/index.php?title=Tutorial_hearts&amp;diff=22768"/>
		<updated>2024-09-26T21:36:53Z</updated>

		<summary type="html">&lt;p&gt;Sguzzer Gunayer: /* Game Database and Game Initialisation */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Studio_Framework_Navigation}}&lt;br /&gt;
&lt;br /&gt;
== Introduction ==&lt;br /&gt;
&lt;br /&gt;
Using this tutorial, you can build a complete working game on the BGA environment: Hearts.&lt;br /&gt;
&lt;br /&gt;
Before you read this tutorial, you must:&lt;br /&gt;
* Read the overall presentations of the BGA Framework ([[Studio|see here]]).&lt;br /&gt;
* Know the rules for Hearts&lt;br /&gt;
* Some-what know the languages used on BGA: PHP, SQL, HTML, CSS, Javascript&lt;br /&gt;
* Set up your development environment [http://en.doc.boardgamearena.com/First_steps_with_BGA_Studio First Steps with BGA Studio]&lt;br /&gt;
* As part of setup you have to have access to your ftp home folder in studio, which would have the full &#039;hearts&#039; game source code. We will be using some resources of this game in this tutorial, so copy it over to local disk if you have not done so.&lt;br /&gt;
&lt;br /&gt;
If you are stuck or have question about this tutorial, post on [https://forum.boardgamearena.com/viewforum.php?f=12 BGA Developers forum]&lt;br /&gt;
&lt;br /&gt;
== Create your first game ==&lt;br /&gt;
&lt;br /&gt;
If you have not already, you have to create a project in BGA Studio. For this tutorial you can create a project heartsYOURNAME where&lt;br /&gt;
YOURNAME is your developer login name. You can also re-use the project you have created for the &amp;quot;First Steps&amp;quot; tutorial above.&lt;br /&gt;
With the initial skeleton of code provided, you can already start a game from the BGA Studio. &lt;br /&gt;
&lt;br /&gt;
1. Find and express start the game in turn-based mode with 4 players. Make sure it works. If you want to see the game as 2nd player press red arrow button on the player panel to switch to that player. More details can be found in [[First_steps_with_BGA_Studio]]&lt;br /&gt;
&lt;br /&gt;
2. Modify the text in heartsYOURNAME_heartsYOURNAME.tpl, reload the page in the browser and make sure your ftp sync works as expected.&lt;br /&gt;
Note: if you have not setup auto-sync do it now, manually copying files is a no-starter.&lt;br /&gt;
&lt;br /&gt;
3. Express stop from settings menu (the gear icon).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;i&amp;gt;Note: please do &#039;&#039;&#039;not&#039;&#039;&#039; use the hearts project code as a base. This tutorial assumes you started with a TEMPLATE project with no prior modifications. Using the hearts project as a base will be very confusing and you won&#039;t be able to follow all the steps.&lt;br /&gt;
&amp;lt;/i&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Attention!!!&amp;lt;/b&amp;gt; Very important note about reloading, if you don&#039;t remember this you may spend hours debugging. The browser caches images. If you change any of these files, you have to do &amp;quot;full reload&amp;quot; which is usually Ctrl+F5 (or Ctrl+reload button on browser) not just a regular reload.&lt;br /&gt;
&lt;br /&gt;
== Hook version control system ==&lt;br /&gt;
&lt;br /&gt;
For a real game, or even for this tutorial, we recommend committing the code to version control right from the start. You are going to find yourself in a situation where the game doesn&#039;t even start anymore and no way of debugging it, unless you have a way to revert. That is where version control becomes very handy. If you are not familiar with version control (e.g. [https://git-scm.com/docs/gittutorial git]) then at least back up your files after each major change. Start now.&lt;br /&gt;
&lt;br /&gt;
Code for this tutorial available is on github: https://github.com/elaskavaia/bga-heartsla&lt;br /&gt;
&lt;br /&gt;
Different revisions represent different steps along the process, starting from original template to a PARTIAL game. The full game can be found in your FTP home folder.&lt;br /&gt;
&lt;br /&gt;
== Update game infos and box graphics ==&lt;br /&gt;
&lt;br /&gt;
Even it does nothing yet, always start by making sure the game looks decent in the game selector, meaning it has nice box graphics and its information is correct. For that we need to edit [[Game_meta-information: gameinfos.inc.php|gameinfos.inc.php]].&lt;br /&gt;
&lt;br /&gt;
For a real game, you would go to [http://boardgamegeek.com BoardGameGeek], find the game, and use the information from BGG to fill in the gameinfos.&lt;br /&gt;
&lt;br /&gt;
So let&#039;s do that. Find &amp;quot;hearts&amp;quot; on BoardGameGeek. (Hint: Original release 1850 :))&lt;br /&gt;
&lt;br /&gt;
You can fill in the year of publishing and bgg id, put &#039;&#039;Public Domain&#039;&#039; under publisher (for a real game, leave an empty string so it won&#039;t be displayed), and a publisher id of 171 for public domain. And as designer and author you can just put your own name just for fun. Set number of players to 4.&lt;br /&gt;
&lt;br /&gt;
  // Players configuration that can be played (ex: 2 to 4 players)&lt;br /&gt;
  &#039;players&#039; =&amp;gt; array( 4 ),  &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Important step&#039;&#039;&#039;: you have to refresh the information in the Studio website through the control panel. So go to Control Panel -&amp;gt; Manage Games -&amp;gt; heartsYOURNAME&lt;br /&gt;
and press Reload for &#039;Reload game informations&#039;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The next step would be to replace &#039;&#039;&#039;game_box.png&#039;&#039;&#039; with nicer images. This can be done from the [[Game metadata manager]]. &lt;br /&gt;
&lt;br /&gt;
Now try to start the game again. If you somehow introduced a syntax error in the gameinfos file it may not work (the game won&#039;t start).&lt;br /&gt;
Always use the &amp;quot;Express Start&amp;quot; button to start the game. You should see a standard state prompt from the template. You should see 4 players on the right: testdude0 .. testdude3.&lt;br /&gt;
To switch between them press the red arrow button near their names, it will open another tab. This way you don&#039;t need to login and logout from multiple accounts!&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;i&amp;gt;Note: if you had run the game before with less than 4 players there is a bug that will prevent you from running it with 4 only (if you did not run it before or run it with 4 players as instructed stop reading this note), to workaround revert back to original players array (i.e. 1,2,3,4), reload game options, then create a table with 4 players, exit that game table, then change gameoptions to 4 only as above, reload game options, create table again.&amp;lt;/i&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Code Rev [https://github.com/elaskavaia/bga-heartsla/tree/4b3a73eeb5acae961ade18473af119e8ce8d1a8f]&lt;br /&gt;
&lt;br /&gt;
== Layout and Graphics ==&lt;br /&gt;
&lt;br /&gt;
In this section we will do graphics of the game, and main layout of the game.&lt;br /&gt;
&lt;br /&gt;
First copy a sprite with cards image from [https://github.com/elaskavaia/bga-heartsla/blob/4b3a73eeb5acae961ade18473af119e8ce8d1a8f/img/cards.jpg hearts img/cards.jpg]  into img/ folder of your project. Project hearts is mounted to your home directory on bga server.&lt;br /&gt;
&amp;lt;blockquote&amp;gt;There are better quality deck of cards image at https://en.doc.boardgamearena.com/Common_board_game_elements_image_resources&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Details about images can be found here: [[Game art: img directory]].&lt;br /&gt;
&lt;br /&gt;
Edit .tpl to add some divs to represent player table and hand area&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;div id=&amp;quot;myhand_wrap&amp;quot; class=&amp;quot;whiteblock&amp;quot;&amp;gt;&lt;br /&gt;
    &amp;lt;h3&amp;gt;My Hand&amp;lt;/h3&amp;gt;&lt;br /&gt;
    &amp;lt;div id=&amp;quot;myhand&amp;quot;&amp;gt;&lt;br /&gt;
    &amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If you refresh you should see now white area with My Hand title.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[File:Heartsla-tpl2.png]]&lt;br /&gt;
&lt;br /&gt;
Now lets add a card into the hand, just so you can feel it. Edit .tpl and a playertablecard div inside a hand div&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
...&lt;br /&gt;
    &amp;lt;div id=&amp;quot;myhand&amp;quot;&amp;gt;&lt;br /&gt;
       &amp;lt;div class=&amp;quot;playertablecard&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
    &amp;lt;/div&amp;gt;&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Edit .css file&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
.playertablecard {&lt;br /&gt;
    display: inline-block;&lt;br /&gt;
    position: relative;&lt;br /&gt;
    margin-top: 5px;&lt;br /&gt;
    width: 72px;&lt;br /&gt;
    height: 96px;&lt;br /&gt;
    background-image: url(&#039;img/cards.jpg&#039;); /* temp hack to see it */&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
When you change existing graphics files remember that you have to FORCE-reload page, i.e. Ctrl-F5, otherwise its cached.&lt;br /&gt;
&lt;br /&gt;
You should see this:&lt;br /&gt;
&lt;br /&gt;
[[File:Heartsla-tpl3.png]]&lt;br /&gt;
&lt;br /&gt;
Awesome! Now lets do the rest of layout.&lt;br /&gt;
&lt;br /&gt;
There are few ways of how html could have been generated, you could have start with nothing and generate&lt;br /&gt;
all by java script. Or you could have started with complete game markup in html and make java script just hide and move pieces around. BGA framework provides also a third way which is mix of both plus template engine to generate HTML using php. So lets do that.&lt;br /&gt;
&lt;br /&gt;
Note: generating blocks in js only is probably simpler now with template strings.&lt;br /&gt;
&lt;br /&gt;
Change .tpl file to have this inside&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;div id=&amp;quot;playertables&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
    &amp;lt;!-- BEGIN playerhandblock --&amp;gt;&lt;br /&gt;
    &amp;lt;div class=&amp;quot;playertable whiteblock playertable_{DIR}&amp;quot;&amp;gt;&lt;br /&gt;
        &amp;lt;div class=&amp;quot;playertablename&amp;quot; style=&amp;quot;color:#{PLAYER_COLOR}&amp;quot;&amp;gt;&lt;br /&gt;
            {PLAYER_NAME}&lt;br /&gt;
        &amp;lt;/div&amp;gt;&lt;br /&gt;
        &amp;lt;div class=&amp;quot;playertablecard&amp;quot; id=&amp;quot;playertablecard_{PLAYER_ID}&amp;quot;&amp;gt;&lt;br /&gt;
        &amp;lt;/div&amp;gt;&lt;br /&gt;
    &amp;lt;/div&amp;gt;&lt;br /&gt;
    &amp;lt;!-- END playerhandblock --&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div id=&amp;quot;myhand_wrap&amp;quot; class=&amp;quot;whiteblock&amp;quot;&amp;gt;&lt;br /&gt;
    &amp;lt;h3&amp;gt;{MY_HAND}&amp;lt;/h3&amp;gt;&lt;br /&gt;
    &amp;lt;div id=&amp;quot;myhand&amp;quot;&amp;gt;&lt;br /&gt;
       &amp;lt;div class=&amp;quot;playertablecard&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
    &amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
What we did is we added &amp;quot;block&amp;quot; playerhandblock, it is marked up using html comments. {VAR} notation is used&lt;br /&gt;
to inject variables and &lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  &amp;lt;!-- BEGIN xxx --&amp;gt; &lt;br /&gt;
   inside &lt;br /&gt;
  &amp;lt;!-- END xxx --&amp;gt; &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
effectively allows us to do template loops.&lt;br /&gt;
&lt;br /&gt;
In .view.php, fill in the implementation of &amp;lt;code&amp;gt;build_page&amp;lt;/code&amp;gt; like so:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    public function build_page($viewArgs)&lt;br /&gt;
    {&lt;br /&gt;
        // Get players&lt;br /&gt;
        $players = $this-&amp;gt;game-&amp;gt;loadPlayersBasicInfos();&lt;br /&gt;
        &lt;br /&gt;
        $template = $this-&amp;gt;getGameName() . &amp;quot;_&amp;quot; . $this-&amp;gt;getGameName();&lt;br /&gt;
        &lt;br /&gt;
        $directions = array( &#039;S&#039;, &#039;W&#039;, &#039;N&#039;, &#039;E&#039; );&lt;br /&gt;
        &lt;br /&gt;
        // this will inflate our player block with actual players data&lt;br /&gt;
        $this-&amp;gt;page-&amp;gt;begin_block($template, &amp;quot;playerhandblock&amp;quot;);&lt;br /&gt;
        foreach ( $players as $player_id =&amp;gt; $info ) {&lt;br /&gt;
            $dir = array_shift($directions);&lt;br /&gt;
            $this-&amp;gt;page-&amp;gt;insert_block(&amp;quot;playerhandblock&amp;quot;, array (&amp;quot;PLAYER_ID&amp;quot; =&amp;gt; $player_id,&lt;br /&gt;
                    &amp;quot;PLAYER_NAME&amp;quot; =&amp;gt; $players [$player_id] [&#039;player_name&#039;],&lt;br /&gt;
                    &amp;quot;PLAYER_COLOR&amp;quot; =&amp;gt; $players [$player_id] [&#039;player_color&#039;],&lt;br /&gt;
                    &amp;quot;DIR&amp;quot; =&amp;gt; $dir ));&lt;br /&gt;
        }&lt;br /&gt;
        // this will make our My Hand text translatable&lt;br /&gt;
        $this-&amp;gt;tpl[&#039;MY_HAND&#039;] = $this-&amp;gt;_(&amp;quot;My hand&amp;quot;);&lt;br /&gt;
    }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
What it does is for each player we have it will replicate the html between &amp;lt;!-- BEGIN playerhandblock --&amp;gt; and &amp;lt;!-- END playerhandblock --&amp;gt; tags, substituting the variable denoted by {XXX}&lt;br /&gt;
with the values you provide. The DIR variable in this case we pulling from directions array (where array_shift will take first element and remove it from the array).&lt;br /&gt;
&lt;br /&gt;
Reload. If everything went well you should see this:&lt;br /&gt;
&lt;br /&gt;
[[File:Hearts all rows.png|alt=Display a list of all players, with a dummy card in each position]]&lt;br /&gt;
&lt;br /&gt;
These are &amp;quot;tableau&amp;quot; areas for 4 players plus My hand visible only to one player. They are not exactly how we wanted them to be because we did not edit .css yet.&lt;br /&gt;
&lt;br /&gt;
Now edit .css, add these lines after import before our previous definition&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
/** Table layout **/&lt;br /&gt;
&lt;br /&gt;
#playertables {&lt;br /&gt;
    position: relative;&lt;br /&gt;
    width: 710px;&lt;br /&gt;
    height: 340px;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.playertablename {&lt;br /&gt;
    font-weight: bold;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.playertable {&lt;br /&gt;
    position: absolute;&lt;br /&gt;
    text-align: center;&lt;br /&gt;
    width: 180px;&lt;br /&gt;
    height: 130px;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.playertable_N {&lt;br /&gt;
    left: 50%;&lt;br /&gt;
    top: 0px;&lt;br /&gt;
    margin-left: -90px; /* half of 180 */&lt;br /&gt;
}&lt;br /&gt;
.playertable_S {&lt;br /&gt;
    left: 50%;&lt;br /&gt;
    bottom: 0px;&lt;br /&gt;
    margin-left: -90px; /* half of 180 */&lt;br /&gt;
}&lt;br /&gt;
.playertable_W {&lt;br /&gt;
    left: 0px;&lt;br /&gt;
    top: 50%;&lt;br /&gt;
    margin-top: -55px; /* half of 130 */&lt;br /&gt;
}&lt;br /&gt;
.playertable_E {&lt;br /&gt;
    right: 0px;&lt;br /&gt;
    top: 50%;&lt;br /&gt;
    margin-top: -55px; /* half of 130 */&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Now you force Reload and you should see this:&lt;br /&gt;
[[File:Heartsla-tpl5.png]]&lt;br /&gt;
&lt;br /&gt;
This is almost all we need for graphics and layout, there are few tweaks left there but lets do some more heavy lifting now.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;i&amp;gt;Note: if you did not see changes you may have not force reloaded, force means you use Ctrl+F5 or Cltr+Shift-R, if you don&#039;t &amp;quot;force&amp;quot; browser will use cached version of images! Which is not what you just changed&amp;lt;/i&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;i&amp;gt;Another Note: In general if you have auto-sync you don&#039;t need to reload if you change game.php file, you need normal reload if you change js, and force reload for images. If you changed state machine or database you likely need to restart the game.&amp;lt;/i&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Game Interface JS Stock ==&lt;br /&gt;
&lt;br /&gt;
The BGA framework provides a few out of the box classes to deal with cards. The client side&lt;br /&gt;
contains a class called [[Stock]] and it can be used for any dynamic html &amp;quot;pieces&amp;quot; management that uses&lt;br /&gt;
common sprite images. On the server side we will use the [[Deck]] class which we discuss later.&lt;br /&gt;
&lt;br /&gt;
If you open cards.jpg in an image viewer you will see that it is a &amp;quot;sprite&amp;quot; image - a 13x4 grid of images stitched together,&lt;br /&gt;
which is a very efficient way to transport images. So we will use the Stock class to mark up these images and create&lt;br /&gt;
&amp;quot;card&amp;quot; divs for us.&lt;br /&gt;
&lt;br /&gt;
First, we need to add &#039;&#039;&#039;ebg/stock&#039;&#039;&#039; as a dependency in the hearts.js file:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
define([&lt;br /&gt;
    &amp;quot;dojo&amp;quot;,&amp;quot;dojo/_base/declare&amp;quot;,&lt;br /&gt;
    &amp;quot;ebg/core/gamegui&amp;quot;,&lt;br /&gt;
    &amp;quot;ebg/counter&amp;quot;,&lt;br /&gt;
    &amp;quot;ebg/stock&amp;quot;     /// &amp;lt;==== HERE&lt;br /&gt;
],&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Then add this to the Javascript constructor, this will define size of our cards&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
            console.log(&#039;hearts constructor&#039;);&lt;br /&gt;
            this.cardwidth = 72;&lt;br /&gt;
            this.cardheight = 96;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The stock is initialized in the Javascript &amp;quot;setup&amp;quot; method like this:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    // TODO: Set up your game interface here, according to &amp;quot;gamedatas&amp;quot;&lt;br /&gt;
&lt;br /&gt;
    // Player hand&lt;br /&gt;
    this.playerHand = new ebg.stock(); // new stock object for hand&lt;br /&gt;
    this.playerHand.create( this, $(&#039;myhand&#039;), this.cardwidth, this.cardheight );&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
As parameters of the &amp;quot;create&amp;quot; method, we provided the width/height of an item (a card), and the container div &amp;quot;myhand&amp;quot; - which is an id of &amp;quot;div&amp;quot; element from our .tpl file representing a player hand.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Then, we must tell the stock what items it is going to display during its life: the 52 cards of a standard card game from a CSS sprite image named &amp;quot;cards.jpg&amp;quot; with all the cards arranged in 4 rows and 13 columns.&lt;br /&gt;
&lt;br /&gt;
Here&#039;s how we tell stock what item types to display:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
            this.playerHand.image_items_per_row = 13; // 13 images per row&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
            // Create cards types:&lt;br /&gt;
            for (var color = 1; color &amp;lt;= 4; color++) {&lt;br /&gt;
                for (var value = 2; value &amp;lt;= 14; value++) {&lt;br /&gt;
                    // Build card type id&lt;br /&gt;
                    var card_type_id = this.getCardUniqueId(color, value);&lt;br /&gt;
                    this.playerHand.addItemType(card_type_id, card_type_id, g_gamethemeurl + &#039;img/cards.jpg&#039;, card_type_id);&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
And add this function to the utilities section&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        // Get card unique identifier based on its color and value&lt;br /&gt;
        getCardUniqueId : function(color, value) {&lt;br /&gt;
            return (color - 1) * 13 + (value - 2);&lt;br /&gt;
        },&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Explanations:&lt;br /&gt;
* At first, we tell the stock component that our CSS sprite contains 13 items per row. This way, it can find the correct image for each card type id.&lt;br /&gt;
* Then for the 4x13 cards, we call the &#039;&#039;&#039;addItemType&#039;&#039;&#039; method that creates the type. The arguments are the type id, the weight of the card (for sorting purpose), the URL of our CSS sprite, and the position of our card image in the CSS sprite. It happens to be the same number in our case.&lt;br /&gt;
&lt;br /&gt;
Note: we need to generate a unique ID for each type of card based on its color and value.  For that we create a function &#039;&#039;&#039;getCardUniqueId&#039;&#039;&#039;. The type is the unique identifier of the TYPE of the card, e.g., the queen of spades encoded as an integer. If our deck had 2 standard card decks we would have had 2 queens of spades; they would share the same type and the same image but would have different ids. NOTE: It&#039;s unfortunate that they named this &#039;&#039;&#039;getCardUniqueId&#039;&#039;&#039;; it should have been &#039;&#039;&#039;getCardUniqueType&#039;&#039;&#039;, because it really isn&#039;t an id, but a TYPE of card. The type of the item should either be a reversible function of its properties (i.e., kind of suite * 13 + value) or just an enumerator described in material.inc.php. In this specific case it&#039;s a synthetic type id, which also the same as the number of the card in the sprite image (i.e., if you enumerate each image in sprite going left to right, then top to bottom).&lt;br /&gt;
&lt;br /&gt;
Now let&#039;s add the 5 of Hearts to the player&#039;s hand just for fun (this code will go in setup method after types initialization):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
// 2 = hearts, 5 is 5, and 42 is the card id, which normally would come from db&lt;br /&gt;
this.playerHand.addToStockWithId( this.getCardUniqueId( 2, 5 ), 42 );&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This will add the card with id 42 and type 16 ( (2-1)*13+(5-2)=16 ). &lt;br /&gt;
&lt;br /&gt;
Note that number 16 would not be something you can see in database, Deck database will have separate field for type and type_arg where type is suite and type_arg is number, so its not the same thing, but you can use same formula to convert. Number 42 on the other hand would be id field in database. But we get to database in the later section.&lt;br /&gt;
&lt;br /&gt;
If you reload now you should see the 5 of hearts in &amp;quot;your hand&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
Stock control can handle clicking on items and forms the selection. You can immediately react to selection&lt;br /&gt;
or you can query it later; for example when user presses some other button.&lt;br /&gt;
&lt;br /&gt;
Let&#039;s hook it up. Add this in the setup method in .js file, after this.playerHand is initialised:&lt;br /&gt;
&lt;br /&gt;
     dojo.connect( this.playerHand, &#039;onChangeSelection&#039;, this, &#039;onPlayerHandSelectionChanged&#039; );&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Then find the Player&#039;s action comment section in .js file and add a handler after the comment:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        onPlayerHandSelectionChanged: function() {&lt;br /&gt;
            var items = this.playerHand.getSelectedItems();&lt;br /&gt;
&lt;br /&gt;
            if (items.length &amp;gt; 0) {&lt;br /&gt;
                if (this.checkAction(&#039;actPlayCard&#039;, true)) {&lt;br /&gt;
                    // Can play a card&lt;br /&gt;
&lt;br /&gt;
                    var card_id = items[0].id;&lt;br /&gt;
                    console.log(&amp;quot;on playCard &amp;quot;+card_id);&lt;br /&gt;
&lt;br /&gt;
                    this.playerHand.unselectAll();&lt;br /&gt;
                } else if (this.checkAction(&#039;actGiveCards&#039;)) {&lt;br /&gt;
                    // Can give cards =&amp;gt; let the player select some cards&lt;br /&gt;
                } else {&lt;br /&gt;
                    this.playerHand.unselectAll();&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        },&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Note : If you already have an example handler &amp;lt;code&amp;gt;onCardClick: function( card_id )&amp;lt;/code&amp;gt;, go ahead and remove that handler, it is a duplicate of what we are implementing in this tutorial and may cause issues later on.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
The function name of the handler is 4th parameter of the dojo.connect function. Make sure you spell it correctly or there will be unpredictable effects.&lt;br /&gt;
&lt;br /&gt;
Now if you reload, open the Javascript Console (F12), and then click on the card in My Hand, you should see:&lt;br /&gt;
  on playCard 42&lt;br /&gt;
printed on the console&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Note : You need to be the active player to have rights to play a card and so log your message in the console&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
== Game Database and Game Initialization ==&lt;br /&gt;
&lt;br /&gt;
Next step, you want to design a game database and setup a new game (on the server side).&lt;br /&gt;
For that we need to a) modify the database schema to add our cards data b) add some global variables into&lt;br /&gt;
the existing globals table.&lt;br /&gt;
&lt;br /&gt;
To modify the schema, first exit your existing game(s). Open &#039;&#039;&#039;dbmodel.sql&#039;&#039;&#039; file and uncomment the card table creation.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
CREATE TABLE IF NOT EXISTS `card` (&lt;br /&gt;
  `card_id` int(10) unsigned NOT NULL AUTO_INCREMENT,&lt;br /&gt;
  `card_type` varchar(16) NOT NULL,&lt;br /&gt;
  `card_type_arg` int(11) NOT NULL,&lt;br /&gt;
  `card_location` varchar(16) NOT NULL,&lt;br /&gt;
  `card_location_arg` int(11) NOT NULL,&lt;br /&gt;
  PRIMARY KEY (`card_id`)&lt;br /&gt;
) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=1 ;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This is the &amp;quot;card&amp;quot; table which will be managed by the Deck php class.&lt;br /&gt;
&lt;br /&gt;
In addition we want a little piece of information in the players table:&lt;br /&gt;
&lt;br /&gt;
  -- add info about first player&lt;br /&gt;
  ALTER TABLE `player` ADD `player_first` BOOLEAN NOT NULL DEFAULT &#039;0&#039;;&lt;br /&gt;
&lt;br /&gt;
Not sure why they put this into the player table, as we could use a global db variable to hold first player as easily.&lt;br /&gt;
But I am just following the existing code more-or-less.&lt;br /&gt;
&lt;br /&gt;
Next we finally get into .game.php class, where the main logic and db interaction would be. Find php constructor which should be &lt;br /&gt;
  function __construct( )&lt;br /&gt;
This is first function in a file. Add this code to constructor.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        parent::__construct();&lt;br /&gt;
        $this-&amp;gt;initGameStateLabels( array( &lt;br /&gt;
                         &amp;quot;currentHandType&amp;quot; =&amp;gt; 10, &lt;br /&gt;
                         &amp;quot;trickColor&amp;quot; =&amp;gt; 11, &lt;br /&gt;
                         &amp;quot;alreadyPlayedHearts&amp;quot; =&amp;gt; 12,&lt;br /&gt;
                          ) );&lt;br /&gt;
&lt;br /&gt;
        $this-&amp;gt;cards = $this-&amp;gt;getNew( &amp;quot;module.common.deck&amp;quot; );&lt;br /&gt;
        $this-&amp;gt;cards-&amp;gt;init( &amp;quot;card&amp;quot; );&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Here we are initializing three &amp;quot;Game State Variables&amp;quot; which are variables stored in the database. They are integers.&lt;br /&gt;
It must start with values higher or equal to 10 since values lower than 10 are reserved. These values are stored by numeric ids&lt;br /&gt;
in the database, but in the php we associate them with string labels for convenience of access. &lt;br /&gt;
&lt;br /&gt;
The variables are:&lt;br /&gt;
&lt;br /&gt;
* &amp;quot;trickColor&amp;quot;: numbers from 1 to 4 that map to card suit (not sure why it&#039;s called color; maybe it&#039;s a translation from French);&lt;br /&gt;
* &amp;quot;alreadyPlayedHearts&amp;quot;: a boolean flag (0 or 1) indicating whether somebody used hearts on the trick;&lt;br /&gt;
* &amp;quot;currentHandType&amp;quot;: stores the value to indicate who to give cards to during exchange.&lt;br /&gt;
&lt;br /&gt;
The next 2 lines are creating $this-&amp;gt;cards object and associating it with &amp;quot;card&amp;quot; table in the the database.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;i&amp;gt;If we called db table &#039;foo&#039; instead of &#039;card&#039; the last statement would have been  $this-&amp;gt;cards-&amp;gt;init( &amp;quot;foo&amp;quot; )&amp;lt;/i&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
At this point I would start a new game and make sure it starts, then exit. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;i&amp;gt;&lt;br /&gt;
If you made a mistake&lt;br /&gt;
in the .sql or php constructor the game won&#039;t start, and good luck debugging it. (That is why it&#039;s important to check&lt;br /&gt;
once in a while to make sure it still starts while you remember what you have changed.)&lt;br /&gt;
&amp;lt;/i&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Code Rev [https://github.com/elaskavaia/bga-heartsla/tree/e3a049257b592ff6167688d4d344f8a83d349b08]&lt;br /&gt;
&lt;br /&gt;
Now we can go to game initialization &#039;&#039;&#039;setupNewGame&#039;&#039;&#039; in game.php. This method is called only once when the game is created.&lt;br /&gt;
&lt;br /&gt;
In your template project you should have code that deals with player table, just leave it as is. Start inserting the&lt;br /&gt;
other code after &amp;quot;Start the game initialization&amp;quot; comment.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        // Init global values with their initial values&lt;br /&gt;
&lt;br /&gt;
        // Note: hand types: 0 = give 3 cards to player on the left&lt;br /&gt;
        //                   1 = give 3 cards to player on the right&lt;br /&gt;
        //                   2 = give 3 cards to player opposite&lt;br /&gt;
        //                   3 = keep cards&lt;br /&gt;
        $this-&amp;gt;setGameStateInitialValue( &#039;currentHandType&#039;, 0 );&lt;br /&gt;
        &lt;br /&gt;
        // Set current trick color to zero (= no trick color)&lt;br /&gt;
        $this-&amp;gt;setGameStateInitialValue( &#039;trickColor&#039;, 0 );&lt;br /&gt;
        &lt;br /&gt;
        // Mark if we already played hearts during this hand&lt;br /&gt;
        $this-&amp;gt;setGameStateInitialValue( &#039;alreadyPlayedHearts&#039;, 0 );&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Here we initialize all the globals to 0.&lt;br /&gt;
&lt;br /&gt;
Next is to create our cards in the database. We have one deck of cards so it&#039;s pretty simple.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        // Create cards&lt;br /&gt;
        $cards = array ();&lt;br /&gt;
        foreach ( $this-&amp;gt;colors as $color_id =&amp;gt; $color ) {&lt;br /&gt;
            // spade, heart, diamond, club&lt;br /&gt;
            for ($value = 2; $value &amp;lt;= 14; $value ++) {&lt;br /&gt;
                //  2, 3, 4, ... K, A&lt;br /&gt;
                $cards [] = array (&#039;type&#039; =&amp;gt; $color_id,&#039;type_arg&#039; =&amp;gt; $value,&#039;nbr&#039; =&amp;gt; 1 );&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
        &lt;br /&gt;
        $this-&amp;gt;cards-&amp;gt;createCards( $cards, &#039;deck&#039; );&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This code that will create one of each card. But don&#039;t run it yet, because we missing $this-&amp;gt;colors.&lt;br /&gt;
So we have state of the game in the database, but there is some static game information which never changes.&lt;br /&gt;
This information should be stored in material.inc.php and this way it can be accessed from all .php files (and .js if you send it via getAllDatas()).&lt;br /&gt;
We will edit this file now by adding these lines&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$this-&amp;gt;colors = array(&lt;br /&gt;
    1 =&amp;gt; array( &#039;name&#039; =&amp;gt; clienttranslate(&#039;spade&#039;),&lt;br /&gt;
                &#039;nametr&#039; =&amp;gt; $this-&amp;gt;_(&#039;spade&#039;) ),&lt;br /&gt;
    2 =&amp;gt; array( &#039;name&#039; =&amp;gt; clienttranslate(&#039;heart&#039;),&lt;br /&gt;
                &#039;nametr&#039; =&amp;gt; $this-&amp;gt;_(&#039;heart&#039;) ),&lt;br /&gt;
    3 =&amp;gt; array( &#039;name&#039; =&amp;gt; clienttranslate(&#039;club&#039;),&lt;br /&gt;
                &#039;nametr&#039; =&amp;gt; $this-&amp;gt;_(&#039;club&#039;) ),&lt;br /&gt;
    4 =&amp;gt; array( &#039;name&#039; =&amp;gt; clienttranslate(&#039;diamond&#039;),&lt;br /&gt;
                &#039;nametr&#039; =&amp;gt; $this-&amp;gt;_(&#039;diamond&#039;) )&lt;br /&gt;
);&lt;br /&gt;
&lt;br /&gt;
$this-&amp;gt;values_label = array(&lt;br /&gt;
    2 =&amp;gt;&#039;2&#039;,&lt;br /&gt;
    3 =&amp;gt; &#039;3&#039;,&lt;br /&gt;
    4 =&amp;gt; &#039;4&#039;,&lt;br /&gt;
    5 =&amp;gt; &#039;5&#039;,&lt;br /&gt;
    6 =&amp;gt; &#039;6&#039;,&lt;br /&gt;
    7 =&amp;gt; &#039;7&#039;,&lt;br /&gt;
    8 =&amp;gt; &#039;8&#039;,&lt;br /&gt;
    9 =&amp;gt; &#039;9&#039;,&lt;br /&gt;
    10 =&amp;gt; &#039;10&#039;,&lt;br /&gt;
    11 =&amp;gt; clienttranslate(&#039;J&#039;),&lt;br /&gt;
    12 =&amp;gt; clienttranslate(&#039;Q&#039;),&lt;br /&gt;
    13 =&amp;gt; clienttranslate(&#039;K&#039;),&lt;br /&gt;
    14 =&amp;gt; clienttranslate(&#039;A&#039;)&lt;br /&gt;
);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Where $this-&amp;gt;colors will define Suit labels and $this-&amp;gt;values_label will define value labels.&lt;br /&gt;
If you noticed, we have two of each label for suits. This is because sometimes we need translated values on the php&lt;br /&gt;
side and sometimes we don&#039;t. In this case &#039;&#039;&#039;nametr&#039;&#039;&#039; will return a translated value in php, which is only useful when you throw exceptions to show the right strings. If you pass a value to the client via notification you should always use untranslated strings, and the client will translate it. &#039;clienttranslate&#039; marks the value for translation but does not actually change it for php. For more about this wonderful translation stuff see [[Translations]].&lt;br /&gt;
&lt;br /&gt;
== Full game model synchronisation ==&lt;br /&gt;
&lt;br /&gt;
Now at any point in the game we need to make sure that database information can be reflected back in the UI, so we must fix the &#039;&#039;&#039;getAllDatas&#039;&#039;&#039; function&lt;br /&gt;
to return all possible data we need to reconstruct the game. This is in the game.php file. The template for getAllDatas() already takes care of player info. Let&#039;s just&lt;br /&gt;
add hand and tableau data before we return a result.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        // Cards in player hand&lt;br /&gt;
        $result[&#039;hand&#039;] = $this-&amp;gt;cards-&amp;gt;getCardsInLocation( &#039;hand&#039;, $current_player_id );&lt;br /&gt;
        &lt;br /&gt;
        // Cards played on the table&lt;br /&gt;
        $result[&#039;cardsontable&#039;] = $this-&amp;gt;cards-&amp;gt;getCardsInLocation( &#039;cardsontable&#039; );&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Now on the client side we should display this data, so in your .js file in the setup function (which is the receiver of getAllDatas) replace our hack of putting 5 of Hearts directly into the hand with:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
            // Cards in player&#039;s hand&lt;br /&gt;
            for ( var i in this.gamedatas.hand) {&lt;br /&gt;
                var card = this.gamedatas.hand[i];&lt;br /&gt;
                var color = card.type;&lt;br /&gt;
                var value = card.type_arg;&lt;br /&gt;
                this.playerHand.addToStockWithId(this.getCardUniqueId(color, value), card.id);&lt;br /&gt;
            }&lt;br /&gt;
&lt;br /&gt;
            // Cards played on table&lt;br /&gt;
            for (i in this.gamedatas.cardsontable) {&lt;br /&gt;
                var card = this.gamedatas.cardsontable[i];&lt;br /&gt;
                var color = card.type;&lt;br /&gt;
                var value = card.type_arg;&lt;br /&gt;
                var player_id = card.location_arg;&lt;br /&gt;
                this.playCardOnTable(player_id, color, value, card.id);&lt;br /&gt;
            }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This should show hand and tableau cards now, except we are missing the &#039;&#039;&#039;playCardOnTable&#039;&#039;&#039; function. So find the &#039;&#039;&#039;getCardUniqueId&#039;&#039;&#039; function which&lt;br /&gt;
should be in the utilities section and add this after it:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        playCardOnTable : function(player_id, color, value, card_id) {&lt;br /&gt;
            // player_id =&amp;gt; direction&lt;br /&gt;
            this.addTableCard(value, color, player_id, player_id);&lt;br /&gt;
&lt;br /&gt;
            if (player_id != this.player_id) {&lt;br /&gt;
                // Some opponent played a card&lt;br /&gt;
                // Move card from player panel&lt;br /&gt;
                this.placeOnObject(&#039;cardontable_&#039; + player_id, &#039;overall_player_board_&#039; + player_id);&lt;br /&gt;
            } else {&lt;br /&gt;
                // You played a card. If it exists in your hand, move card from there and remove&lt;br /&gt;
                // corresponding item&lt;br /&gt;
&lt;br /&gt;
                if ($(&#039;myhand_item_&#039; + card_id)) {&lt;br /&gt;
                    this.placeOnObject(&#039;cardontable_&#039; + player_id, &#039;myhand_item_&#039; + card_id);&lt;br /&gt;
                    this.playerHand.removeFromStockById(card_id);&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
&lt;br /&gt;
            // In any case: move it to its final destination&lt;br /&gt;
            this.slideToObject(&#039;cardontable_&#039; + player_id, &#039;playertablecard_&#039; + player_id).play();&lt;br /&gt;
        },&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
For this to work we also need to define the addTableCard&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        addTableCard(value, color, card_player_id, playerTableId) {&lt;br /&gt;
            const x = value - 2;&lt;br /&gt;
            const y = color - 1;&lt;br /&gt;
            document.getElementById(&#039;playertablecard_&#039; + playerTableId).insertAdjacentHTML(&#039;beforeend&#039;, `&lt;br /&gt;
                &amp;lt;div class=&amp;quot;card cardontable&amp;quot; id=&amp;quot;cardontable_${card_player_id}&amp;quot; style=&amp;quot;background-position:-${x}00% -${y}00%&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
            `);&lt;br /&gt;
        },&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
What this does is basically create another card object, because if it is not our card it&#039;s not in our hand (Stock) so&lt;br /&gt;
we have to create it out of thin air. The technique to do that is to implement a Javascript template object defined in the .tpl file with some&lt;br /&gt;
parameters, which will basically create a &amp;quot;div&amp;quot; string (yes you could have used string concatenation but it would not be fancy).&lt;br /&gt;
Now dojo.place places it (the div) on top of a placeholder. Now we have an object with an id of &#039;cardontable_&#039; + player_id. Depending&lt;br /&gt;
on who is playing it we either place it on the player miniboard or in hand (and remove it from hand stock). Then we animate the card move.&lt;br /&gt;
&lt;br /&gt;
We also should fix our .css file now to add style for cardontable and REMOVE background for playertablecard which really is a placeholder div and not a card. (Don&#039;t miss the remove step; it will be all screwy if you do!)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
.playertablecard {&lt;br /&gt;
    display: inline-block;&lt;br /&gt;
    position: relative;&lt;br /&gt;
    margin-top: 5px;&lt;br /&gt;
    width: 72px;&lt;br /&gt;
    height: 96px;&lt;br /&gt;
    /* we remove background-image here */&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
/*** cards on table ***/&lt;br /&gt;
&lt;br /&gt;
.cardontable {&lt;br /&gt;
    position: absolute;&lt;br /&gt;
    width: 72px;&lt;br /&gt;
    height: 96px;&lt;br /&gt;
    background-image: url(&#039;img/cards.jpg&#039;); &lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Now to test that it actually works let&#039;s deal cards to players during game initialization:&lt;br /&gt;
&lt;br /&gt;
Add this after createCards in setupNewGame function in the game.php file&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        // Shuffle deck&lt;br /&gt;
        $this-&amp;gt;cards-&amp;gt;shuffle(&#039;deck&#039;);&lt;br /&gt;
        // Deal 13 cards to each players&lt;br /&gt;
        $players = $this-&amp;gt;loadPlayersBasicInfos();&lt;br /&gt;
        foreach ( $players as $player_id =&amp;gt; $player ) {&lt;br /&gt;
            $cards = $this-&amp;gt;cards-&amp;gt;pickCards(13, &#039;deck&#039;, $player_id);&lt;br /&gt;
        } &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Now when you start the game you should see 13 cards in your hand!&lt;br /&gt;
&lt;br /&gt;
We just need to hook-up clicking on card and test if our playCardOnTable works.&lt;br /&gt;
&lt;br /&gt;
Find onPlayerHandSelectionChanged function in the JS file, we should have logging there like  console.log(&amp;quot;on playCard &amp;quot;+card_id);&lt;br /&gt;
So after that insert this (Note: this code is for testing we will replace it with server interaction after we test it.):&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
                    console.log(&amp;quot;on playCard &amp;quot;+card_id);&lt;br /&gt;
                    // type is (color - 1) * 13 + (value - 2)&lt;br /&gt;
                    var type = items[0].type;&lt;br /&gt;
                    var color = Math.floor(type / 13) + 1;&lt;br /&gt;
                    var value = type % 13 + 2;&lt;br /&gt;
                    &lt;br /&gt;
                    this.playCardOnTable(this.player_id,color,value,card_id);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Now if you force reload (because we changed .css before) you should be able to click on card from your hand and see it moving,&lt;br /&gt;
you can click on few cards this way. When you done enjoying the animation, press F5 to get your hand back.&lt;br /&gt;
&lt;br /&gt;
[[File:Heartsla-sync.png]]&lt;br /&gt;
&lt;br /&gt;
Code Rev [https://github.com/elaskavaia/bga-heartsla/tree/01d4e2f595fd14c2adcc97a957d21bb2766f78a8]&lt;br /&gt;
&lt;br /&gt;
== State Machine ==&lt;br /&gt;
&lt;br /&gt;
Now we need to create a game state machine. So the states are (excluding two more states we will add later to handle the exchange of cards at the beginning of the rounds):&lt;br /&gt;
&lt;br /&gt;
* Cards are dealt to all players (lets call it &amp;quot;newHand&amp;quot;)&lt;br /&gt;
* Player is selected who will start a new trick (&amp;quot;newTrick&amp;quot;)&lt;br /&gt;
* Player start or respond to played card (&amp;quot;playerTurn&amp;quot;)&lt;br /&gt;
* Game control is passed to next player or trick is ended (&amp;quot;nextPlayer&amp;quot;)&lt;br /&gt;
* End of hand processing (scoring and check for end of game) (&amp;quot;nextHand&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The state handling spread across 4 files, so you have to make sure all pieces are connected together.&lt;br /&gt;
The state machine states.php defines all the states, and function handlers on php side in a form of string,&lt;br /&gt;
and if any of these functions are not implemented it would be very hard to debug because it will break in random places.&lt;br /&gt;
&lt;br /&gt;
So .states.php&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$machinestates = array(&lt;br /&gt;
&lt;br /&gt;
    // The initial state. Please do not modify.&lt;br /&gt;
    1 =&amp;gt; array(&lt;br /&gt;
        &amp;quot;name&amp;quot; =&amp;gt; &amp;quot;gameSetup&amp;quot;,&lt;br /&gt;
        &amp;quot;description&amp;quot; =&amp;gt; clienttranslate(&amp;quot;Game setup&amp;quot;),&lt;br /&gt;
        &amp;quot;type&amp;quot; =&amp;gt; &amp;quot;manager&amp;quot;,&lt;br /&gt;
        &amp;quot;action&amp;quot; =&amp;gt; &amp;quot;stGameSetup&amp;quot;,&lt;br /&gt;
        &amp;quot;transitions&amp;quot; =&amp;gt; array( &amp;quot;&amp;quot; =&amp;gt; 2 )&lt;br /&gt;
    ),&lt;br /&gt;
    &lt;br /&gt;
    &lt;br /&gt;
    /// New hand&lt;br /&gt;
    2 =&amp;gt; array(&lt;br /&gt;
        &amp;quot;name&amp;quot; =&amp;gt; &amp;quot;newHand&amp;quot;,&lt;br /&gt;
        &amp;quot;description&amp;quot; =&amp;gt; &amp;quot;&amp;quot;,&lt;br /&gt;
        &amp;quot;type&amp;quot; =&amp;gt; &amp;quot;game&amp;quot;,&lt;br /&gt;
        &amp;quot;action&amp;quot; =&amp;gt; &amp;quot;stNewHand&amp;quot;,&lt;br /&gt;
        &amp;quot;updateGameProgression&amp;quot; =&amp;gt; true,   &lt;br /&gt;
        &amp;quot;transitions&amp;quot; =&amp;gt; array( &amp;quot;&amp;quot; =&amp;gt; 30 )&lt;br /&gt;
    ),    &lt;br /&gt;
&lt;br /&gt;
    21 =&amp;gt; array(       &lt;br /&gt;
        &amp;quot;name&amp;quot; =&amp;gt; &amp;quot;giveCards&amp;quot;,&lt;br /&gt;
        &amp;quot;description&amp;quot; =&amp;gt; clienttranslate(&#039;Some players must choose 3 cards to give to ${direction}&#039;),&lt;br /&gt;
        &amp;quot;descriptionmyturn&amp;quot; =&amp;gt; clienttranslate(&#039;${you} must choose 3 cards to give to ${direction}&#039;),&lt;br /&gt;
        &amp;quot;type&amp;quot; =&amp;gt; &amp;quot;multipleactiveplayer&amp;quot;,&lt;br /&gt;
        &amp;quot;action&amp;quot; =&amp;gt; &amp;quot;stGiveCards&amp;quot;,&lt;br /&gt;
        &amp;quot;args&amp;quot; =&amp;gt; &amp;quot;argGiveCards&amp;quot;,&lt;br /&gt;
        &amp;quot;possibleactions&amp;quot; =&amp;gt; array( &amp;quot;actGiveCards&amp;quot; ),&lt;br /&gt;
        &amp;quot;transitions&amp;quot; =&amp;gt; array( &amp;quot;giveCards&amp;quot; =&amp;gt; 22, &amp;quot;skip&amp;quot; =&amp;gt; 22 )        &lt;br /&gt;
    ), &lt;br /&gt;
    &lt;br /&gt;
    22 =&amp;gt; array(&lt;br /&gt;
        &amp;quot;name&amp;quot; =&amp;gt; &amp;quot;takeCards&amp;quot;,&lt;br /&gt;
        &amp;quot;description&amp;quot; =&amp;gt; &amp;quot;&amp;quot;,&lt;br /&gt;
        &amp;quot;type&amp;quot; =&amp;gt; &amp;quot;game&amp;quot;,&lt;br /&gt;
        &amp;quot;action&amp;quot; =&amp;gt; &amp;quot;stTakeCards&amp;quot;,&lt;br /&gt;
        &amp;quot;transitions&amp;quot; =&amp;gt; array( &amp;quot;startHand&amp;quot; =&amp;gt; 30, &amp;quot;skip&amp;quot; =&amp;gt; 30  )&lt;br /&gt;
    ),        &lt;br /&gt;
      &lt;br /&gt;
    &lt;br /&gt;
    // Trick&lt;br /&gt;
    &lt;br /&gt;
    30 =&amp;gt; array(&lt;br /&gt;
        &amp;quot;name&amp;quot; =&amp;gt; &amp;quot;newTrick&amp;quot;,&lt;br /&gt;
        &amp;quot;description&amp;quot; =&amp;gt; &amp;quot;&amp;quot;,&lt;br /&gt;
        &amp;quot;type&amp;quot; =&amp;gt; &amp;quot;game&amp;quot;,&lt;br /&gt;
        &amp;quot;action&amp;quot; =&amp;gt; &amp;quot;stNewTrick&amp;quot;,&lt;br /&gt;
        &amp;quot;transitions&amp;quot; =&amp;gt; array( &amp;quot;&amp;quot; =&amp;gt; 31 )&lt;br /&gt;
    ),       &lt;br /&gt;
    31 =&amp;gt; array(&lt;br /&gt;
        &amp;quot;name&amp;quot; =&amp;gt; &amp;quot;playerTurn&amp;quot;,&lt;br /&gt;
        &amp;quot;description&amp;quot; =&amp;gt; clienttranslate(&#039;${actplayer} must play a card&#039;),&lt;br /&gt;
        &amp;quot;descriptionmyturn&amp;quot; =&amp;gt; clienttranslate(&#039;${you} must play a card&#039;),&lt;br /&gt;
        &amp;quot;type&amp;quot; =&amp;gt; &amp;quot;activeplayer&amp;quot;,&lt;br /&gt;
        &amp;quot;possibleactions&amp;quot; =&amp;gt; array( &amp;quot;actPlayCard&amp;quot; ),&lt;br /&gt;
        &amp;quot;transitions&amp;quot; =&amp;gt; array( &amp;quot;playCard&amp;quot; =&amp;gt; 32 )&lt;br /&gt;
    ), &lt;br /&gt;
    32 =&amp;gt; array(&lt;br /&gt;
        &amp;quot;name&amp;quot; =&amp;gt; &amp;quot;nextPlayer&amp;quot;,&lt;br /&gt;
        &amp;quot;description&amp;quot; =&amp;gt; &amp;quot;&amp;quot;,&lt;br /&gt;
        &amp;quot;type&amp;quot; =&amp;gt; &amp;quot;game&amp;quot;,&lt;br /&gt;
        &amp;quot;action&amp;quot; =&amp;gt; &amp;quot;stNextPlayer&amp;quot;,&lt;br /&gt;
        &amp;quot;transitions&amp;quot; =&amp;gt; array( &amp;quot;nextPlayer&amp;quot; =&amp;gt; 31, &amp;quot;nextTrick&amp;quot; =&amp;gt; 30, &amp;quot;endHand&amp;quot; =&amp;gt; 40 )&lt;br /&gt;
    ), &lt;br /&gt;
    &lt;br /&gt;
    &lt;br /&gt;
    // End of the hand (scoring, etc...)&lt;br /&gt;
    40 =&amp;gt; array(&lt;br /&gt;
        &amp;quot;name&amp;quot; =&amp;gt; &amp;quot;endHand&amp;quot;,&lt;br /&gt;
        &amp;quot;description&amp;quot; =&amp;gt; &amp;quot;&amp;quot;,&lt;br /&gt;
        &amp;quot;type&amp;quot; =&amp;gt; &amp;quot;game&amp;quot;,&lt;br /&gt;
        &amp;quot;action&amp;quot; =&amp;gt; &amp;quot;stEndHand&amp;quot;,&lt;br /&gt;
        &amp;quot;transitions&amp;quot; =&amp;gt; array( &amp;quot;nextHand&amp;quot; =&amp;gt; 2, &amp;quot;endGame&amp;quot; =&amp;gt; 99 )&lt;br /&gt;
    ),     &lt;br /&gt;
   &lt;br /&gt;
    // Final state.&lt;br /&gt;
    // Please do not modify.&lt;br /&gt;
    99 =&amp;gt; array(&lt;br /&gt;
        &amp;quot;name&amp;quot; =&amp;gt; &amp;quot;gameEnd&amp;quot;,&lt;br /&gt;
        &amp;quot;description&amp;quot; =&amp;gt; clienttranslate(&amp;quot;End of game&amp;quot;),&lt;br /&gt;
        &amp;quot;type&amp;quot; =&amp;gt; &amp;quot;manager&amp;quot;,&lt;br /&gt;
        &amp;quot;action&amp;quot; =&amp;gt; &amp;quot;stGameEnd&amp;quot;,&lt;br /&gt;
        &amp;quot;args&amp;quot; =&amp;gt; &amp;quot;argGameEnd&amp;quot;&lt;br /&gt;
    )&lt;br /&gt;
&lt;br /&gt;
);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The full details on these fields are in [[Your_game_state_machine:_states.inc.php]].&lt;br /&gt;
&lt;br /&gt;
But basically we have Player states, in which a human player has to perform an &amp;quot;action&amp;quot; by pressing some button in the UI or selecting some game item, which will trigger js handler, which will do an ajax call to the server.&lt;br /&gt;
&lt;br /&gt;
To make it run we have to define all the handler functions that we referenced in states, which are - one function for state arguments argGiveCards, 4 functions for robot states (where the game performs some action)&lt;br /&gt;
and 1 function for player actions handling.&lt;br /&gt;
In .game.php, find &#039;Game state arguments&#039; section and paste this in:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    function argGiveCards() {&lt;br /&gt;
        return array ();&lt;br /&gt;
    }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This normally passes some parameters to states, but we don&#039;t need anything yet. It&#039;s good to have a placeholder there anyway, so we can fix it later.&lt;br /&gt;
Important: even when it&#039;s a stub, this function must return an array not a scalar.&lt;br /&gt;
&lt;br /&gt;
Let&#039;s do stubs for other functions, find the game state actions section in .game.php file and insert these&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    function stNewHand() {&lt;br /&gt;
        // Take back all cards (from any location =&amp;gt; null) to deck&lt;br /&gt;
        $this-&amp;gt;cards-&amp;gt;moveAllCardsInLocation(null, &amp;quot;deck&amp;quot;);&lt;br /&gt;
        $this-&amp;gt;cards-&amp;gt;shuffle(&#039;deck&#039;);&lt;br /&gt;
        // Deal 13 cards to each players&lt;br /&gt;
        // Create deck, shuffle it and give 13 initial cards&lt;br /&gt;
        $players = $this-&amp;gt;loadPlayersBasicInfos();&lt;br /&gt;
        foreach ( $players as $player_id =&amp;gt; $player ) {&lt;br /&gt;
            $cards = $this-&amp;gt;cards-&amp;gt;pickCards(13, &#039;deck&#039;, $player_id);&lt;br /&gt;
            // Notify player about his cards&lt;br /&gt;
            $this-&amp;gt;notifyPlayer($player_id, &#039;newHand&#039;, &#039;&#039;, array (&#039;cards&#039; =&amp;gt; $cards ));&lt;br /&gt;
        }&lt;br /&gt;
        $this-&amp;gt;setGameStateValue(&#039;alreadyPlayedHearts&#039;, 0);&lt;br /&gt;
        $this-&amp;gt;gamestate-&amp;gt;nextState(&amp;quot;&amp;quot;);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function stNewTrick() {&lt;br /&gt;
        // New trick: active the player who wins the last trick, or the player who own the club-2 card&lt;br /&gt;
        // Reset trick color to 0 (= no color)&lt;br /&gt;
        $this-&amp;gt;setGameStateInitialValue(&#039;trickColor&#039;, 0);&lt;br /&gt;
        $this-&amp;gt;gamestate-&amp;gt;nextState();&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function stNextPlayer() {&lt;br /&gt;
        // Active next player OR end the trick and go to the next trick OR end the hand&lt;br /&gt;
        if ($this-&amp;gt;cards-&amp;gt;countCardInLocation(&#039;cardsontable&#039;) == 4) {&lt;br /&gt;
            // This is the end of the trick&lt;br /&gt;
            // Move all cards to &amp;quot;cardswon&amp;quot; of the given player&lt;br /&gt;
            $best_value_player_id = $this-&amp;gt;activeNextPlayer(); // TODO figure out winner of trick&lt;br /&gt;
            $this-&amp;gt;cards-&amp;gt;moveAllCardsInLocation(&#039;cardsontable&#039;, &#039;cardswon&#039;, null, $best_value_player_id);&lt;br /&gt;
        &lt;br /&gt;
            if ($this-&amp;gt;cards-&amp;gt;countCardInLocation(&#039;hand&#039;) == 0) {&lt;br /&gt;
                // End of the hand&lt;br /&gt;
                $this-&amp;gt;gamestate-&amp;gt;nextState(&amp;quot;endHand&amp;quot;);&lt;br /&gt;
            } else {&lt;br /&gt;
                // End of the trick&lt;br /&gt;
                $this-&amp;gt;gamestate-&amp;gt;nextState(&amp;quot;nextTrick&amp;quot;);&lt;br /&gt;
            }&lt;br /&gt;
        } else {&lt;br /&gt;
            // Standard case (not the end of the trick)&lt;br /&gt;
            // =&amp;gt; just active the next player&lt;br /&gt;
            $player_id = $this-&amp;gt;activeNextPlayer();&lt;br /&gt;
            $this-&amp;gt;giveExtraTime($player_id);&lt;br /&gt;
            $this-&amp;gt;gamestate-&amp;gt;nextState(&#039;nextPlayer&#039;);&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function stEndHand() {&lt;br /&gt;
        $this-&amp;gt;gamestate-&amp;gt;nextState(&amp;quot;nextHand&amp;quot;);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Important: All state actions game or player must end with state transition (or thrown exception). Also make sure it&#039;s ONLY one state transition,&lt;br /&gt;
if you accidentally fall through after state transition and do another one it will be a real mess and head scratching for long time.&lt;br /&gt;
&lt;br /&gt;
Now find &#039;player actions&#039; section and paste this code there&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    function actPlayCard(int $card_id) {&lt;br /&gt;
        $player_id = $this-&amp;gt;getActivePlayerId();&lt;br /&gt;
        throw new BgaUserException($this-&amp;gt;_(&amp;quot;Not implemented: &amp;quot;) . &amp;quot;$player_id plays $card_id&amp;quot;);&lt;br /&gt;
    }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
We won&#039;t implement it yet but throw an exception which we will see if interaction is working properly&lt;br /&gt;
&lt;br /&gt;
Now the game should start but it would not be any different than before because we have to implement actual interactions.&lt;br /&gt;
It&#039;s good to check if it&#039;s still working though (and if it was running before you have to exit because we changed state machine and normally it will break stuff).  NOTE: When you play a card, you will not yet get the &amp;quot;Not implemented&amp;quot; message.  That is added in the next section.&lt;br /&gt;
&lt;br /&gt;
== Client - Server interactions ==&lt;br /&gt;
&lt;br /&gt;
Now to implement things for real we have hook UI actions to ajax calls, and process notifications sent by the server.&lt;br /&gt;
So previously we hooked playCardOnTable right into js handler which caused client animation, in real game its a two&lt;br /&gt;
step operation. When user clicks on game element js client sends an ajax call to server, server processes it and updates database, server sends&lt;br /&gt;
notification in response, client hooks animations to server notification.&lt;br /&gt;
&lt;br /&gt;
So in .js code replace onPlayerHandSelectionChanged with&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        onPlayerHandSelectionChanged : function() {&lt;br /&gt;
            var items = this.playerHand.getSelectedItems();&lt;br /&gt;
&lt;br /&gt;
            if (items.length &amp;gt; 0) {&lt;br /&gt;
                var action = &#039;actPlayCard&#039;;&lt;br /&gt;
                if (this.checkAction(action, true)) {&lt;br /&gt;
                    // Can play a card&lt;br /&gt;
                    var card_id = items[0].id;                    &lt;br /&gt;
                    this.bgaPerformAction(action, {&lt;br /&gt;
                        card_id : card_id,&lt;br /&gt;
                    });&lt;br /&gt;
&lt;br /&gt;
                    this.playerHand.unselectAll();&lt;br /&gt;
                } else if (this.checkAction(&#039;actGiveCards&#039;)) {&lt;br /&gt;
                    // Can give cards =&amp;gt; let the player select some cards&lt;br /&gt;
                } else {&lt;br /&gt;
                    this.playerHand.unselectAll();&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        },&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Now when you click on card you should get a server response: Not implemented...&lt;br /&gt;
&lt;br /&gt;
Lets implement it, in .game.php&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    function actPlayCard(int $card_id) {&lt;br /&gt;
        $player_id = $this-&amp;gt;getActivePlayerId();&lt;br /&gt;
        $this-&amp;gt;cards-&amp;gt;moveCard($card_id, &#039;cardsontable&#039;, $player_id);&lt;br /&gt;
        // XXX check rules here&lt;br /&gt;
        $currentCard = $this-&amp;gt;cards-&amp;gt;getCard($card_id);&lt;br /&gt;
        // And notify&lt;br /&gt;
        $this-&amp;gt;notifyAllPlayers(&#039;playCard&#039;, clienttranslate(&#039;${player_name} plays ${value_displayed} ${color_displayed}&#039;), array (&lt;br /&gt;
                &#039;i18n&#039; =&amp;gt; array (&#039;color_displayed&#039;,&#039;value_displayed&#039; ),&#039;card_id&#039; =&amp;gt; $card_id,&#039;player_id&#039; =&amp;gt; $player_id,&lt;br /&gt;
                &#039;player_name&#039; =&amp;gt; $this-&amp;gt;getActivePlayerName(),&#039;value&#039; =&amp;gt; $currentCard [&#039;type_arg&#039;],&lt;br /&gt;
                &#039;value_displayed&#039; =&amp;gt; $this-&amp;gt;values_label [$currentCard [&#039;type_arg&#039;]],&#039;color&#039; =&amp;gt; $currentCard [&#039;type&#039;],&lt;br /&gt;
                &#039;color_displayed&#039; =&amp;gt; $this-&amp;gt;colors [$currentCard [&#039;type&#039;]] [&#039;name&#039;] ));&lt;br /&gt;
        // Next player&lt;br /&gt;
        $this-&amp;gt;gamestate-&amp;gt;nextState(&#039;playCard&#039;);&lt;br /&gt;
    }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We get the card from client, we move it to the table (moveCard is hooked to database directly, its part of deck class),&lt;br /&gt;
we notify all players and we change state. What we are missing here is bunch of checks (rule enforcements), we will add it later.&lt;br /&gt;
&lt;br /&gt;
Interesting part about this notify is that we use i18n array for strings that needs to be translated by client, so&lt;br /&gt;
they are sent as English text in notification, then client has to know which parameters needs translating.&lt;br /&gt;
&lt;br /&gt;
On the client side .js we have to implement a notification handler to do the animation&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        setupNotifications : function() {&lt;br /&gt;
            console.log(&#039;notifications subscriptions setup&#039;);&lt;br /&gt;
&lt;br /&gt;
            const notifs = [&lt;br /&gt;
                [&#039;newHand&#039;, 1],&lt;br /&gt;
                [&#039;playCard&#039;, 100],&lt;br /&gt;
            ];&lt;br /&gt;
    &lt;br /&gt;
            notifs.forEach((notif) =&amp;gt; {&lt;br /&gt;
                dojo.subscribe(notif[0], this, `notif_${notif[0]}`);&lt;br /&gt;
                this.notifqueue.setSynchronous(notif[0], notif[1]);&lt;br /&gt;
            });&lt;br /&gt;
&lt;br /&gt;
        },&lt;br /&gt;
&lt;br /&gt;
        notif_newHand : function(notif) {&lt;br /&gt;
            // We received a new full hand of 13 cards.&lt;br /&gt;
            this.playerHand.removeAll();&lt;br /&gt;
&lt;br /&gt;
            for ( var i in notif.args.cards) {&lt;br /&gt;
                var card = notif.args.cards[i];&lt;br /&gt;
                var color = card.type;&lt;br /&gt;
                var value = card.type_arg;&lt;br /&gt;
                this.playerHand.addToStockWithId(this.getCardUniqueId(color, value), card.id);&lt;br /&gt;
            }&lt;br /&gt;
        },&lt;br /&gt;
&lt;br /&gt;
        notif_playCard : function(notif) {&lt;br /&gt;
            // Play a card on the table&lt;br /&gt;
            this.playCardOnTable(notif.args.player_id, notif.args.color, notif.args.value, notif.args.card_id);&lt;br /&gt;
        },&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Now it actually works through the server when you click on card - the move is recorded. If you test it now you will notice&lt;br /&gt;
after trick is done all cards remains on the table, but if you press F5 they would disappear, this is because&lt;br /&gt;
we updated database to pick-up the cards but did not send notification about it, so we need to send notification about it&lt;br /&gt;
and have a handler for it&lt;br /&gt;
&lt;br /&gt;
So in .game.php file add notification in stNextPlayer function after moveAllCardsInLocation call:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
            // Notify&lt;br /&gt;
            // Note: we use 2 notifications here in order we can pause the display during the first notification&lt;br /&gt;
            //  before we move all cards to the winner (during the second)&lt;br /&gt;
            $players = $this-&amp;gt;loadPlayersBasicInfos();&lt;br /&gt;
            $this-&amp;gt;notifyAllPlayers( &#039;trickWin&#039;, clienttranslate(&#039;${player_name} wins the trick&#039;), array(&lt;br /&gt;
                &#039;player_id&#039; =&amp;gt; $best_value_player_id,&lt;br /&gt;
                &#039;player_name&#039; =&amp;gt; $players[ $best_value_player_id ][&#039;player_name&#039;]&lt;br /&gt;
            ) );            &lt;br /&gt;
            $this-&amp;gt;notifyAllPlayers( &#039;giveAllCardsToPlayer&#039;,&#039;&#039;, array(&lt;br /&gt;
                &#039;player_id&#039; =&amp;gt; $best_value_player_id&lt;br /&gt;
            ) );&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
And in .js file add 2 more notification handlers.&lt;br /&gt;
&lt;br /&gt;
This is to subscribe in setupNotifications function&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
            const notifs = [&lt;br /&gt;
                ...&lt;br /&gt;
                [&#039;trickWin&#039;, 1000],&lt;br /&gt;
                [&#039;giveAllCardsToPlayer&#039;, 600],&lt;br /&gt;
            ];&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
And these are handlers&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        notif_trickWin : function(notif) {&lt;br /&gt;
            // We do nothing here (just wait in order players can view the 4 cards played before they&#039;re gone.&lt;br /&gt;
        },&lt;br /&gt;
        notif_giveAllCardsToPlayer : function(notif) {&lt;br /&gt;
            // Move all cards on table to given table, then destroy them&lt;br /&gt;
            var winner_id = notif.args.player_id;&lt;br /&gt;
            for ( var player_id in this.gamedatas.players) {&lt;br /&gt;
                var anim = this.slideToObject(&#039;cardontable_&#039; + player_id, &#039;overall_player_board_&#039; + winner_id);&lt;br /&gt;
                dojo.connect(anim, &#039;onEnd&#039;, function(node) {&lt;br /&gt;
                    dojo.destroy(node);&lt;br /&gt;
                });&lt;br /&gt;
                anim.play();&lt;br /&gt;
            }&lt;br /&gt;
        },&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
So &#039;trickWin&#039; notification does not do much except it will delay the processing of next notification by 1 second (1000 ms)&lt;br /&gt;
and it will log the message (that happens independently of what handler does).&lt;br /&gt;
&amp;lt;i&amp;gt;Note: if on the other hand you don&#039;t want to log but want to do something else, send an empty message&amp;lt;/i&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Now after the trick you see all cards move towards the &amp;quot;player&#039;s stash&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
== Scoring and End of game handling ==&lt;br /&gt;
&lt;br /&gt;
Now we should calculate scoring and for that we need to actually track who wins the trick.&lt;br /&gt;
Trick is won by the player with highest card (no trump). We just need to remember what is trick suite.&lt;br /&gt;
For which we will use state variable &#039;trickColor&#039; which we already conveniently created.&lt;br /&gt;
&lt;br /&gt;
In .game.php file find the playCard function and add this before notify functions&lt;br /&gt;
        $currentTrickColor = $this-&amp;gt;getGameStateValue( &#039;trickColor&#039; ) ;&lt;br /&gt;
        if( $currentTrickColor == 0 )&lt;br /&gt;
            $this-&amp;gt;setGameStateValue( &#039;trickColor&#039;, $currentCard[&#039;type&#039;] );&lt;br /&gt;
&lt;br /&gt;
This will make sure we remember the first suit being played, now to use it modify the stNextPlayer function to fix our TODO comment&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    function stNextPlayer() {&lt;br /&gt;
        // Active next player OR end the trick and go to the next trick OR end the hand&lt;br /&gt;
        if ($this-&amp;gt;cards-&amp;gt;countCardInLocation(&#039;cardsontable&#039;) == 4) {&lt;br /&gt;
            // This is the end of the trick&lt;br /&gt;
            $cards_on_table = $this-&amp;gt;cards-&amp;gt;getCardsInLocation(&#039;cardsontable&#039;);&lt;br /&gt;
            $best_value = 0;&lt;br /&gt;
            $best_value_player_id = null;&lt;br /&gt;
            $currentTrickColor = $this-&amp;gt;getGameStateValue(&#039;trickColor&#039;);&lt;br /&gt;
            foreach ( $cards_on_table as $card ) {&lt;br /&gt;
                // Note: type = card color&lt;br /&gt;
                if ($card [&#039;type&#039;] == $currentTrickColor) {&lt;br /&gt;
                    if ($best_value_player_id === null || $card [&#039;type_arg&#039;] &amp;gt; $best_value) {&lt;br /&gt;
                        $best_value_player_id = $card [&#039;location_arg&#039;]; // Note: location_arg = player who played this card on table&lt;br /&gt;
                        $best_value = $card [&#039;type_arg&#039;]; // Note: type_arg = value of the card&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
            &lt;br /&gt;
            // Active this player =&amp;gt; he&#039;s the one who starts the next trick&lt;br /&gt;
            $this-&amp;gt;gamestate-&amp;gt;changeActivePlayer( $best_value_player_id );&lt;br /&gt;
            &lt;br /&gt;
            // Move all cards to &amp;quot;cardswon&amp;quot; of the given player&lt;br /&gt;
            $this-&amp;gt;cards-&amp;gt;moveAllCardsInLocation(&#039;cardsontable&#039;, &#039;cardswon&#039;, null, $best_value_player_id);&lt;br /&gt;
        &lt;br /&gt;
            // Notify&lt;br /&gt;
            // ... same code here as before&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The scoring rule in the studio example code is huge multi-page function, for this tutorial we will make simplier.&lt;br /&gt;
Lets score -1 point per heart and call it a day. And game will end when somebody goes -100 or below.&lt;br /&gt;
&lt;br /&gt;
As UI goes for scoring, the main thing to update is the scoring on the mini boards represented by stars, also&lt;br /&gt;
we want to show that in the log. &lt;br /&gt;
In addition scoring can be shown in [[Game_interface_logic:_yourgamename.js#Scoring_dialogs|Scoring Dialog]] using tableWindow notification, but it is a tutorial on its own and you can do it as homework (it is part of original heart game).&lt;br /&gt;
&lt;br /&gt;
In .js file we need to add one more subscription and notification handler:&lt;br /&gt;
             const notifs = [&lt;br /&gt;
                 ...&lt;br /&gt;
                 [&#039;newScores&#039;, 1],&lt;br /&gt;
             ];&lt;br /&gt;
in setupNotifications&lt;br /&gt;
&lt;br /&gt;
and &lt;br /&gt;
        notif_newScores : function(notif) {&lt;br /&gt;
            // Update players&#039; scores&lt;br /&gt;
            for ( var player_id in notif.args.newScores) {&lt;br /&gt;
                this.scoreCtrl[player_id].toValue(notif.args.newScores[player_id]);&lt;br /&gt;
            }&lt;br /&gt;
        },&lt;br /&gt;
somewhere after. this.scoreCtrl is pre-existing object that shows the scoring and this function will update score values per player from notification argument&lt;br /&gt;
&lt;br /&gt;
so in .game.php our stEndHand function will look like&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    function stEndHand() {&lt;br /&gt;
            // Count and score points, then end the game or go to the next hand.&lt;br /&gt;
        $players = $this-&amp;gt;loadPlayersBasicInfos();&lt;br /&gt;
        // Gets all &amp;quot;hearts&amp;quot; + queen of spades&lt;br /&gt;
&lt;br /&gt;
        $player_to_points = array ();&lt;br /&gt;
        foreach ( $players as $player_id =&amp;gt; $player ) {&lt;br /&gt;
            $player_to_points [$player_id] = 0;&lt;br /&gt;
        }&lt;br /&gt;
        $cards = $this-&amp;gt;cards-&amp;gt;getCardsInLocation(&amp;quot;cardswon&amp;quot;);&lt;br /&gt;
        foreach ( $cards as $card ) {&lt;br /&gt;
            $player_id = $card [&#039;location_arg&#039;];&lt;br /&gt;
            // Note: 2 = heart&lt;br /&gt;
            if ($card [&#039;type&#039;] == 2) {&lt;br /&gt;
                $player_to_points [$player_id] ++;&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
        // Apply scores to player&lt;br /&gt;
        foreach ( $player_to_points as $player_id =&amp;gt; $points ) {&lt;br /&gt;
            if ($points != 0) {&lt;br /&gt;
                $sql = &amp;quot;UPDATE player SET player_score=player_score-$points  WHERE player_id=&#039;$player_id&#039;&amp;quot;;&lt;br /&gt;
                $this-&amp;gt;DbQuery($sql);&lt;br /&gt;
                $heart_number = $player_to_points [$player_id];&lt;br /&gt;
                $this-&amp;gt;notifyAllPlayers(&amp;quot;points&amp;quot;, clienttranslate(&#039;${player_name} gets ${nbr} hearts and looses ${nbr} points&#039;), array (&lt;br /&gt;
                        &#039;player_id&#039; =&amp;gt; $player_id,&#039;player_name&#039; =&amp;gt; $players [$player_id] [&#039;player_name&#039;],&lt;br /&gt;
                        &#039;nbr&#039; =&amp;gt; $heart_number ));&lt;br /&gt;
            } else {&lt;br /&gt;
                // No point lost (just notify)&lt;br /&gt;
                $this-&amp;gt;notifyAllPlayers(&amp;quot;points&amp;quot;, clienttranslate(&#039;${player_name} did not get any hearts&#039;), array (&lt;br /&gt;
                        &#039;player_id&#039; =&amp;gt; $player_id,&#039;player_name&#039; =&amp;gt; $players [$player_id] [&#039;player_name&#039;] ));&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
        $newScores = $this-&amp;gt;getCollectionFromDb(&amp;quot;SELECT player_id, player_score FROM player&amp;quot;, true );&lt;br /&gt;
        $this-&amp;gt;notifyAllPlayers( &amp;quot;newScores&amp;quot;, &#039;&#039;, array( &#039;newScores&#039; =&amp;gt; $newScores ) );&lt;br /&gt;
&lt;br /&gt;
        ///// Test if this is the end of the game&lt;br /&gt;
        foreach ( $newScores as $player_id =&amp;gt; $score ) {&lt;br /&gt;
            if ($score &amp;lt;= -100) {&lt;br /&gt;
                // Trigger the end of the game !&lt;br /&gt;
                $this-&amp;gt;gamestate-&amp;gt;nextState(&amp;quot;endGame&amp;quot;);&lt;br /&gt;
                return;&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        &lt;br /&gt;
        $this-&amp;gt;gamestate-&amp;gt;nextState(&amp;quot;nextHand&amp;quot;);&lt;br /&gt;
    }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
So it should more less work now, including end of game condition. Try to play it!&lt;br /&gt;
&lt;br /&gt;
== Additional stuff ==&lt;br /&gt;
&lt;br /&gt;
The following things were not implemented and can add them yourself by looking at the code of original hearts game:&lt;br /&gt;
&lt;br /&gt;
* Remove debug code from setupNewGame to deal cards, cards are now dealt in stNewHand state handler&lt;br /&gt;
* Rule checking and rule enforcements in playCard function&lt;br /&gt;
* Start scoring with 100 points each and end when &amp;lt;= 0&lt;br /&gt;
* Fix scoring rules with Q of spades and 26 point reverse scoring&lt;br /&gt;
* First player one with 2 club&lt;br /&gt;
* Add progress handling&lt;br /&gt;
* Add statistics&lt;br /&gt;
* Add card exchange states&lt;br /&gt;
* Add game option to start with 75 points instead of 100&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Category:Studio]]&lt;/div&gt;</summary>
		<author><name>Sguzzer Gunayer</name></author>
	</entry>
	<entry>
		<id>https://en.doc.boardgamearena.com/index.php?title=Game_interface_logic:_Game.js&amp;diff=22740</id>
		<title>Game interface logic: Game.js</title>
		<link rel="alternate" type="text/html" href="https://en.doc.boardgamearena.com/index.php?title=Game_interface_logic:_Game.js&amp;diff=22740"/>
		<updated>2024-09-25T18:27:22Z</updated>

		<summary type="html">&lt;p&gt;Sguzzer Gunayer: /* Counters */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Studio_Framework_Navigation}}&lt;br /&gt;
&lt;br /&gt;
__TOC__&lt;br /&gt;
&lt;br /&gt;
This is the main file for your game interface. Here you will define:&lt;br /&gt;
&lt;br /&gt;
* Which actions on the page will generate calls to the server.&lt;br /&gt;
* What happens when you get a notification for a change from the server and how it will show in the browser. &lt;br /&gt;
* Setup user interface&lt;br /&gt;
&lt;br /&gt;
== File structure ==&lt;br /&gt;
&lt;br /&gt;
The details of how the file is structured are described below with comments in the code skeleton provided to you.&lt;br /&gt;
&lt;br /&gt;
Here is the basic structure:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;constructor&#039;&#039;&#039;: here you can define global variables for your whole interface.&lt;br /&gt;
* &#039;&#039;&#039;setup&#039;&#039;&#039;: this method is called when the page is refreshed, and sets up the game interface.&lt;br /&gt;
* &#039;&#039;&#039;onEnteringState&#039;&#039;&#039;: this method is called when entering a new game state. You can use it to customize the view for each game state.&lt;br /&gt;
* &#039;&#039;&#039;onLeavingState&#039;&#039;&#039;: this method is called when leaving a game state.&lt;br /&gt;
* &#039;&#039;&#039;onUpdateActionButtons&#039;&#039;&#039;: called on state changes, in order to add action buttons to the status bar. Note: in a multipleactiveplayer state, it will be called when another player has become inactive.&lt;br /&gt;
* &#039;&#039;(utility methods)&#039;&#039;: this is where you can define your utility methods.&lt;br /&gt;
* &#039;&#039;(player&#039;s actions)&#039;&#039;: this is where you can write your handlers for player actions on the interface (example: click on an item).&lt;br /&gt;
* &#039;&#039;&#039;setupNotifications&#039;&#039;&#039;: this method associates notifications with notification handlers. For each game notification, you can trigger a javascript method to handle it and update the game interface.&lt;br /&gt;
* &#039;&#039;(notification handlers)&#039;&#039;: this is where you define the notifications handlers associated with notifications in &#039;&#039;&#039;setupNotifications&#039;&#039;&#039;, above.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
More details:&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;setup(gamedatas: object)            &#039;&#039;&#039;&lt;br /&gt;
This method must set up the game user interface according to current game situation specified in parameters.&lt;br /&gt;
The method is called each time the game interface is displayed to a player, ie:&lt;br /&gt;
&lt;br /&gt;
* when the game starts&lt;br /&gt;
* when a player opens a game in the browser later &lt;br /&gt;
* when a player refreshes the game page (F5)&lt;br /&gt;
* when player does a server side Undo&lt;br /&gt;
&lt;br /&gt;
&amp;quot;gamedatas&amp;quot; argument contains all data retrieved by your &amp;quot;getAllDatas&amp;quot; PHP method and some more.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;onEnteringState(stateName: string, args: { args: any } | null): void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
This method is called each time we enter a new game state.&lt;br /&gt;
You can use this method to perform some user interface changes at this moment.&lt;br /&gt;
To access state arguments passed via calling php arg* method use args?.args.&lt;br /&gt;
Typically you would do something only for active player, using this.isCurrentPlayerActive() check.&lt;br /&gt;
It is also called (for the current game state only) when doing a browser refresh (after the setup method is called).&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Warning&#039;&#039;&#039;: for multipleactiveplayer states:&lt;br /&gt;
the active players are NOT active yet so you must use onUpdateActionButtons to perform the client side operation which depends on a player active/inactive status.&lt;br /&gt;
If you are doing initialization of some structures which do not depend on the active player, you can just replace (this.isCurrentPlayerActive()) with (!this.isSpectator) &lt;br /&gt;
for the main switch in that method.&lt;br /&gt;
&lt;br /&gt;
See more details in [[Your_game_state_machine:_states.inc.php#Difference_between_Single_active_and_Multi_active_states]]&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;onLeavingState(stateName: string): void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
This method is called each time we leave a game state.&lt;br /&gt;
You can use this method to perform some user interface changes at this point (i.e. cleanup).&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;onUpdateActionButtons(stateName: string, args: object | null): void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
In this method you can manage &amp;quot;action buttons&amp;quot; that are displayed in the action status bar and highlight active UI elements.&lt;br /&gt;
To access state arguments passed via calling php arg* method use &#039;&#039;&#039;args&#039;&#039;&#039; parameter. Note: args can be null! For &#039;&#039;&#039;game&#039;&#039;&#039; states and when you don&#039;t supply state args function - it is null.&lt;br /&gt;
This method is called when the active or multiactive player changes. In a classic &amp;quot;activePlayer&amp;quot; state this method is called before the onEnteringState state.&lt;br /&gt;
In multipleactiveplayer state it is a mess. The sequencing of calls depends on whether you get into that state from transitions OR from reloading the whole game (i.e. F5).&lt;br /&gt;
&lt;br /&gt;
See more details in [[Your_game_state_machine:_states.inc.php#Difference_between_Single_active_and_Multi_active_states]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Dojo framework ==&lt;br /&gt;
&lt;br /&gt;
BGA uses the [http://dojotoolkit.org/ Dojo Javascript framework].&lt;br /&gt;
&lt;br /&gt;
The Dojo framework allows us to do complex things more easily. The BGA framework uses Dojo extensively.&lt;br /&gt;
&lt;br /&gt;
To implement a game, you only need to use a few parts of the Dojo framework. All the Dojo methods you need are described on this page.&lt;br /&gt;
&lt;br /&gt;
== Javascript minimization (after July 2020) ==&lt;br /&gt;
&lt;br /&gt;
For performance reasons, when deploying a game the javascript code is minimized using &#039;&#039;&#039;terser&#039;&#039;&#039; (https://github.com/terser/terser). This minifier works with modern javascript syntax. From your project &amp;quot;Manage game&amp;quot; page, you can now test a minified version of your javascript on the studio (and revert to the original).&lt;br /&gt;
&lt;br /&gt;
NB: it has been reported that there is an issue with this minifier and percentage values for opacity.&lt;br /&gt;
&lt;br /&gt;
== Accessing Players Information ==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.player_id: number&#039;&#039;&#039;&lt;br /&gt;
id of the player who is looking at the game. The player may not be part of the game (i.e. spectator)&lt;br /&gt;
  if (notif.args.player_id == this.player_id) {&lt;br /&gt;
    ...&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.isSpectator: boolean&#039;&#039;&#039;&lt;br /&gt;
Flag set to true if the user at the table is a spectator (not a player).&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    if (this.isSpectator) {&lt;br /&gt;
        this.player_color = &#039;ffffff&#039;;&lt;br /&gt;
    } else {&lt;br /&gt;
        this.player_color = gamedatas.players[this.player_id].color;&lt;br /&gt;
    }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note: If you want to hide an element from spectators, you should use [[Game_interface_stylesheet:_yourgamename.css#spectatorMode|CSS &#039;spectatorMode&#039; class]].&lt;br /&gt;
&lt;br /&gt;
You may consider making a function like this, to detect if the game is in a read-only state (i.e. non-interactive):&lt;br /&gt;
  // Returns true for spectators, instant replay (during game), archive mode (after game end)&lt;br /&gt;
  isReadOnly: function () {&lt;br /&gt;
    return this.isSpectator || typeof g_replayFrom != &#039;undefined&#039; || g_archive_mode;&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.gamedatas: object&#039;&#039;&#039;&lt;br /&gt;
Contains the initial set of data to init the game, created at game start or by game refresh (F5).&lt;br /&gt;
You can update it as needed to keep an up-to-date reference of the game on the client side if you need it, however most of the time this is unnecessary.&lt;br /&gt;
&lt;br /&gt;
Note: In hotseat mode, the framework does not keep this.gamedatas of hotseat players and shares the same set as the main player to store data.&lt;br /&gt;
&lt;br /&gt;
Note: be careful when you update this data structurally, many framework functions expect data to be certain way and they will break if they see something else.&lt;br /&gt;
&lt;br /&gt;
Typical example of accessing player&#039;s info&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
for (var player_id in this.gamedatas.players) { &lt;br /&gt;
    var playerInfo = this.gamedatas.players [player_id];&lt;br /&gt;
    var c = playerInfo.color;&lt;br /&gt;
    var name = playerInfo.name;&lt;br /&gt;
    // do something &lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.isCurrentPlayerActive(): boolean&#039;&#039;&#039;&lt;br /&gt;
Returns true if the player on whose browser the code is running is currently active (it&#039;s his turn to play). Note: see remarks above about usage of this function inside onEnteringState method.&lt;br /&gt;
  if (this.isCurrentPlayerActive()) ...&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.getActivePlayerId(): number&#039;&#039;&#039;&lt;br /&gt;
Return the ID of the active player, or null if we are not in an &amp;quot;activeplayer&amp;quot; type state.&lt;br /&gt;
  if (this.player_id == this.getActivePlayerId()) ...&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.getActivePlayers(): number[]&#039;&#039;&#039;&lt;br /&gt;
Return an array with the IDs of players who are currently active (or an empty array if there are none).&lt;br /&gt;
&lt;br /&gt;
== Accessing and manipulating the DOM ==&lt;br /&gt;
&lt;br /&gt;
=== Element by Id ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;$(elementId: ElementOrId)&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
The $ function is used to get an HTML element using its &amp;quot;id&amp;quot; attribute.&lt;br /&gt;
&lt;br /&gt;
Example: modify the content of a &amp;quot;span&amp;quot; element:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
In your HTML code:&lt;br /&gt;
   &amp;lt;span id=&amp;quot;a_value_in_the_game_interface&amp;quot;&amp;gt;1234&amp;lt;/span&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In your Javascript code:&lt;br /&gt;
   $(&#039;a_value_in_the_game_interface&#039;).innerHTML = &amp;quot;9999&amp;quot;;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Note: It is safe to use if you don&#039;t know if variable is string (id of element) or element itself, i.e. &lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  foo: function(card) {&lt;br /&gt;
       card = $(card); // now its node, no need to write if (typeof card === &#039;string&#039;) ...&lt;br /&gt;
       // but its good idea to check for null here&lt;br /&gt;
       ...&lt;br /&gt;
  }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;getElementById(elementId: string)&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Note: $() is the standard method to access some HTML element with the BGA Framework. You can use &#039;&#039;&#039;getElementById&#039;&#039;&#039; but it is longer to type and less handy as it does not do some checks.&lt;br /&gt;
&lt;br /&gt;
=== Style ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;dojo.style(node: ElementOrId, styleName: string, styleValue: any): void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
With dojo.style you can modify the CSS property of any HTML element in your interface.&lt;br /&gt;
&lt;br /&gt;
Examples:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
     // Make an element disappear&lt;br /&gt;
     dojo.style( &#039;my_element&#039;, &#039;display&#039;, &#039;none&#039; );&lt;br /&gt;
&lt;br /&gt;
     // Give an element a 2px border&lt;br /&gt;
     dojo.style( &#039;my_element&#039;, &#039;borderWidth&#039;, &#039;2px&#039; );&lt;br /&gt;
&lt;br /&gt;
     // Change the background position of an element&lt;br /&gt;
     // (very practical when you are using CSS sprites to transform an element to another)&lt;br /&gt;
     dojo.style( &#039;my_element&#039;, &#039;backgroundPosition&#039;, &#039;-20px -50px&#039; );&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note: if you have to modify several CSS properties of an element, or if you have a complex CSS transformation to do, you should consider using dojo.addClass/dojo.removeClass (see below).&lt;br /&gt;
&lt;br /&gt;
You can also use object to set multiple values&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
dojo.setStyle(&amp;quot;thinger&amp;quot;, {&lt;br /&gt;
  &amp;quot;opacity&amp;quot;: 0.5,&lt;br /&gt;
  &amp;quot;border&amp;quot;: &amp;quot;3px solid black&amp;quot;,&lt;br /&gt;
  &amp;quot;height&amp;quot;: &amp;quot;300px&amp;quot;&lt;br /&gt;
});&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.addStyleToClass(cssClassName: string, styleName: string, styleValue: any):&#039;&#039;&#039; &#039;&#039;&#039;void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Same as dojo.style(), but for all the nodes set with the specified cssClassName&lt;br /&gt;
Equivalent of &lt;br /&gt;
  &lt;br /&gt;
  dojo.query(`.${aclass}`).style(styleName, styleValue)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
dojo.query(&amp;quot;#baz &amp;gt; div&amp;quot;).style({&lt;br /&gt;
  opacity:0.75,&lt;br /&gt;
  fontSize:&amp;quot;13pt&amp;quot;&lt;br /&gt;
});&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Vanilla JS style&#039;&#039;&#039;&lt;br /&gt;
  $(&#039;my_element&#039;).style.display=&#039;none&#039;; // set&lt;br /&gt;
  var display = $(&#039;my_element&#039;).style.display; // get&lt;br /&gt;
  $(&#039;my_element&#039;).style.removeProperty(&#039;display&#039;); // remove&lt;br /&gt;
&lt;br /&gt;
=== Classes ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;dojo.addClass(node: ElementOrId, classes: string): void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;dojo.removeClass(node: ElementOrId, classes: string): void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;dojo.hasClass(node: ElementOrId, aclass: string): void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;dojo.toggleClass(node: ElementOrId, aclass: string): void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
In many situations, many small CSS property updates can be replaced by a CSS class change (i.e., you add a CSS class to your element instead of applying all modifications manually).&lt;br /&gt;
&lt;br /&gt;
Advantages are:&lt;br /&gt;
* All your CSS stuff remains in your CSS file.&lt;br /&gt;
* You can add/remove a list of CSS modifications with a simple function and without error.&lt;br /&gt;
* You can test whether you applied the CSS to an element with the &#039;&#039;&#039;dojo.hasClass&#039;&#039;&#039; method.&lt;br /&gt;
&lt;br /&gt;
Example from &#039;&#039;Reversi&#039;&#039;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    // We add &amp;quot;possibleMove&amp;quot; to an element&lt;br /&gt;
    dojo.addClass( &#039;square_&#039;+x+&#039;_&#039;+y, &#039;possibleMove&#039; );&lt;br /&gt;
&lt;br /&gt;
    // In our CSS file, the class is defined as:&lt;br /&gt;
    .possibleMove {&lt;br /&gt;
      background-color: white;&lt;br /&gt;
      opacity: 0.2;&lt;br /&gt;
      filter:alpha(opacity=20); /* For IE8 and earlier */  &lt;br /&gt;
      cursor: pointer;  &lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
     // So we&#039;ve applied 4 CSS property changes in one line of code.&lt;br /&gt;
&lt;br /&gt;
     // ... and when we need to check if a square is a possible move on the client side:&lt;br /&gt;
     if( dojo.hasClass( &#039;square_&#039;+x+&#039;_&#039;+y, &#039;possibleMove&#039; ) )&lt;br /&gt;
     { ... }&lt;br /&gt;
&lt;br /&gt;
     // ... and if we want to remove all possible moves in one line of code (see &amp;quot;dojo.query&amp;quot; method):&lt;br /&gt;
     dojo.query( &#039;.possibleMove&#039; ).removeClass( &#039;possibleMove&#039; );&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Vanilla JS classList&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
This is the only exception where dojo versions are better&lt;br /&gt;
  // add class&lt;br /&gt;
  $(token_id).classList.addClass(&#039;possibleMove&#039;);&lt;br /&gt;
  // remove class&lt;br /&gt;
  $(token_id).classList.removeClass(&#039;possibleMove&#039;);&lt;br /&gt;
  // add 2 classes&lt;br /&gt;
  const myclasses = [&#039;a&#039;,&#039;b&#039;];&lt;br /&gt;
  $(token_id).classList.addClass(...myclasses);&lt;br /&gt;
  // add classes to query result&lt;br /&gt;
  document.querySelectorAll(&amp;quot;.hand .card&amp;quot;).forEach((node)=&amp;gt;node.classList.addClass(&#039;possibleMove&#039;));&lt;br /&gt;
&lt;br /&gt;
=== Attributes ===&lt;br /&gt;
&lt;br /&gt;
;dojo.attr&lt;br /&gt;
&lt;br /&gt;
With dojo.attr you can access or change the value of an attribute or property of any HTML element in your interface.&lt;br /&gt;
&lt;br /&gt;
Exemple:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
     // Get the title of a node&lt;br /&gt;
     var title = dojo.attr( id, &#039;title&#039; );&lt;br /&gt;
     // Change the height of a node&lt;br /&gt;
     dojo.attr( &#039;img_growing_tree&#039;, &#039;height&#039;, 100 );&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Vanilla JS attr&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
   $(token).id=new_id; // set attr for &amp;quot;id&amp;quot;&lt;br /&gt;
   var id = $(token).id; // get&lt;br /&gt;
&lt;br /&gt;
=== Queries ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;dojo.query(cssSelector: string): Element[]&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
With dojo.query, you can query a bunch of HTML elements with a single function, with a &amp;quot;CSS selector&amp;quot; style.&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
     // All elements with class &amp;quot;possibleMove&amp;quot;:&lt;br /&gt;
     var elements = dojo.query( &#039;.possibleMove&#039; );&lt;br /&gt;
&lt;br /&gt;
     // Count number of tokens (i.e., elements of class &amp;quot;token&amp;quot;) on the board (i.e., the element with id &amp;quot;board&amp;quot;):&lt;br /&gt;
     dojo.query( &#039;#board .token&#039; ).length;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
But what is really cool with dojo.query is that you can combine it with almost all methods above.&lt;br /&gt;
&lt;br /&gt;
Examples:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
     // Trigger a method when the mouse enter in any element with class &amp;quot;meeple&amp;quot;:&lt;br /&gt;
     dojo.query( &#039;.meeple&#039; ).connect( &#039;onmouseenter&#039;, this, &#039;myMethodToTrigger&#039; );&lt;br /&gt;
&lt;br /&gt;
     // Hide all meeples who are on the board&lt;br /&gt;
     dojo.query( &#039;#board .meeple&#039; ).style( &#039;display&#039;, &#039;none&#039; );&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Vanilla JS query&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
  var cards=document.querySelectorAll(&amp;quot;.hand .card&amp;quot;);// all cards in all hands&lt;br /&gt;
  var cards=$(&#039;hand&#039;).querySelectorAll(&amp;quot;.card&amp;quot;);// all cards in specific hand&lt;br /&gt;
  var card=document.querySelector(&amp;quot;.hand .card&amp;quot;);// first card or null if none (super handy)&lt;br /&gt;
&lt;br /&gt;
=== Creating and Destroying elements ===&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;dojo.empty(node: ElementOrId)&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Remove all children of the node element&lt;br /&gt;
   dojo.empty(&#039;my_hand&#039;);&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;dojo.destroy(node: ElementOrId)&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Remove the element&lt;br /&gt;
   dojo.destroy(&#039;my_token&#039;);&lt;br /&gt;
&lt;br /&gt;
   dojo.query(&amp;quot;.green&amp;quot;, mynode).forEach(dojo.destroy); // this remove all subnode of class green from mynode&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;dojo.create(tag: string, attributes?: obj, parent?: ElementOrId): Element&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Create element&lt;br /&gt;
&lt;br /&gt;
    dojo.create(&amp;quot;div&amp;quot;, { class: &amp;quot;yellow_arrow&amp;quot; }, parent); // this creates div with class yellow_array and places it in &amp;quot;parent&amp;quot;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.format_block(name: string, args: object): string&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
This bga function that takes global var from template file and substitute variables, typical use would be&lt;br /&gt;
&lt;br /&gt;
                var player = gamedatas.players[player_id];&lt;br /&gt;
                var div = this.format_block(&#039;jstpl_player_board&#039;, player ); // var jstpl_player_board = ... is defined in .tpl file &lt;br /&gt;
Note: result is trimmed&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.format_string(name: string, args: object): string&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
This bga function just substitute variables in a string, i.e.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
     var div = this.format_string(&#039;&amp;lt;div color=&amp;quot;${player_color}&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&#039;, {player_color: &#039;#ff0000&#039;} );&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Note: result is trimmed&lt;br /&gt;
&lt;br /&gt;
Note: this can be replaced by using backquoted string now: &lt;br /&gt;
     const player_color =  &#039;#ff0000&#039;;&lt;br /&gt;
&lt;br /&gt;
    const div = ``;&lt;br /&gt;
&#039;&#039;&#039;this.format_string_recursive&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
This bga function is similar to this.format_string but is capable of processing recursive argument structures and translations. It is used to format server notifications.&lt;br /&gt;
&lt;br /&gt;
TODO: find better place for these function docs&lt;br /&gt;
&lt;br /&gt;
=== Moving elements ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;dojo.place(node: string | Element, refNode: ElementOrId, pos?: string | number): Element&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
dojo.place is the best function to insert HTML code somewhere in your game interface without breaking something. It is much better to use than the &#039;&#039;&#039;innerHTML=&#039;&#039;&#039; method if you must insert HTML tags and not only values.&lt;br /&gt;
&lt;br /&gt;
node: can be a string or a DOM node. If it is a string starting with “&amp;lt;”, it is assumed to be an HTML fragment, which will be created. Otherwise it is assumed to be an id of a DOM node. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
     // Insert your HTML code as a child of a container element&lt;br /&gt;
     dojo.place( &amp;quot;&amp;lt;div class=&#039;foo&#039;&amp;gt;&amp;lt;/div&amp;gt;&amp;quot;, &amp;quot;your_container_element_id&amp;quot; );&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
pos: optional argument. Can be a number or one of the following strings: “before”, “after”, “replace”, “only”, “first”, or “last”. If omitted, “last” is assumed.&lt;br /&gt;
&lt;br /&gt;
* &amp;quot;replace&amp;quot;: replace the container element with my_node element&lt;br /&gt;
* &amp;quot;first&amp;quot;: places the node as a child of the reference node. The node is placed as the first child.&lt;br /&gt;
* &amp;quot;last&amp;quot; (default): places the node as a child of the reference node. The node is placed as the last child.&lt;br /&gt;
* &amp;quot;before&amp;quot;: places the node right before the reference node.&lt;br /&gt;
* &amp;quot;after&amp;quot;: places the node right after the reference node.&lt;br /&gt;
* &amp;quot;only&amp;quot;: replaces all children of the reference node with the node.&lt;br /&gt;
&lt;br /&gt;
this parameter can be a positive integer. In this case, the node will be placed as a child of the reference node with this number (counting from 0). If the number is more than number of children, the node will be appended to the reference node making it the last child. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
     // Replace all children of container with my_node &lt;br /&gt;
     dojo.place( $(&#039;my_node&#039;), &amp;quot;your_container_element_id&amp;quot;, &amp;quot;only&amp;quot; );&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
See also full doc on dojo.place: [https://dojotoolkit.org/reference-guide/1.7/dojo/place.html]&lt;br /&gt;
&lt;br /&gt;
Usually, when you want to insert some piece of HTML in your game interface, you should use &amp;quot;[[Game_layout:_view_and_template:_yourgamename.view.php_and_yourgamename_yourgamename.tpl#Javascript_templates|Javascript templates]]&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
But you can also relocate elements like that. Note: it won&#039;t animate if you do that.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.placeOnObject(mobile_obj: ElementOrId, target_obj: ElementOrId): void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
places mobile_obj on target_obj, set the absolute positions and centers the mobile_obj on target_obj,&lt;br /&gt;
effect is immediate&lt;br /&gt;
&lt;br /&gt;
This is not really an animation, but placeOnObject is frequently used before starting an animation.&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  // (We just created an object &amp;quot;my_new_token&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
  // Place the new token on current player board&lt;br /&gt;
  this.placeOnObject( &amp;quot;my_new_token&amp;quot;, &amp;quot;overall_player_board_&amp;quot;+this.player_id );&lt;br /&gt;
  &lt;br /&gt;
  // Then slide it to its position on the board&lt;br /&gt;
  this.slideToObject( &amp;quot;my_new_token&amp;quot;, &amp;quot;a_place_on_board&amp;quot; ).play();&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.placeOnObjectPos(mobile_obj: ElementOrId, target_obj: ElementOrId, target_x: number, target_y: number): void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
This method works exactly like placeOnObject, except than you can specify some (x,y) coordinates (in px). This way, the center of &amp;quot;mobile_obj&amp;quot; will be placed to the specified x,y position relatively to the center of &amp;quot;target_obj&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Note: the placement works differently from this.slideToObjectPos&#039;&#039;, since coordinates are calculated based on the center of objects.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.attachToNewParent(mobile_obj: ElementOrId, target_obj: ElementOrId): void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
With this method, you change the HTML parent of &amp;quot;mobile_obj&amp;quot; element without moving it. &lt;br /&gt;
&amp;quot;target_obj&amp;quot; is the new parent of this element. The beauty of &lt;br /&gt;
attachToNewParent is that the mobile_obj element DOES NOT MOVE during this process.&lt;br /&gt;
&lt;br /&gt;
What happens is that the method calculate a relative position of mobile_obj to make sure it does not move after the HTML parent changes.&lt;br /&gt;
&lt;br /&gt;
Why using this method?&lt;br /&gt;
&lt;br /&gt;
Changing the HTML parent of an element can be useful for the following reasons:&lt;br /&gt;
* When the HTML parent moves, all its child are moving with them. If some game elements is no more linked with a parent HTML object, you may want to attach it to another place.&lt;br /&gt;
* The z_order (vertical order of display) depends on the position in the DOM, so you may need to change the parent of some game elements when they are moving in your game area.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;CAREFUL&#039;&#039;&#039;: this function destroys original object and places a clone onto a new parent, this will break all references to this HTML element (ex: dojo.connect).&lt;br /&gt;
If you need version that does not destroy the object but the same otherwise see [[BGA_Studio_Cookbook#Attach_to_new_parent_without_destroying_the_object]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Animations ==&lt;br /&gt;
&lt;br /&gt;
===Dojo Animations===&lt;br /&gt;
&lt;br /&gt;
BGA animations is based on Dojo Animation ([http://dojotoolkit.org/documentation/tutorials/1.8/animation/ see tutorial here]).&lt;br /&gt;
&lt;br /&gt;
However, most of the time, you can just use methods below, which are built on top of Dojo Animation.&lt;br /&gt;
&lt;br /&gt;
Note: one interesting method from Dojo that could be useful from time to time is &amp;quot;Dojo.Animation&amp;quot;. It allows you to make any CSS property &amp;quot;slide&amp;quot; from one value to another.&lt;br /&gt;
&lt;br /&gt;
Note 2: the slideTo methods are not compatible with CSS transform (scale, zoom, rotate...). If possible, avoid using CSS transform on nodes that are being slided. Eventually, the only possible solution to make these 2 compatible is to disable all CSS transform properties, use slideToObjectPos/placeOnObjectPos, and then apply them again.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Sliding===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.slideToObject(mobile_obj: ElementOrId, target_obj: ElementOrId, duration?: number, delay?: number): Animation&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
You can use slideToObject to &amp;quot;slide&amp;quot; an element to a target position.&lt;br /&gt;
&lt;br /&gt;
Sliding element on the game area is the recommended and the most used way to animate your game interface. Using slides allow players to figure out what is happening on the game, as if they were playing with the real boardgame.&lt;br /&gt;
&lt;br /&gt;
The parameters are:&lt;br /&gt;
* mobile_obj: the ID of the object to move. This object must be &amp;quot;relative&amp;quot; or &amp;quot;absolute&amp;quot; positioned.&lt;br /&gt;
* target_obj: the ID of the target object. This object must be &amp;quot;relative&amp;quot; or &amp;quot;absolute&amp;quot; positioned. Note that it is not mandatory that mobile_obj and target_obj have the same size. If their size are different, the system slides the center of mobile_obj to the center of target_obj.&lt;br /&gt;
* duration: (optional) defines the duration in millisecond of the slide. The default is 500 milliseconds.&lt;br /&gt;
* delay: (optional). If you defines a delay, the slide will start only after this delay. This is particularly useful when you want to slide several object from the same position to the same position: you can give a 0ms delay to the first object, a 100ms delay to the second one, a 200ms delay to the third one, ... this way they won&#039;t be superposed during the slide.&lt;br /&gt;
&lt;br /&gt;
BE CAREFUL: The method returns an dojo.fx animation, so you can combine it with other animation if you want to. It means that you have to call the &amp;quot;play()&amp;quot; method, otherwise the animation WON&#039;T START.&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
   this.slideToObject( &amp;quot;some_token&amp;quot;, &amp;quot;some_place_on_board&amp;quot; ).play();&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.slideToObjectPos(mobile_obj: ElementOrId, target_obj: ElementOrId, target_x: number, target_y: number, duration?: number, delay?: number): Animation&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
This method does exactly the same as &amp;quot;slideToObject&amp;quot;, except than you can specify some (x,y) coordinates. This way, &amp;quot;mobile_obj&amp;quot; will slide to the specified x,y position relatively to &amp;quot;target_obj&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
Example: slide a token to some place on the board, 10 pixels from the top:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
   this.slideToObjectPos( &amp;quot;some_token&amp;quot;, &amp;quot;some_place_on_board&amp;quot;, 0, 10 ).play();&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.slideTemporaryObject(mobile_obj_html: string, parent: ElementOrId, from: ElementOrId, to: ElementOrId, duration?: number, delay?: number): Animation&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
This method is useful when you want to slide a temporary HTML object from one place to another. As this object does not exists before the animation and won&#039;t remain after, it could be complex to create this object (with dojo.place), to place it at its origin (with placeOnObject) to slide it (with slideToObject) and to make it disappear at the end.&lt;br /&gt;
&lt;br /&gt;
slideTemporaryObject does all of this for you:&lt;br /&gt;
* mobile_obj_html is a piece of HTML code that represent the object to slide.&lt;br /&gt;
* parent is the ID of an HTML element of your interface that will be the parent of this temporary HTML object.&lt;br /&gt;
* from is the ID of the origin of the slide.&lt;br /&gt;
* to is the ID of the target of the slide.&lt;br /&gt;
* duration/delay works exactly like in &amp;quot;slideToObject&amp;quot;&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
this.slideTemporaryObject( &#039;&amp;lt;div class=&amp;quot;token_icon&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&#039;, &#039;tokens&#039;, &#039;my_origin_div&#039;, &#039;my_target_div&#039; ).play();&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Destroy===&lt;br /&gt;
&#039;&#039;&#039;this.slideToObjectAndDestroy(mobile_obj: ElementOrId, target_obj: ElementOrId, duration?: number, delay?: number): void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
This method is a handy shortcut to slide an existing HTML object to some place then destroy it upon arrival. It can be used for example to move a victory token or a card from the board to the player panel to show that the player earns it, then destroy it when we don&#039;t need to keep it visible on the player panel.&lt;br /&gt;
&lt;br /&gt;
It works the same as this.slideToObject and takes the same arguments, but it starts the animation. &lt;br /&gt;
&lt;br /&gt;
CAREFUL: Make sure nothing is creating the same object at the same time the animation is running, because this will cause some random disappearing effects&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
this.slideToObjectAndDestroy( &amp;quot;some_token&amp;quot;, &amp;quot;some_place_on_board&amp;quot;, 1000, 0 );&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.fadeOutAndDestroy( node: string | Element, duration?: number, delay?: number):&#039;&#039;&#039; &#039;&#039;&#039;void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
This function fade out the target node, then destroy it. Its starts the animation.&lt;br /&gt;
* duration/delay works exactly like in &amp;quot;slideToObject&amp;quot;&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
   this.fadeOutAndDestroy( &amp;quot;a_card_that_must_disappear&amp;quot; );&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
CAREFUL: the HTML node still exists until during few milliseconds, until the fadeOut has been completed.&lt;br /&gt;
Make sure nothing is creating same object at the same time as animation is running, because you will be some random dissapearing effects&lt;br /&gt;
&lt;br /&gt;
===Rotating elements===&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
This example combines &amp;quot;Dojo.Animation&amp;quot; method and a CSS property transform that allow you to rotate the element.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
// node is Element we rotating&lt;br /&gt;
		    var animation = new dojo.Animation({&lt;br /&gt;
			    curve: [fromDegree, toDegree],&lt;br /&gt;
			    onAnimate: (v) =&amp;gt; {&lt;br /&gt;
				    node.style.transform = &#039;rotate(&#039; + v + &#039;deg)&#039;;&lt;br /&gt;
			    } &lt;br /&gt;
		    });&lt;br /&gt;
		    &lt;br /&gt;
		    animation.play();  &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
BGA has its own interface to rotate&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.rotateTo(node: string | Element, degree: number): void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
It starts the animation, and stored the rotation degree in the class, so next time you rotate object - it is additive.&lt;br /&gt;
There is no animation hooks in this one, if you need to change any parameters use dojo animation above.&lt;br /&gt;
&lt;br /&gt;
There is also &#039;&#039;&#039;rotateInstantTo&#039;&#039;&#039; with same signature which does not animate&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Animation Callbacks===&lt;br /&gt;
&lt;br /&gt;
If you wish to run some code only after an animation has completed you can do this by linking a callback method to &#039;onEnd&#039;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
var animation_id = this.slideToObject( mobile_obj, target_obj, 500 );&lt;br /&gt;
dojo.connect(animation_id, &#039;onEnd&#039;, () =&amp;gt; {&lt;br /&gt;
   // do something here&lt;br /&gt;
});&lt;br /&gt;
animation_id.play();&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If you wish to call a second animation after the first (rather than general code) then you can use a dojo animation chain (see tutorial referenced above).&lt;br /&gt;
&lt;br /&gt;
== Players input ==&lt;br /&gt;
&lt;br /&gt;
=== Connecting ===&lt;br /&gt;
&#039;&#039;&#039;dojo.connect(element: Element, event: string, context: object, method: eventHandler): any&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;dojo.connect(element: Element, event: string, handler: eventHandler): any&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Used to associate a player event with one of your notification methods.&lt;br /&gt;
&lt;br /&gt;
Example: associate a click on an element (&amp;quot;my_element&amp;quot;) with one of our methods (&amp;quot;onClickOnMyElement&amp;quot;):&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
      dojo.connect( $(&#039;my_element&#039;), &#039;onclick&#039;, this, &#039;onClickOnMyElement&#039; );&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Same idea but based on query (i.e. all element of &#039;pet&#039; class)&lt;br /&gt;
      dojo.query(&amp;quot;.pet&amp;quot;).connect(&#039;onclick&#039;, this, &#039;onPet&#039;);&lt;br /&gt;
&lt;br /&gt;
Note: if you need to disconnect the handler you have to store handler returned from this method, i.e.&lt;br /&gt;
   &lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    var handler = dojo.connect(...);&lt;br /&gt;
    ...&lt;br /&gt;
    dojo.disconnect(handler);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If you don&#039;t store the handler - you have to destroy the object to disconnect it&lt;br /&gt;
&lt;br /&gt;
Typical function that implements the input handler will look like this&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
onPet: function(event) {&lt;br /&gt;
    var id = event.currentTarget.id;&lt;br /&gt;
    console.log(&#039;onPet &#039; + id);&lt;br /&gt;
    dojo.stopEvent(event);&lt;br /&gt;
    if (this.gamedatas.gamestate.name == &#039;playerTurnPet&#039;) {&lt;br /&gt;
          this.bgaPerformAction(&#039;actPlayPet&#039;, {card: id});&lt;br /&gt;
    } else {&lt;br /&gt;
          this.showMoveUnauthorized();&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.connect(element: ElementOrId, event: string, method: eventHandler): void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Used to associate a player event with one of your notification methods.&lt;br /&gt;
&lt;br /&gt;
      this.connect( $(&#039;my_element&#039;), &#039;onclick&#039;, &#039;onClickOnMyElement&#039; );&lt;br /&gt;
&lt;br /&gt;
Or you can use an in-place handler&lt;br /&gt;
&lt;br /&gt;
      this.connect( $(&#039;my_element&#039;), &#039;onclick&#039;, (e) =&amp;gt; { console.log(&#039;boo&#039;); } );&lt;br /&gt;
&lt;br /&gt;
Note that this function stores the connection handler. That is the only real difference between &#039;&#039;&#039;this.connect&#039;&#039;&#039; and &#039;&#039;&#039;dojo.connect&#039;&#039;&#039;. If you plan to destroy the element you connected, you &#039;&#039;&#039;must&#039;&#039;&#039; call this.disconnect() to prevent memory leaks.&lt;br /&gt;
This function is mainly for permanent objects - if you just want to connect the temp object you should probably not use this method but use dojo.connect which won&#039;t require any clean-up.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.connectClass(cssClassName: string, event: string, method: eventHandler): void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Same as connect(), but for all the nodes set with the specified cssClassName.&lt;br /&gt;
 this.connectClass(&#039;pet&#039;, &#039;onclick&#039;, &#039;onPet&#039;);&lt;br /&gt;
&#039;&#039;&#039;this.disconnect(element: ElementOrId, event: string): void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Disconnect event handler (previously registered with this.connect or this.connectClass).&lt;br /&gt;
&lt;br /&gt;
   this.disconnect( $(&#039;my_element&#039;), &#039;onclick&#039;);&lt;br /&gt;
&lt;br /&gt;
Note: dynamic connect/disconnect is for advanced cases ONLY, you should always connect elements statically if possible, i.e. in setup() method.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.disconnectAll(): void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Disconnect all previously registed event handlers (registered via this.connect or this.connectClass)&lt;br /&gt;
&lt;br /&gt;
  this.disconnectAll();&lt;br /&gt;
&lt;br /&gt;
=== Actions ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.bgaPerformAction(action: string, args?: object, options: object = { lock: true, checkAction: true }): Promise&amp;lt;void&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Triggers an action on the backend. This is a combination of checkAction and ajaxcall, returning a Promise which resoves when ajaxcall ends.&lt;br /&gt;
&lt;br /&gt;
This method must be used to send a player input to the game server. &#039;&#039;&#039;It should not be triggered programmatically&#039;&#039;&#039;, especially not in loops, in callbacks, in notifications, or in onEnteringState/onUpdateActionButtons/onLeavingState, in order not to create race conditions or break replay game and tutorial features. It should be used only in reaction to a user action in the interface.&lt;br /&gt;
&lt;br /&gt;
* action: name of the action, as it is written in &amp;quot;possibleactions&amp;quot; of the current state.&lt;br /&gt;
* args: an object containing the call parameters to send to the action&lt;br /&gt;
* options: options to tweak the call with some defaults. Default is &amp;lt;code&amp;gt;{ lock: true, checkAction: true }&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Example of a standard call without args:&lt;br /&gt;
  this.bgaPerformAction(&#039;pass&#039;);&lt;br /&gt;
&lt;br /&gt;
Example of a standard call with action args:&lt;br /&gt;
  this.bgaPerformAction(&#039;actPlayCard&#039;, { id: this.selectedCardId });&lt;br /&gt;
&lt;br /&gt;
Example of a call without checking action (because player is inactive in a multiactive state):&lt;br /&gt;
&lt;br /&gt;
 this.bgaPerformAction(&#039;actChangeMind&#039;, {}, { checkAction: false });&lt;br /&gt;
&lt;br /&gt;
Example of a call without lock (because of a special action not directly related to the game flow):&lt;br /&gt;
&lt;br /&gt;
 this.bgaPerformAction(&#039;actSetAutoBid&#039;, { alwaysBidUntil: 500 }, { lock: false, checkAction: false });&lt;br /&gt;
&lt;br /&gt;
Example of call with reaction to exception:&lt;br /&gt;
  this.bgaPerformAction(&#039;actPlayCard&#039;, { id: this.selectedCardId }).catch(()=&amp;gt;{ this.selectedCardId = undefined; });&lt;br /&gt;
&lt;br /&gt;
Example of call with reaction to success:&lt;br /&gt;
  this.bgaPerformAction(&#039;actPlayCard&#039;, { id: this.selectedCardId }).then(()=&amp;gt;{ this.unselectAll(); });&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.ajaxcall(url, parameters, obj_callback, callback, callback_anycase?, ajax_method?: string)&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Note: bgaPerformAction is a simpler way to use ajax calls, ajaxcall stays in the doc for legacy reasons only and should not be used in new projects.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Same warning as &#039;&#039;&#039;this.bgaPerformAction&#039;&#039;&#039; about using on user action only.&lt;br /&gt;
&lt;br /&gt;
* url: the url of the action to perform. For a game, it must be: &amp;quot;/&amp;lt;mygame&amp;gt;/&amp;lt;mygame&amp;gt;/myAction.html&amp;quot;&lt;br /&gt;
* parameters: an array of parameter to send to the game server. &lt;br /&gt;
** Note that &amp;quot;lock: true&amp;quot; must always be specified in this list of parameters in order the interface can be locked during the server call. Cannot use lock: false - to not lock it has to be undefined.&lt;br /&gt;
** Note: Restricted parameter names (please don&#039;t use them):&lt;br /&gt;
*** &amp;quot;action&amp;quot;&lt;br /&gt;
*** &amp;quot;module&amp;quot;&lt;br /&gt;
*** &amp;quot;class&amp;quot;&lt;br /&gt;
* obj_callback: must be set to &amp;quot;this&amp;quot;.&lt;br /&gt;
* callback (non-optional but rarely used): a function to trigger when the server returns result and everything went fine (not used, as all data handling is done via notifications).&lt;br /&gt;
* callback_anycase: (optional) a function to trigger when the server returns ok OR error.  If no error this function is called with parameter value false. If an error occurred, the first parameter will be set to true, the second will contain the error message sent by the PHP back-end, and the third will contain an error code.&lt;br /&gt;
* ajax_method: (optional and rarely used) if you need to send large amounts of data (over 2048 bytes), you can set this parameter to &#039;post&#039; (all lower-case) to send a POST request as opposed to the default GET. This works, but was not officially documented, so only use if you really need to.&lt;br /&gt;
&lt;br /&gt;
Usage:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
this.ajaxcall( &#039;/mygame/mygame/actMyAction.html&#039;, { lock: true, &lt;br /&gt;
   arg1: myarg1, &lt;br /&gt;
   arg2: myarg2&lt;br /&gt;
}, this, (result)=&amp;gt;{} );&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.checkAction(action: string, nomessage?: boolean): boolean &#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Check if player can do the specified action by taking into account:&lt;br /&gt;
* if interface is locked it will return false and show message &amp;quot;An action is already in progress&amp;quot;,  unless nomessage set to true &lt;br /&gt;
* if player is not active it will return false and show message &amp;quot;This is not your turn&amp;quot;, unless nomessage set to true &lt;br /&gt;
* if action is not in list in possible actions (defined by &amp;quot;possibleaction&amp;quot; in current game state) it will return false and show &amp;quot;This move is not authorized now&amp;quot; error (unconditionally).&lt;br /&gt;
* otherwise returns true&lt;br /&gt;
Example:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  function onClickOnGameElement( evt )  {&lt;br /&gt;
     if( this.checkAction( &amp;quot;actMyAction&amp;quot; ) ) {&lt;br /&gt;
        // Do the action&lt;br /&gt;
     }&lt;br /&gt;
  }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.checkPossibleActions(action: string): boolean&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
* this is independent of the player being active, so can be used instead of this.checkAction(). This is particularly useful for multiplayer states when the player is not active in a &#039;player may like to change their mind&#039; scenario. Unlike this.checkAction, this function does NOT take interface locking into account &lt;br /&gt;
&lt;br /&gt;
* if action is not in list in possible actions (defined by &amp;quot;possibleaction&amp;quot; in current game state) it will return false and show &amp;quot;This move is not authorized now&amp;quot; error (unconditionally).&lt;br /&gt;
* otherwise returns true&lt;br /&gt;
&lt;br /&gt;
  function onChangeMyMind( evt )  {&lt;br /&gt;
     if( this.checkPossibleActions( &amp;quot;actMyAction&amp;quot; ) ) {&lt;br /&gt;
        // Do the action&lt;br /&gt;
     }&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.checkLock(nomessage?: boolean): boolean&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
When using &amp;quot;lock: true&amp;quot; in ajax call you can use this function to check if interface is in lock state (it will be locked during server call and notification processing).&lt;br /&gt;
This check can be used to block some other interactions which do not result in ajaxcall or if you want to suppress errors. Note: normally you only need to use this.checkAction(...), this is for advanced cases.&lt;br /&gt;
&lt;br /&gt;
It will also show error unless nomessage is set to true&lt;br /&gt;
&lt;br /&gt;
  function onChangeMyMind( evt )  {&lt;br /&gt;
     if( this.checkLock() ) {&lt;br /&gt;
        // Do the action&lt;br /&gt;
     }&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
== Notifications ==&lt;br /&gt;
&lt;br /&gt;
When something happens on the server side, your game interface Javascript logic received a notification.&lt;br /&gt;
If you have not done so yet check what notification are in [[Main_game_logic:_yourgamename.game.php#Notifications]]&lt;br /&gt;
&lt;br /&gt;
Here&#039;s how you can handle these notifications on the client side.&lt;br /&gt;
&lt;br /&gt;
=== Subscribe to notifications ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;dojo.subscribe(notif_type: string, callback_obj: Object, handler: string|handler)&#039;&#039;&#039;&lt;br /&gt;
* notif_type - notification type/name send by php server&lt;br /&gt;
* callback_obj - usually this&lt;br /&gt;
* handler - if string method of callback_obj with name name is called, when notification is called, with notification object as parameter (see below)&lt;br /&gt;
&lt;br /&gt;
Your Javascript &amp;quot;setupNotifications&amp;quot; method is the place where you can subscribe to notifications from your PHP code.&lt;br /&gt;
&lt;br /&gt;
Here&#039;s how you associate one of your Javascript method to a notification &amp;quot;playDisc&amp;quot; (from Reversi example):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
   setupNotifications: function() {&lt;br /&gt;
      ...&lt;br /&gt;
      dojo.subscribe(&#039;playDisc&#039;, this, &amp;quot;notif_playDisc&amp;quot;);&lt;br /&gt;
   },&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note: the &amp;quot;playDisc&amp;quot; corresponds to the name of the notification you define it in your PHP code, in your &amp;quot;notifyAllPlayers&amp;quot; or &amp;quot;notifyPlayer&amp;quot; method.&lt;br /&gt;
&lt;br /&gt;
Then, you have to define your &amp;quot;notif_playDisc&amp;quot; method:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
   notif_playDisc: function(notif) {&lt;br /&gt;
     // Remove current possible moves (makes the board more clear)&lt;br /&gt;
     dojo.query( &#039;.possibleMove&#039; ).removeClass( &#039;possibleMove&#039; );          &lt;br /&gt;
     this.addDiscOnBoard( notif.args.x, notif.args.y, notif.args.player_id );&lt;br /&gt;
   },&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In a notification handler like our &amp;quot;notif_playDisc&amp;quot; method, you can access all notifications arguments with &amp;quot;notif.args&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&lt;br /&gt;
PHP&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    $this-&amp;gt;notifyAllPlayers( &amp;quot;apples&amp;quot;, clienttranslate(&#039;player takes ${count} apples&#039;), [ &amp;quot;count&amp;quot; =&amp;gt; 3 ] );&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
JavaScript&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    setupNotifications: function() {&lt;br /&gt;
       dojo.subscribe( &#039;apples&#039;, this, &#039;notif_apples&#039; );&lt;br /&gt;
    },&lt;br /&gt;
&lt;br /&gt;
    notif_apples: function(notif) {&lt;br /&gt;
      //You can access the &amp;quot;count&amp;quot; like this:&lt;br /&gt;
       alert(&amp;quot;count = &amp;quot; + notif.args.count);&lt;br /&gt;
    }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== The notification Object received by client ===&lt;br /&gt;
&lt;br /&gt;
When sending a notification on your PHP, the client side will receive an Object with the following attributes:&lt;br /&gt;
&lt;br /&gt;
* type - type of the notification (as passed by php function)&lt;br /&gt;
* log - the log string passed from php notification&lt;br /&gt;
* args - This is the arguments that you passed on your notification method on php&lt;br /&gt;
* bIsTableMsg - is true when you use [[Main_game_logic:_yourgamename.game.php#NotifyAllPlayers|NotifyAllPlayers]] method (false otherwise)&lt;br /&gt;
* channelorig - information about table ID (formatted as : &amp;quot;/table/t[TABLE_NUMBER]&amp;quot;)&lt;br /&gt;
* gamenameorig - name of the game&lt;br /&gt;
* move_id - ID of the move associated with the notification&lt;br /&gt;
* table_id - ID of the table (comes as string)&lt;br /&gt;
* time - UNIX GMT timestamp&lt;br /&gt;
* uid - unique identifier of the notification&lt;br /&gt;
* h - unknown&lt;br /&gt;
&lt;br /&gt;
&#039;&#039; Note that those information were inferred from observation on console log. If an Admin can confirm/correct (and remove this line), you&#039;re welcome :)&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
=== Ignoring notifications ===&lt;br /&gt;
&lt;br /&gt;
Sometimes you need to ignore some notification on client side. You don&#039;t want them to be shown in game log and you don&#039;t want them to be handled.&lt;br /&gt;
&lt;br /&gt;
The most common use case is when a player gets private information. They will receive a specific notification (such as &amp;quot;You received Ace of Heart&amp;quot;), while other players would receive more generic notification (&amp;quot;Player received a card&amp;quot;).&lt;br /&gt;
&lt;br /&gt;
In X.game.php&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        $this-&amp;gt;notifyAllPlayers(&amp;quot;dealCard&amp;quot;, clienttranslate(&#039;${player_name} received a card&#039;), [&lt;br /&gt;
            &#039;player_id&#039; =&amp;gt; $playerId,&lt;br /&gt;
            &#039;player_name&#039; =&amp;gt; $this-&amp;gt;getActivePlayerName()&lt;br /&gt;
        ]);&lt;br /&gt;
&lt;br /&gt;
        $this-&amp;gt;notifyPlayer($playerId, &amp;quot;dealCardPrivate&amp;quot;, clienttranslate(&#039;You received ${cardName}&#039;), [&lt;br /&gt;
            &amp;quot;type&amp;quot; =&amp;gt; $card[&amp;quot;type&amp;quot;],&lt;br /&gt;
            &amp;quot;cardName&amp;quot; =&amp;gt; $this-&amp;gt;getCardName($card[&amp;quot;type&amp;quot;])&lt;br /&gt;
        ]);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The problem with this approach is that the active player will receive two notifications:&lt;br /&gt;
* Player1 received a card&lt;br /&gt;
* You received Ace of Hearts&lt;br /&gt;
&lt;br /&gt;
Hence, notification ignoring.&lt;br /&gt;
&lt;br /&gt;
NOTE: You can think that it would be possible to send such notification to all players except active just by using notifyPlayer and it seems to work. The problem however is that table spectators would miss such notification and their user interface (and game log) wouldn&#039;t be updated. Since there is no way to send notification just to spectators, ignoring the notification (or &amp;quot;filtering&amp;quot;) is the only reasonable solution.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;setIgnoreNotificationCheck(notif_type: string, predicate: ((notif: Notif)=&amp;gt;boolean))&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
This method will set a check whether any of notifications of specific type should be ignored.&lt;br /&gt;
&lt;br /&gt;
The parameters are:&lt;br /&gt;
* notif_type: type of the notification &lt;br /&gt;
* predicate (notif =&amp;gt; boolean): a function that will receive notif object and will return true if this specific notification should be ignored&lt;br /&gt;
&lt;br /&gt;
Before dispatching any notification of this type, the framework will call predicate to check whether notification should be ignored, if it return true - the notification will be dispatched, i.e. logged or handled.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    this.notifqueue.setIgnoreNotificationCheck( &#039;dealCard&#039;, (notif) =&amp;gt; (notif.args.player_id == this.player_id) );&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
IMPORTANT: Remember that this notification is ignored on the client side, but was still received by the client. Therefore it shouldn&#039;t contain any private information as cheaters can get it. In other words this is not a way to hide information.&lt;br /&gt;
&lt;br /&gt;
IMPORTANT: When a game is reloaded with F5 or when opening a turn based game, old notifications are replayed as history notification. They are used just to update the game log and are stripped of all arguments except player_id, i18n and any argument present in message. If you use and other argument in your predicate you should &#039;&#039;&#039;preserve&#039;&#039;&#039; it as explained [[Main_game_logic:_yourgamename.game.php#Notify_players|here]].&lt;br /&gt;
&lt;br /&gt;
=== Synchronous notifications ===&lt;br /&gt;
&lt;br /&gt;
When several notifications are received by your game interface, these notifications are processed immediately, one after the other, in the same exact order they have been generated in your PHP game logic.&lt;br /&gt;
&lt;br /&gt;
However, sometimes, you need to give some time to the players to figure out what happened on the game before jumping to the next notification. Indeed, in many games, there are a lot of automatic actions, and the computer is going to resolve all these actions very fast if you don&#039;t tell it not to do so.&lt;br /&gt;
&lt;br /&gt;
As an example, for Reversi, when someone is playing a disc, we want to wait 500 milliseconds before doing anything else in order the opponent player can figure out what move has been played.&lt;br /&gt;
&lt;br /&gt;
Here&#039;s how we do this, right after our subscription:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    dojo.subscribe( &#039;playDisc&#039;, this, &amp;quot;notif_playDisc&amp;quot; );&lt;br /&gt;
    this.notifqueue.setSynchronous( &#039;playDisc&#039;, 500 );   // Wait 500 milliseconds after executing the playDisc handler&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
-----&lt;br /&gt;
&lt;br /&gt;
It is also possible to control the delay timing dynamically (e.g., using notification args). As an example, maybe your notification &#039;cardPlayed&#039; should pause for a different amount of time depending on the number or type of cards played.&lt;br /&gt;
&lt;br /&gt;
For this case, use &#039;&#039;&#039;setSynchronous&#039;&#039;&#039; without specifying the duration and use &#039;&#039;&#039;setSynchronousDuration&#039;&#039;&#039; within the notification callback.&lt;br /&gt;
&lt;br /&gt;
* NOTE: If you forget to invoke &#039;&#039;&#039;setSynchronousDuration&#039;&#039;&#039;, the game will remain paused forever!&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
setupNotifications: function () {&lt;br /&gt;
    dojo.subscribe( &#039;cardPlayed&#039;, this, &#039;notif_cardPlayed&#039; );&lt;br /&gt;
    this.notifqueue.setSynchronous( &#039;cardPlayed&#039; ); // wait time is dynamic&lt;br /&gt;
    ...&lt;br /&gt;
},&lt;br /&gt;
&lt;br /&gt;
notif_cardPlayed: function (notif) {&lt;br /&gt;
    // MUST call setSynchronousDuration&lt;br /&gt;
&lt;br /&gt;
    // Example 1: From notification args (PHP)&lt;br /&gt;
    this.notifqueue.setSynchronousDuration(notif.args.duration);&lt;br /&gt;
    ...&lt;br /&gt;
&lt;br /&gt;
    // Or, example 2: Match the duration to a Dojo animation&lt;br /&gt;
    var anim = dojo.fx.combine([&lt;br /&gt;
        ...&lt;br /&gt;
    ]);&lt;br /&gt;
    anim.play();&lt;br /&gt;
    this.notifqueue.setSynchronousDuration(anim.duration);&lt;br /&gt;
},&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You can also manually call this.notifqueue.setSynchronousDuration(0) once client operations are finished, but be careful that even fast replay still has a path to call it.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;WARNING: combining synchronous and ignored notifications&#039;&#039;&#039;&lt;br /&gt;
You must be careful when combining dynamic synchronous durations (as described above) with ignored notifications. If you have a conditionally ignored notification like this (see below section):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;this.notifqueue.setIgnoreNotificationCheck( &#039;myNotif&#039;, (notif) =&amp;gt; (notif.args.player_id == this.player_id) /* or any other condition */ )&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
then you CANNOT do&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;this.notifqueue.setSynchronous(&#039;myNotif&#039;);&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
as, when the ignored check passes, the notification handler, in which `this.notifqueue.setSychronousDuration` is called, is never called and so the duration is never set and interface locking results.&lt;br /&gt;
&lt;br /&gt;
The workaround is to set a &amp;quot;dummy&amp;quot; time:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;this.notifqueue.setSynchronous(&#039;myNotif&#039;, 5000);&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
whose value is irrelevant but must be large enough to cover the time before the notification handler is called. The large value never actually comes into play because the notification is either ignored, or the synchronous duration is reset to a sensible value inside the handler.&lt;br /&gt;
&lt;br /&gt;
=== Pre-defined notification types ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;tableWindow&#039;&#039;&#039; - This defines notification to display [[Game_interface_logic:_yourgamename.js#Scoring_dialogs|Scoring Dialogs]], see below.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;message&#039;&#039;&#039; - This defines notification that shows on players log and have no other effect (technically any unhandled notification will do the same but its recommended to use this keyword for consistency)&lt;br /&gt;
&lt;br /&gt;
   // You can call this on php side without doing anything on client side&lt;br /&gt;
    self::notifyAllPlayers( &#039;message&#039;, clienttranslate(&#039;hello&#039;), [] );&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;simplePause&#039;&#039;&#039; - This notification will just delay other notifications, maybe useful if you know you need some extra time for animation or something. Requires a time parameter.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    self::notifyAllPlayers( &#039;simplePause&#039;, &#039;&#039;, [ &#039;time&#039; =&amp;gt; 500] ); // time is in milliseconds&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note: the following types are RESERVED by framework, do not use:&lt;br /&gt;
&lt;br /&gt;
gameStateChange gameStateChangePrivateArg gameStateMultipleActiveUpdate newActivePlayer playerstatus yourturnack clockalert tableInfosChanged playerEliminated tableDecision  archivewaitingdelay end_archivewaitingdelay replaywaitingdelay end_replaywaitingdelay replayinitialwaitingdelay end_replayinitialwaitingdelay aiPlayerWaitingDelay replay_has_ended updateSpectatorList  wouldlikethink updateReflexionTime undoRestorePoint resetInterfaceWithAllDatas zombieModeFail zombieModeFailWarning aiError skipTurnOfPlayer zombieBack allPlayersAreZombie gameResultNeutralized playerConcedeGame showTutorial showCursor showCursorClick skipTurnOfPlayerWarning  banFromTable resultsAvailable switchToTurnbased newPrivateState infomsg&lt;br /&gt;
&lt;br /&gt;
== Tooltips ==&lt;br /&gt;
&lt;br /&gt;
=== Adding static tooltips ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.addTooltip(nodeId: string, helpStringTranslated: string, actionStringTranslated: string, delay?: number): void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Add a simple text tooltip to the DOM node.&lt;br /&gt;
&lt;br /&gt;
Specify &#039;helpStringTranslated&#039; to display some information about &amp;quot;what is this game element?&amp;quot;.&lt;br /&gt;
Specify &#039;actionStringTranslated&#039; to display some information about &amp;quot;what happens when I click on this element?&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
You must specify both of the strings. You can only use one and specify an empty string (&#039;&#039;) for the other one.&lt;br /&gt;
&lt;br /&gt;
When you pass text directly function _() must be used for the text to be marked for translation! Except for empty string.&lt;br /&gt;
&lt;br /&gt;
Parameter &amp;quot;delay&amp;quot; is optional. It is primarily used to specify a zero delay for some game element when the tooltip gives really important information for the game - but remember: no essential information must be placed in tooltips as they won&#039;t be displayed in some browsers (see [[BGA_Studio_Guidelines|Guidelines]]).&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
   this.addTooltip( &#039;cardcount&#039;, _(&#039;Number of cards in hand&#039;), &#039;&#039; );&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note: this generates static tooltip and attaches to existing dom element, if you need to generate tooltip more dynamically you have to call that method every time information about object is updated or use completely different tehnique, see dynamic tooltips below.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.addTooltipHtml(nodeId: string, html: string, delay?: number): void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Add an HTML tooltip to the DOM node (for more elaborate content such as presenting a bigger version of a card).&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.addTooltipToClass(cssClass: string, helpStringTranslated: string, actionStringTranslated: string, delay?: number ): void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Add a simple text tooltip to all the DOM nodes set with this cssClass. See more details above for this.addTooltip.&lt;br /&gt;
     this.addTooltipToClass( &#039;meeple&#039;, _(&#039;This is A Meeple&#039;), _(&#039;Click to tickle&#039;) );&lt;br /&gt;
&lt;br /&gt;
IMPORTANT: all concerned nodes must exist and have IDs to get tooltips.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.addTooltipHtmlToClass(cssClass: string, html: string, delay?: number): void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Add an HTML tooltip to to all the DOM nodes set with this cssClass (for more elaborate content such as presenting a bigger version of a card).&lt;br /&gt;
&lt;br /&gt;
IMPORTANT: all concerned nodes must exist and have IDs to get tooltips.&lt;br /&gt;
&lt;br /&gt;
=== Removing static tooltips ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.removeTooltip(nodeId: string): void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Remove a tooltip from the DOM node with given id.&lt;br /&gt;
&lt;br /&gt;
=== Advanced tooltips ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;force tooltip to open&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
If you want to force tooltip to open in reaction to some other action, i.e. click you can do this&lt;br /&gt;
&lt;br /&gt;
   this.tooltips[id].open(id)&lt;br /&gt;
&lt;br /&gt;
where id is the id of the tooltip node where tooltip was installed.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;dynamic tooltips&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
See [[BGA_Studio_Cookbook#Dynamic_tooltips]]&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;tooltips on mobile&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Tooltips is very unreliable on mobile, it is recommended to implement some other method to obtaining same information,&lt;br /&gt;
such as simple click handler in dedicated &amp;quot;Help&amp;quot; mode or provide dedicated clickable areas such as corner of card.&lt;br /&gt;
&lt;br /&gt;
== Warning messages ==&lt;br /&gt;
&lt;br /&gt;
Sometimes, there is something important that is happening in the game and you have to make sure all players get the message. Most of the time, the evolution of the game situation or the game log is enough, but sometimes you need something more visible.&lt;br /&gt;
&lt;br /&gt;
Ex: someone fulfills one of the end of the game conditions, so this is the last turn.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.showMessage(msg: string, type: string): void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
showMessage shows a message in a big rectangular area on the top of the screen of the current player, and it dissapears after few seconds (also it will be in the log in some cases).&lt;br /&gt;
&lt;br /&gt;
* &amp;quot;msg&amp;quot; is the string to display. It should be translated.&lt;br /&gt;
* &amp;quot;type&amp;quot; can be set to &amp;quot;info&amp;quot;, &amp;quot;error&amp;quot;, &amp;quot;only_to_log&amp;quot; or custom string. If set to &amp;quot;info&amp;quot;, the message will be an informative message on a white background. If set to &amp;quot;error&amp;quot;, the message will be an error message on a red background and it will be added to log. If set to &amp;quot;only_to_log&amp;quot;, the message will be added to the game log but will not popup at the top of the screen.&lt;br /&gt;
If set to custom string, it will be transparent, to use custom type define &amp;quot;head_xxx&amp;quot; in css, where xxx is the type. For example if you want yellow warning, use &amp;quot;warning&amp;quot; as type and add this to css:&lt;br /&gt;
 .head_warning {&lt;br /&gt;
    background-color: #e6c66e;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
Important: the normal way to inform players about the progression of the game is the game log. The &amp;quot;showMessage&amp;quot; is intrusive and should not be used often.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    notif_messageinfo: function(notif) {&lt;br /&gt;
	if (!g_archive_mode) {&lt;br /&gt;
        	var message = this.format_string_recursive(notif.log, notif.args);&lt;br /&gt;
		this.showMessage(_(&#039;Announcement:&#039;) + &amp;quot; &amp;quot; + message, &#039;info&#039;);		&lt;br /&gt;
         }&lt;br /&gt;
    },&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Show message could be used on the client side to prevent user wrong moves before it is send to server.&lt;br /&gt;
Example from &#039;battleship&#039;:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
onGrid: function(event) {&lt;br /&gt;
     if (checkIfPlayerTriesToFireOnThemselves(event)) {&lt;br /&gt;
        this.showMessage(_(&#039;This is your own board silly!&#039;), &#039;error&#039;);&lt;br /&gt;
        return;&lt;br /&gt;
     }&lt;br /&gt;
     ...&lt;br /&gt;
},&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.showMoveUnauthorized(): void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Shows predefined user error that move is unauthorized now&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
onPet: function(event) {&lt;br /&gt;
     if (checkPet(event)==false) {&lt;br /&gt;
        this.showMoveUnauthorized();&lt;br /&gt;
        return;&lt;br /&gt;
     }&lt;br /&gt;
     ...&lt;br /&gt;
},&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Dialogs ==&lt;br /&gt;
&lt;br /&gt;
=== Confirmation dialog ===&lt;br /&gt;
&lt;br /&gt;
When an important action with a lot of consequences is triggered by the player, you may want to propose a confirmation dialog.&lt;br /&gt;
&lt;br /&gt;
CAREFUL: the general guideline of BGA is to AVOID the use of confirmation dialogs. Confirmation dialogs slow down the game and bother players. The players know that they have to pay attention to each move when they are playing online.&lt;br /&gt;
&lt;br /&gt;
The situations where you should use a confirmation dialog are the following:&lt;br /&gt;
* It must not happen very often during a game.&lt;br /&gt;
* It must be linked to an action that can really &amp;quot;kill a game&amp;quot; if the player does not pay attention.&lt;br /&gt;
* It must be something that can be done by mistake (ex: a link on the action status bar).&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.confirmationDialog(message: string, yesHandler: (param: any) =&amp;gt; void, noHandler?: (param: any) =&amp;gt; void, param?: any): void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
* message - message will be shown to user, use _() to translate&lt;br /&gt;
* yesHandler - non-optional handler to be called on yes&lt;br /&gt;
* noHandler - optional handler to called on no&lt;br /&gt;
* param - if specified, it will be passed to both handlers&lt;br /&gt;
NOTE: this is async function, it does not return anything and you should not do anything after, you must do everything in handlers&lt;br /&gt;
&lt;br /&gt;
How to display a confirmation dialog:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    this.confirmationDialog(_(&amp;quot;Are you sure you want to bake a pie?&amp;quot;), () =&amp;gt; {&lt;br /&gt;
      this.bakeThePie();&lt;br /&gt;
    });&lt;br /&gt;
    return; // nothing should be called or done after calling this, all action must be done in the handler&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
With param and both handlers&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    this.confirmationDialog(_(&amp;quot;Are you sure you want to bake a pie?&amp;quot;), &lt;br /&gt;
           (ingredient) =&amp;gt; this.bakeThePie(ingredient), &lt;br /&gt;
           (ingredient) =&amp;gt; console.log(`cancelled baking of ${ingredient}`), &lt;br /&gt;
           &#039;apple&#039;);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Multiple choice dialog ===&lt;br /&gt;
&lt;br /&gt;
You can use this dialog to give user a choice with small amount of options&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.multipleChoiceDialog(message: string, choices: string[], callback: (choice: number) =&amp;gt; void): void&#039;&#039;&#039;&lt;br /&gt;
* message - message will be shown to user, use _() to translate&lt;br /&gt;
* choices - array of choices&lt;br /&gt;
* callback - non-optional handler to be called on choice made, the choice parameter is the INDEX of the choice from the array of choices&lt;br /&gt;
&lt;br /&gt;
NOTE: this is async function, it does not return anything and you should not do anything after, you must do everything in handlers&lt;br /&gt;
NOTE: there is no cancel handler, so make sure you gave user a choice to get out of it&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    const keys = [&amp;quot;0&amp;quot;, &amp;quot;1&amp;quot;, &amp;quot;5&amp;quot;, &amp;quot;10&amp;quot;];&lt;br /&gt;
    this.multipleChoiceDialog(_(&amp;quot;How many bugs to fix?&amp;quot;), keys, (choice) =&amp;gt; {&lt;br /&gt;
      if (choice==0) return; // cancel operation, do not call server action&lt;br /&gt;
      var bugchoice = keys[choice]; // choice will be 0,1,2,3 here&lt;br /&gt;
      this.bgaPerformAction(&amp;quot;fixBugs&amp;quot;, { number: bugchoice });&lt;br /&gt;
    });&lt;br /&gt;
    return; // must return here&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Generic Dialogs ===&lt;br /&gt;
&lt;br /&gt;
As a general rule, you shouldn&#039;t use dialogs windows.&lt;br /&gt;
&lt;br /&gt;
BGA guidelines specify that all game elements should be displayed on the main screen. Players can eventually scroll down to see game elements they don&#039;t need to see anytime, and you may eventually create anchors to move between game area section. Of course dialogs windows are very practical, but the thing is: all players know how to scroll down, and not all players know how to show up your dialog window. In addition, when the dialog shows up, players can&#039;t access the other game components.&lt;br /&gt;
&lt;br /&gt;
Sometimes although, you need to display a dialog window. Here is how you do this:&lt;br /&gt;
&lt;br /&gt;
  // Create the new dialog over the play zone. You should store the handler in a member variable to access it later&lt;br /&gt;
  this.myDlg = new ebg.popindialog();&lt;br /&gt;
  this.myDlg.create( &#039;myDialogUniqueId&#039; );&lt;br /&gt;
  this.myDlg.setTitle( _(&amp;quot;my dialog title to translate&amp;quot;) );&lt;br /&gt;
  this.myDlg.setMaxWidth( 500 ); // Optional&lt;br /&gt;
  &lt;br /&gt;
  // Create the HTML of my dialog. &lt;br /&gt;
  // The best practice here is to use [[Game_layout:_view_and_template:_yourgamename.view.php_and_yourgamename_yourgamename.tpl#Javascript_templates|Javascript templates]]&lt;br /&gt;
  var html = this.format_block( &#039;jstpl_myDialogTemplate&#039;, { &lt;br /&gt;
                arg1: myArg1,&lt;br /&gt;
                arg2: myArg2,&lt;br /&gt;
                ...&lt;br /&gt;
            } );  &lt;br /&gt;
  &lt;br /&gt;
  // Show the dialog&lt;br /&gt;
  this.myDlg.setContent( html ); // Must be set before calling show() so that the size of the content is defined before positioning the dialog&lt;br /&gt;
  this.myDlg.show();&lt;br /&gt;
  &lt;br /&gt;
  // Now that the dialog has been displayed, you can connect your method to some dialog elements&lt;br /&gt;
  // Example, if you have an &amp;quot;OK&amp;quot; button in the HTML of your dialog:&lt;br /&gt;
  dojo.connect($(&#039;my_ok_button&#039;), &#039;onclick&#039;, this, (event) =&amp;gt; {&lt;br /&gt;
                event.preventDefault();&lt;br /&gt;
                this.myDlg.destroy();&lt;br /&gt;
            });&lt;br /&gt;
&lt;br /&gt;
If necessary, you can remove the default top right corner &#039;close&#039; icon, or replace the function called when it is clicked:&lt;br /&gt;
  // Removes the default close icon&lt;br /&gt;
  this.myDlg.hideCloseIcon();&lt;br /&gt;
&lt;br /&gt;
  // Replace the function call when it&#039;s clicked&lt;br /&gt;
  this.myDlg.replaceCloseCallback((event) =&amp;gt; { ... });&lt;br /&gt;
&lt;br /&gt;
=== Scoring dialogs ===&lt;br /&gt;
&lt;br /&gt;
Sometimes at the end of a round you want to display a big table that details the points wins in each section of the game.&lt;br /&gt;
&lt;br /&gt;
Example: in Hearts game, we display at the end of each round the number of &amp;quot;heart&amp;quot; cards collected by each player, the player who collected the Queen of Spades, and the total number of points loose by each player.&lt;br /&gt;
&lt;br /&gt;
Scoring dialogs are managed entirely on &#039;&#039;&#039;PHP side&#039;&#039;&#039;, but they are described here as their effects are visible only on client side.&lt;br /&gt;
&lt;br /&gt;
Displaying a scoring dialog is quite simple and is using a special notification type: &amp;quot;tableWindow&amp;quot;:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  // on PHP side:&lt;br /&gt;
  $this-&amp;gt;notifyAllPlayers( &amp;quot;tableWindow&amp;quot;, &#039;&#039;, array(&lt;br /&gt;
            &amp;quot;id&amp;quot; =&amp;gt; &#039;finalScoring&#039;,&lt;br /&gt;
            &amp;quot;title&amp;quot; =&amp;gt; clienttranslate(&amp;quot;Title of the scoring dialog&amp;quot;),&lt;br /&gt;
            &amp;quot;table&amp;quot; =&amp;gt; $table&lt;br /&gt;
        )); &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The &amp;quot;table&amp;quot; argument is a 2 dimensional PHP array that describes the table you want to display, line by line and column by column.&lt;br /&gt;
&lt;br /&gt;
Example: display an 3x3 array of strings&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
   $table = [&lt;br /&gt;
      [ &amp;quot;one&amp;quot;, &amp;quot;two&amp;quot;, &amp;quot;three&amp;quot; ],    // This is my first line&lt;br /&gt;
      [ &amp;quot;four&amp;quot;, &amp;quot;five&amp;quot;, &amp;quot;six&amp;quot; ],    // This is my second line&lt;br /&gt;
      [ &amp;quot;seven&amp;quot;, &amp;quot;height&amp;quot;, &amp;quot;nine&amp;quot; ]    // This is my third line&lt;br /&gt;
   ];&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
As you can see above, in each &amp;quot;cell&amp;quot; of your array you can display a simple string value. But you can also display a complex value with a template and associated arguments like this:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
   $table = [&lt;br /&gt;
      [ &amp;quot;one&amp;quot;, &amp;quot;two&amp;quot;, [ &amp;quot;str&amp;quot; =&amp;gt; clienttranslate(&amp;quot;a string with an ${argument}&amp;quot;), &amp;quot;args&amp;quot; =&amp;gt; [ &#039;argument&#039; =&amp;gt; &#039;argument_value&#039; ] ] ],&lt;br /&gt;
      [ &amp;quot;four&amp;quot;, &amp;quot;five&amp;quot;, &amp;quot;six&amp;quot; ], &lt;br /&gt;
      [ &amp;quot;seven&amp;quot;, &amp;quot;height&amp;quot;, &amp;quot;nine&amp;quot; ]&lt;br /&gt;
   ];&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This is especially useful when you want to display player names with colors. Example from &amp;quot;Hearts&amp;quot;:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        $firstRow = [ &#039;&#039; ];&lt;br /&gt;
        foreach( $players as $player_id =&amp;gt; $player )    {&lt;br /&gt;
            $cell = [ &#039;str&#039; =&amp;gt; &#039;${player_name}&#039;,&lt;br /&gt;
                      &#039;args&#039; =&amp;gt; [ &#039;player_name&#039; =&amp;gt; $player[&#039;player_name&#039;] ],&lt;br /&gt;
                      &#039;type&#039; =&amp;gt; &#039;header&#039;&lt;br /&gt;
                    ];&lt;br /&gt;
            $firstRow[] = $cell;&lt;br /&gt;
        }&lt;br /&gt;
        $table[] = $firstRow;&lt;br /&gt;
        ...&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You can also use three extra attributes in the parameter array for the notification:&lt;br /&gt;
* &#039;&#039;&#039;header&#039;&#039;&#039;: the content for this parameter displays before the table (also, the html will be parsed and player names will be colored according to the current game colors). &lt;br /&gt;
* &#039;&#039;&#039;footer&#039;&#039;&#039;: the content for this parameter displays after the table (no parsing for coloring the player names)&lt;br /&gt;
* &#039;&#039;&#039;closing&#039;&#039;&#039;: if this parameter is used, a button will be displayed with this label at the bottom of the popup and will allow players to close it (more easily than by clicking the top right &#039;cross&#039; icon).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
   $this-&amp;gt;notifyAllPlayers( &amp;quot;tableWindow&amp;quot;, &#039;&#039;, [&lt;br /&gt;
            &amp;quot;id&amp;quot; =&amp;gt; &#039;finalScoring&#039;,&lt;br /&gt;
            &amp;quot;title&amp;quot; =&amp;gt; clienttranslate(&amp;quot;Title of the scoring dialog&amp;quot;),&lt;br /&gt;
            &amp;quot;table&amp;quot; =&amp;gt; $table,&lt;br /&gt;
            &amp;quot;header&amp;quot; =&amp;gt; [&#039;str&#039; =&amp;gt; clienttranslate(&#039;Table header with parameter ${number}&#039;),&lt;br /&gt;
                                 &#039;args&#039; =&amp;gt; [ &#039;number&#039; =&amp;gt; 3 ],&lt;br /&gt;
                               ],&lt;br /&gt;
            &amp;quot;footer&amp;quot; =&amp;gt; &#039;&amp;lt;div class=&amp;quot;myfoot&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&#039;,&lt;br /&gt;
            &amp;quot;closing&amp;quot; =&amp;gt; clienttranslate( &amp;quot;Closing button label&amp;quot; )&lt;br /&gt;
        ] ); &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note: currently id is not used - so you cannot access resulting div by id on js side &lt;br /&gt;
&lt;br /&gt;
Note: any traslatable string have to be wrapped by clienttranslate() on top level OR it has to be recursive template. &lt;br /&gt;
&lt;br /&gt;
DO NOT DO THIS: &lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
   &amp;quot;footer&amp;quot; =&amp;gt; &#039;&amp;lt;div&amp;gt;&#039;.clienttranslate( &amp;quot;The end&amp;quot; ).&#039;&amp;lt;/div&amp;gt;&#039;, // this will not work for translations!!!&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Scoring animated display ===&lt;br /&gt;
&lt;br /&gt;
Sometimes, you may want to display a score value over an element to make the scoring easier to follow for the players (Terra Mystica final scoring for example).&lt;br /&gt;
You can do it with:&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.displayScoring(anchor_id: string, color: string, score: number | string, duration?: number, offset_x?: number, offset_y?: number): void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;anchor_id&#039;&#039;&#039;: ID of the html element to place the animated score onto (without the &#039;#&#039;) &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;color&#039;&#039;&#039;: hexadecimal RGB representation of the color (should be the color of the scoring player), but without a leading &#039;#&#039;.  For instance, &#039;ff0000&#039; for red.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;score&#039;&#039;&#039;: numeric score to display, prefixed by a &#039;+&#039; or &#039;-&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;duration&#039;&#039;&#039;: animation duration in milliseconds (optional, default is 1000)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;offset_x&#039;&#039;&#039; and &#039;&#039;&#039;offset_y&#039;&#039;&#039;: if both offset_x and offset_y are defined and not null, apply the following offset (in pixels) to the scoring animation. &lt;br /&gt;
Note that the score is centered in the anchor, so the offsets might have to be negative if you calculate the position.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Note: if you want to display successively each score, you can use &#039;&#039;this.notifqueue.setSynchronous()&#039;&#039; function.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    setupNotifications: function()   {&lt;br /&gt;
           dojo.subscribe( &#039;displayScoring&#039;, this, &amp;quot;notif_displayScoring&amp;quot; );&lt;br /&gt;
           ...&lt;br /&gt;
    }&lt;br /&gt;
...&lt;br /&gt;
&lt;br /&gt;
    notif_displayScoring: function(notif) {&lt;br /&gt;
            const duration = notif.args.duration?notif.args.duration:1000;&lt;br /&gt;
            this.notifqueue.setSynchronous(&#039;displayScoring&#039;, duration );&lt;br /&gt;
	    this.displayScoring( notif.args.target, notif.args.color, notif.args.score, duration);&lt;br /&gt;
    },&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Speech bubble ===&lt;br /&gt;
&lt;br /&gt;
For better interactivity in some games (Love Letter for example), you may use comic book style speech bubbles to express the players voices.&lt;br /&gt;
This is done with showBubble:&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.showBubble(anchor_id: string, text: string, delay?: number, duration?: number, custom_class?: string): void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
* anchor_id - where to attach the bubble&lt;br /&gt;
* text - what to put in bubble, can be html&lt;br /&gt;
* delay - delay in milliseconds (optional, default 0)&lt;br /&gt;
* duration -  duration of animation in milliseconds (optional, default 3000)&lt;br /&gt;
* custom_class - extra class to add to bubble (optional), if you need to override the default bubble style&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
   this.showBubble(&#039;meeple_2&#039;, _(&#039;Hello&#039;), 0, 1000, &#039;pink_bubble&#039;);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  notif_speechBubble(notif) {&lt;br /&gt;
    var html = this.format_string_recursive(notif.args.text, notif.args.args);&lt;br /&gt;
    this.showBubble(notif.args.target, html, notif.args.delay ?? 0, notif.args.duration ?? 1000);&lt;br /&gt;
  },&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Warning&#039;&#039;&#039;: if your bubble could overlap other active elements of the interface (buttons in particular), as it stays in place even after disappearing, you should use a custom class to give it the style &amp;quot;pointer-events: none;&amp;quot; in order to intercept click events.&lt;br /&gt;
&lt;br /&gt;
Note: If you want this visually, but want to take complete control over this bubble and its animation (for example to make it permanent) you can just use div with &#039;discussion_bubble&#039; class on it, and content of div is what will be shown.&lt;br /&gt;
&lt;br /&gt;
== Translations ==&lt;br /&gt;
&lt;br /&gt;
See [[Translations]]&lt;br /&gt;
&lt;br /&gt;
== Players panels ==&lt;br /&gt;
&lt;br /&gt;
=== Update players score ===&lt;br /&gt;
&lt;br /&gt;
The column player_score from the player table is automatically loaded into this.scoreCtrl and therefore into the stars location on the player board. This occurs sometime after the game setup() function. However this score must be updated as the game progresses using notifications.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Note: this.scoreCtrl[player_id] is object of class [[Counter]], you can use other counter API.&lt;br /&gt;
&lt;br /&gt;
Increase a player score (with a positive or negative number):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  this.scoreCtrl[ player_id ].incValue( score_delta );&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Set a player score to a specific value:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  this.scoreCtrl[ player_id ].setValue( new_score );&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Set a player score to a specific value with animation:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  this.scoreCtrl[ player_id ].toValue( new_score );&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Typical usage would be (that will process &#039;score&#039; notification):&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        setupNotifications : function() {&lt;br /&gt;
              ...&lt;br /&gt;
             dojo.subscribe(&#039;score&#039;, this, &amp;quot;notif_score&amp;quot;);&lt;br /&gt;
        },&lt;br /&gt;
        notif_score: function(notif) {&lt;br /&gt;
            this.scoreCtrl[notif.args.player_id].setValue(notif.args.player_score);&lt;br /&gt;
        },&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Adding stuff to player&#039;s panel ===&lt;br /&gt;
&lt;br /&gt;
At first, create a new &amp;quot;JS template&amp;quot; string in your template (tpl) file:&lt;br /&gt;
&lt;br /&gt;
(from Gomoku example)&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
var jstpl_player_board = &#039;\&amp;lt;div class=&amp;quot;cp_board&amp;quot;&amp;gt;\&lt;br /&gt;
    &amp;lt;div id=&amp;quot;stoneicon_p${id}&amp;quot; class=&amp;quot;gmk_stoneicon gmk_stoneicon_${color}&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&amp;lt;span id=&amp;quot;stonecount_p${id}&amp;quot;&amp;gt;0&amp;lt;/span&amp;gt;\&lt;br /&gt;
&amp;lt;/div&amp;gt;&#039;;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Then, you add this piece of code in your JS file to add this template to each player panel:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
            // Setting up player boards&lt;br /&gt;
            for( var player_id in gamedatas.players )&lt;br /&gt;
            {&lt;br /&gt;
                var player = gamedatas.players[player_id];&lt;br /&gt;
                         &lt;br /&gt;
                // Setting up players boards if needed&lt;br /&gt;
                var player_board_div = $(&#039;player_board_&#039;+player_id);&lt;br /&gt;
                dojo.place( this.format_block(&#039;jstpl_player_board&#039;, player ), player_board_div );&lt;br /&gt;
            }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
(Note: the code above is of course from your &amp;quot;setup&amp;quot; function in your Javascript).&lt;br /&gt;
&lt;br /&gt;
Very often, you have to distinguish current player and others players. In this case, you just have to create another JS template (ex: jstpl_otherplayer_board) and use it when &amp;quot;player_id&amp;quot; is different than &amp;quot;this.player_id&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Fixing Player Panel heights ===&lt;br /&gt;
&lt;br /&gt;
You may find that the player panels don&#039;t automatically resize when adding something to (or removing something from) a player panel while the display is in portrait mode (i.e. the player summary panels are at the top of the screen rather than down the right side).&lt;br /&gt;
&lt;br /&gt;
When this happens, call &amp;lt;pre&amp;gt;this.adaptPlayersPanels();&amp;lt;/pre&amp;gt; This recalculates the layout and also adjusts the position of the actionbar for you.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Player&#039;s panel disabling/enabling ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.disablePlayerPanel(player_id: number): void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Disable given player panel (the panel background become gray).&lt;br /&gt;
&lt;br /&gt;
Usually, this is used to signal that this played passes, or will be inactive during a while.&lt;br /&gt;
&lt;br /&gt;
Note that the only effect of this is visual. There are no consequences on the behaviour of the panel itself.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.enablePlayerPanel(player_id:number): void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Enable a player panel that has been disabled before.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.enableAllPlayerPanels(): void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Enable all player panels that has been disabled before.&lt;br /&gt;
&lt;br /&gt;
=== Player order ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.updatePlayerOrdering(): void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
This function makes sure that player order in player&#039;s panel matches this.gamedatas.playerorder and its normally called by framework.&lt;br /&gt;
You can call it yoursel if you change this.gamedatas.playerorder from notification.&lt;br /&gt;
Also you can override this function to change defaults  OR insert a non-player panel [[BGA_Studio_Cookbook#Inserting_non-player_panel]].&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Counters ===&lt;br /&gt;
Note: there is a bga component called  &amp;quot;ebg/counter&amp;quot;, this API is not using it. These methods below are declared right in the core game. If you need animation for counters use ebg/counter&lt;br /&gt;
&lt;br /&gt;
To use this API just create a counter dom element like this (class does not really matter)&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 &amp;lt;div class=&amp;quot;counter&amp;quot; id=&amp;quot;bread&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
 &amp;lt;div class=&amp;quot;counter&amp;quot; id=&amp;quot;coin&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
The &amp;quot;bread&amp;quot; div will be the counter name.&lt;br /&gt;
&lt;br /&gt;
The php code should send all &amp;quot;counters&amp;quot; data from getAllDatas() method like this&lt;br /&gt;
&lt;br /&gt;
game.php&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  protected function getAllDatas() {&lt;br /&gt;
    // (the key must match counter_name)&lt;br /&gt;
    $result[&#039;counters&#039;]=[&lt;br /&gt;
        &#039;bread&#039; =&amp;gt; [ &lt;br /&gt;
         &#039;counter_name&#039; =&amp;gt; &#039;bread&#039;, &lt;br /&gt;
         &#039;counter_value&#039; =&amp;gt; 3&lt;br /&gt;
         ], &lt;br /&gt;
        &#039;coin&#039; =&amp;gt; [&lt;br /&gt;
          &#039;counter_name&#039; =&amp;gt; &#039;coin&#039;, &lt;br /&gt;
          &#039;counter_value&#039; =&amp;gt; 5&lt;br /&gt;
        ]&lt;br /&gt;
   ];&lt;br /&gt;
   return $result;&lt;br /&gt;
  }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;setCounter(counter_name: stirng, new_value: string | number): void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
updates the global this.gamedatas.counters and value of node $(counter_name)&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  notif_counter: function(notif) { &lt;br /&gt;
    this.setCounter(notif.args.counter_name, notif.args.counter_value);&lt;br /&gt;
  },&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;incCounter(counter_name: string, delta: number): void&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  notif_counter : function(notif) {&lt;br /&gt;
    this.incCounter(notif.args.counter_name, notif.args.inc);&lt;br /&gt;
  },&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;updateCounters(counters: object): void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Useful for updating game counters in the player panel (such as resources). &lt;br /&gt;
&#039;counters&#039; arg is map of counters (the key must match counter_name)&lt;br /&gt;
  {&lt;br /&gt;
    &#039;bread&#039;: { &lt;br /&gt;
         &#039;counter_name&#039; : &#039;bread&#039;, &lt;br /&gt;
         &#039;counter_value&#039; =&amp;gt; 3&lt;br /&gt;
    }, &lt;br /&gt;
    &#039;coin&#039;: { &lt;br /&gt;
         &#039;counter_name&#039; : &#039;coin&#039;, &lt;br /&gt;
         &#039;counter_value&#039; =&amp;gt; 5&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
All counters MUST be referenced in this.gamedatas.counters (means they should be send from php) and will be updated.&lt;br /&gt;
DOM objects referenced by &#039;counter_name&#039; will have their innerHTML updated with &#039;counter_value&#039;.&lt;br /&gt;
&lt;br /&gt;
Usually you call this from notification&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
                        notif_counter : function(notif) {&lt;br /&gt;
                            this.updateCounters(notif.args.counters);&lt;br /&gt;
                        },&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== BGA GUI components ==&lt;br /&gt;
&lt;br /&gt;
BGA framework provides some useful ready-to-use components for the game interface:&lt;br /&gt;
&lt;br /&gt;
[[Studio#BGA_Studio_game_components_reference]]&lt;br /&gt;
&lt;br /&gt;
Note that each time you are using an additional component, you must declare it at the top of your Javascript file in the list of modules used.&lt;br /&gt;
&lt;br /&gt;
Example if you are using &amp;quot;ebg.stock&amp;quot;:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
define([&lt;br /&gt;
    &amp;quot;dojo&amp;quot;,&amp;quot;dojo/_base/declare&amp;quot;,&lt;br /&gt;
    &amp;quot;ebg/core/gamegui&amp;quot;,&lt;br /&gt;
    &amp;quot;ebg/counter&amp;quot;,&lt;br /&gt;
    &amp;quot;ebg/stock&amp;quot;  /// &amp;lt;=== we are using ebg.stock module&lt;br /&gt;
],&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== BGA Buttons ==&lt;br /&gt;
&lt;br /&gt;
=== Basic Button ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.addActionButton(id: string, label: string, method: string | eventhandler, destination?: string, blinking?: boolean, color?: string): void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
You can use this method to add an action button in the main action status bar (or other places).&lt;br /&gt;
&lt;br /&gt;
Arguments:&lt;br /&gt;
* id: an element ID that should be unique in your HTML DOM document.&lt;br /&gt;
* label: the text of the button. Should be translatable (use _() function). Note: this can also be any html, such as &amp;quot;&amp;lt;div class=&#039;brick&#039;&amp;gt;&amp;lt;/div&amp;gt;&amp;quot;, see example below on how to make image action buttons.&lt;br /&gt;
* method: the name of your method that must be triggered when the player clicks on this button (can be name of the method on game class or handler).&lt;br /&gt;
* destination (optional): id of parent on where to add button, ONLY use in rare cases if location is not action bar. Use &#039;&#039;&#039;null&#039;&#039;&#039; as value if you need to specify other arguments.&lt;br /&gt;
* blinking (optional): if set to &#039;&#039;&#039;true&#039;&#039;&#039;, the button is going blink to catch player&#039;s attention. Please DO NOT abuse blinking button. If you need button to blink after some time passed add class &#039;blinking&#039; to the button later.&lt;br /&gt;
* color: could be &#039;&#039;&#039;blue&#039;&#039;&#039; (default), &#039;&#039;&#039;red&#039;&#039;&#039;,&#039;&#039;&#039;gray&#039;&#039;&#039; or &#039;&#039;&#039;none&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
You should only use this method in your &amp;quot;onUpdateActionButtons&amp;quot; method. Usually, you use it like this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        onUpdateActionButtons: function( stateName, args ) {                      &lt;br /&gt;
            if (this.isCurrentPlayerActive()) {            &lt;br /&gt;
                switch( stateName ) {&lt;br /&gt;
                case &#039;giveCards&#039;:&lt;br /&gt;
                    this.addActionButton( &#039;giveCards_button&#039;, _(&#039;Give selected cards&#039;), &#039;onGiveCards&#039; ); &lt;br /&gt;
                    this.addActionButton( &#039;pass_button&#039;, _(&#039;Pass&#039;), () =&amp;gt; this.bgaPerformAction(&#039;actPass&#039;) ); &lt;br /&gt;
                    break;&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        },   &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In the example above, we are adding a &amp;quot;Give selected cards&amp;quot; button in the case we are on game state &amp;quot;giveCards&amp;quot;. When player clicks on this button, it triggers our &amp;quot;onGiveCards&amp;quot; method.&lt;br /&gt;
&lt;br /&gt;
Example using blinking red button:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    this.addActionButton( &#039;button_confirm&#039;, _(&#039;Confirm?&#039;), &#039;onConfirm&#039;, null, true, &#039;red&#039;); &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If you want to call the handler with arguments, you can use arrow functions, like this:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
     this.addActionButton( &#039;commit_button&#039;, _(&#039;Confirm&#039;), () =&amp;gt; this.onConfirm(this.selectedCardId), null, false, &#039;red&#039;); &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Image Button ===&lt;br /&gt;
&lt;br /&gt;
You can use the same method, but add extra class to a button to disable the padding and style it, i.e.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
this.addActionButton( &#039;button_brick&#039;, &#039;&amp;lt;div class=&amp;quot;brick&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&#039;, ()=&amp;gt;{... on brick ...}, null, null, &#039;gray&#039;); &lt;br /&gt;
dojo.addClass(&#039;button_brick&#039;,&#039;bgaimagebutton&#039;);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
where&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
.bgaimagebutton {&lt;br /&gt;
  padding: 0px 12px;&lt;br /&gt;
  min-height: 28px;&lt;br /&gt;
  border: none;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If you use this a lot, you can define a helper function, i.e.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
 * This method can be used instead of addActionButton, to add a button which is an image (i.e. resource). Can be useful when player&lt;br /&gt;
 * need to make a choice of resources or tokens.&lt;br /&gt;
 */&lt;br /&gt;
addImageActionButton: function(id, div, handler, bcolor, tooltip) {&lt;br /&gt;
	if (typeof bcolor == &amp;quot;undefined&amp;quot;) {&lt;br /&gt;
		bcolor = &amp;quot;gray&amp;quot;;&lt;br /&gt;
	}&lt;br /&gt;
	// this will actually make a transparent button id color = gray&lt;br /&gt;
	this.addActionButton(id, div, handler, null, false, bcolor);&lt;br /&gt;
	// remove border, for images it better without&lt;br /&gt;
	dojo.style(id, &amp;quot;border&amp;quot;, &amp;quot;none&amp;quot;);&lt;br /&gt;
	// but add shadow style (box-shadow, see css)&lt;br /&gt;
	dojo.addClass(id, &amp;quot;shadow bgaimagebutton&amp;quot;);&lt;br /&gt;
	// you can also add additional styles, such as background&lt;br /&gt;
	if (tooltip) {&lt;br /&gt;
		dojo.attr(id, &amp;quot;title&amp;quot;, tooltip);&lt;br /&gt;
	}&lt;br /&gt;
	return $(id);&lt;br /&gt;
},&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Disabling Button ===&lt;br /&gt;
&lt;br /&gt;
You can disable the &#039;&#039;&#039;bgabutton&#039;&#039;&#039; by adding the css class &#039;&#039;&#039;disabled&#039;&#039;&#039; in you js. The disabled button is still visible but is grey and not clickable.&lt;br /&gt;
For example in the &#039;&#039;&#039;onUpdateActionButtons&#039;&#039;&#039; : &lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
this.addActionButton(&#039;play_button_id&#039;, _(&#039;Play 1 to 3 cards&#039;), &#039;playFunctionButton&#039;); &lt;br /&gt;
if (condition) {&lt;br /&gt;
  dojo.addClass(&#039;play_button_id&#039;, &#039;disabled&#039;);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Custom Buttons ===&lt;br /&gt;
&lt;br /&gt;
You can create a custom button, but the BGA framework provides a standard button that requires only .css classes: &#039;&#039;&#039;bgabutton&#039;&#039;&#039; and &#039;&#039;&#039;bgabutton_${color}&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Examples:&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;a href=&amp;quot;#&amp;quot; id=&amp;quot;my_button_id&amp;quot; class=&amp;quot;bgabutton bgabutton_blue&amp;quot;&amp;gt;&amp;lt;span&amp;gt;My blue button&amp;lt;/span&amp;gt;&amp;lt;/a&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;a href=&amp;quot;#&amp;quot; id=&amp;quot;my_button_id&amp;quot; class=&amp;quot;bgabutton bgabutton_red bgabutton_big&amp;quot;&amp;gt;&amp;lt;span&amp;gt;My big red button&amp;lt;/span&amp;gt;&amp;lt;/a&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note&#039;&#039;&#039;: To see it in action, check out &#039;&#039;Coloretto&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
=== Button outside of action bar ===&lt;br /&gt;
&lt;br /&gt;
Use addActionButton() method with destination argument set&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
this.addActionButton( &#039;commit_button&#039;, _(&#039;Confirm&#039;), &#039;onConfirm&#039;, &#039;player_board&#039;, true, &#039;red&#039;); &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
in example above the button will be place on object with id &#039;player_board&#039;&lt;br /&gt;
&lt;br /&gt;
== Image loading ==&lt;br /&gt;
&lt;br /&gt;
See also [[Game_art:_img_directory]].&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Be careful&#039;&#039;&#039;: by default, ALL images of your img directory are loaded on a player&#039;s browser when he loads the game. For this reason, don&#039;t let in your img directory images that are not useful, otherwise it&#039;s going to slowdown the game load.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.dontPreloadImage(image_file_name: string)&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Using dontPreloadImage, you tell the interface to not preload a specific image in your img directory.&lt;br /&gt;
&lt;br /&gt;
Example of use:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
this.dontPreloadImage( &#039;cards.png&#039; );&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This is particularly useful if for example you have 2 different themes for a game. To accelerate the loading of the game, you can specify to not preload images corresponding to the other theme.&lt;br /&gt;
&lt;br /&gt;
Another example of use: in &amp;quot;Gosu&amp;quot; game with Kamakor extension, you play with 5 sets of cards among 10 available. Cards images are organized by sets, and we only preload the images corresponding to the 5 current sets with &#039;&#039;&#039;ensureSpecificGameImageLoading( image_file_names_array )&#039;&#039;&#039;.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
// By default, do not preload anything&lt;br /&gt;
this.dontPreloadImage( &#039;cards.png&#039; );&lt;br /&gt;
this.dontPreloadImage( &#039;clan1.png&#039; );&lt;br /&gt;
this.dontPreloadImage( &#039;clan2.png&#039; );&lt;br /&gt;
this.dontPreloadImage( &#039;clan3.png&#039; );&lt;br /&gt;
this.dontPreloadImage( &#039;clan4.png&#039; );&lt;br /&gt;
this.dontPreloadImage( &#039;clan5.png&#039; );&lt;br /&gt;
this.dontPreloadImage( &#039;clan6.png&#039; );&lt;br /&gt;
this.dontPreloadImage( &#039;clan7.png&#039; );&lt;br /&gt;
this.dontPreloadImage( &#039;clan8.png&#039; );&lt;br /&gt;
this.dontPreloadImage( &#039;clan9.png&#039; );&lt;br /&gt;
this.dontPreloadImage( &#039;clan10.png&#039; );&lt;br /&gt;
var to_preload = [];&lt;br /&gt;
for( i in this.gamedatas.clans )&lt;br /&gt;
{&lt;br /&gt;
	var clan_id = this.gamedatas.clans[i];&lt;br /&gt;
	to_preload.push( &#039;clan&#039;+clan_id+&#039;.png&#039; );&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
this.ensureSpecificGameImageLoading( to_preload );&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note:&#039;&#039;&#039; You don&#039;t need to specify to not preload game box images (game_box.png, game_box75.png...) since they are not preloaded by default.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.ensureSpecificGameImageLoading(list: string[])&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
This is oppostive of dontPreloadImage - its ensure specific images is loaded. Note: only makes sense if preload list is empty, otherwise everything is loaded anyway&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;load specific images&#039;&#039;&#039;&lt;br /&gt;
All images that will be preloaded stored in g_img_preload. If you want to override it directly - there is no API, but you can do this in GAME constructor&lt;br /&gt;
&lt;br /&gt;
          g_img_preload = [&#039;tokens.png&#039;, &#039;trains.png&#039;, &#039;loc_plan.png&#039;, &#039;eng.png&#039;, &#039;eng-back.png&#039;];&lt;br /&gt;
&lt;br /&gt;
You can also set it to empty array and call ensureSpecificGameImageLoading() on specific images&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Sounds ==&lt;br /&gt;
&lt;br /&gt;
Add a custom sound and make it load with your interface:&lt;br /&gt;
&lt;br /&gt;
Add this in your template (.tpl) file:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;audio id=&amp;quot;audiosrc_&amp;lt;gamename&amp;gt;_&amp;lt;yoursoundname&amp;gt;&amp;quot; src=&amp;quot;{GAMETHEMEURL}img/&amp;lt;gamename&amp;gt;_&amp;lt;yoursoundname&amp;gt;.mp3&amp;quot; preload=&amp;quot;none&amp;quot; autobuffer&amp;gt;&amp;lt;/audio&amp;gt;&lt;br /&gt;
&amp;lt;audio id=&amp;quot;audiosrc_o_&amp;lt;gamename&amp;gt;_&amp;lt;yoursoundname&amp;gt;&amp;quot; src=&amp;quot;{GAMETHEMEURL}img/&amp;lt;gamename&amp;gt;_&amp;lt;yoursoundname&amp;gt;.ogg&amp;quot; preload=&amp;quot;none&amp;quot; autobuffer&amp;gt;&amp;lt;/audio&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note: this is a requirement to provide both a mp3 and a ogg file with the names &amp;lt;code&amp;gt;&amp;lt;gamename&amp;gt;_&amp;lt;yoursoundname&amp;gt;[.ogg][.mp3]&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Play the sound (from your .js file):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
playSound(&#039;&amp;lt;gamename&amp;gt;_&amp;lt;yoursoundname&amp;gt;&#039;);   // do not add &#039;this.&#039; - its a global function&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Disable the standard &amp;quot;move&amp;quot; sound for this move (to replace it with your custom sound):&lt;br /&gt;
&lt;br /&gt;
Add this to your notification handler:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
this.disableNextMoveSound();&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note: it only disable the sound for the next move.&lt;br /&gt;
&lt;br /&gt;
== Title bar and states ==&lt;br /&gt;
&lt;br /&gt;
=== Client states ===&lt;br /&gt;
&lt;br /&gt;
Client states is a way to simulate the state transition but without actually going&lt;br /&gt;
to server. It is usefull when you need to ask user multiple questions before you&lt;br /&gt;
send things to server&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.setClientState(newState: string, args: object)&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
     this.setClientState(&amp;quot;client_playerPicksLocation&amp;quot;, {&lt;br /&gt;
                               descriptionmyturn : _(&amp;quot;${you} must select location&amp;quot;),&lt;br /&gt;
                           });&lt;br /&gt;
&lt;br /&gt;
For more information see [[BGA_Studio_Cookbook#Multi_Step_Interactions:_Select_Worker.2FPlace_Worker_-_Using_Client_States]]&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.restoreServerGameState()&#039;&#039;&#039;&lt;br /&gt;
If you are in client state it will restore the current server state (cheap undo)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.on_client_state&#039;&#039;&#039;&lt;br /&gt;
Boolean indicating that we are in client state&lt;br /&gt;
&lt;br /&gt;
=== Title bar ===&lt;br /&gt;
If you simply want to show something in title bar you can do it directly &lt;br /&gt;
     $(&#039;pagemaintitletext&#039;).innerHTML = text;&lt;br /&gt;
&lt;br /&gt;
This however will not work with parameters and will not draw You in color,&lt;br /&gt;
if you want to do proper args rendering use method below&lt;br /&gt;
&lt;br /&gt;
;&#039;&#039;&#039;this.removeActionButtons()&#039;&#039;&#039;&lt;br /&gt;
Removes all buttons from title bar&lt;br /&gt;
&lt;br /&gt;
;&#039;&#039;&#039;this.updatePageTitle()&#039;&#039;&#039;&lt;br /&gt;
:This function allows to update the current page title and turn description according to the game state arguments. If the current game state description this.gamedatas.gamestate.descriptionmyturn is modified before calling this function it allows to update the turn description without changing state. This will handle arguments substitutions properly.&lt;br /&gt;
&lt;br /&gt;
Note: this functional also will calls this.onUpdateActionButtons, if you want different buttons then state defaults, use method in example to replace them, if it becomes too clumsy use client states (see above)&lt;br /&gt;
&lt;br /&gt;
Example from Terra Mystica:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
onClickFavorTile: function( evt ) {&lt;br /&gt;
    ...&lt;br /&gt;
    if ( ... ) {&lt;br /&gt;
        this.gamedatas.gamestate.descriptionmyturn = _(&#039;Special action: &#039;) + _(&#039;Advance 1 space	on a Cult track&#039;);&lt;br /&gt;
        this.updatePageTitle();&lt;br /&gt;
        this.removeActionButtons();&lt;br /&gt;
        this.addActionButton( ... );&lt;br /&gt;
         ...&lt;br /&gt;
        return;&lt;br /&gt;
    }&lt;br /&gt;
    ...&lt;br /&gt;
&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== User preferences ==&lt;br /&gt;
&#039;&#039;&#039;this.getGameUserPreference(pref_id)&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Return the value of a user preference. It will return the value currently selected in the select combo box, in the top-right menu.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.setGameUserPreference(pref_id, value)&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Programmatically change a user preference. It will have the same effect as if the player changed the value in the select combo box, in the top-right menu.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.onGameUserPreferenceChanged&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
A callback you can define if you want to be notified when a user changes a user preference.&lt;br /&gt;
&lt;br /&gt;
Example:&amp;lt;pre&amp;gt;&lt;br /&gt;
onGameUserPreferenceChanged: function(pref_id, pref_value) {&lt;br /&gt;
  switch (pref_id) {&lt;br /&gt;
    case 201: &lt;br /&gt;
      document.getElementsByTagName(&#039;html&#039;)[0].classList.toggle(&#039;dark-background&#039;, pref_value == 2);&lt;br /&gt;
      break;&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Other useful stuff ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;dojo.hitch&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
With dojo.hitch, you can create a callback function that will run with your game object context whatever happen.&lt;br /&gt;
&lt;br /&gt;
Typical example: display a BGA confirmation dialog with a callback function created with dojo.hitch:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        this.confirmationDialog( _(&#039;Are you sure you want to make this?&#039;), dojo.hitch( this, function() {&lt;br /&gt;
            this.bgaPerformAction(&#039;makeThis&#039;);&lt;br /&gt;
        } ) );   &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In the example above, using dojo.hitch, we ensure that the &amp;quot;this&amp;quot; object will be set when the callback is called.&lt;br /&gt;
&lt;br /&gt;
NOTE: In modern JS there are lambdas that eliminate need for that, the example above will look like this&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        this.confirmationDialog( _(&#039;Are you sure you want to make this?&#039;), () =&amp;gt; this.bgaPerformAction( &#039;makeThis&#039;) );   &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
;&#039;&#039;&#039;onScreenWidthChange()&#039;&#039;&#039;&lt;br /&gt;
:This function can be overridden in your game to manage some resizing on the client side when the browser window is resized. This function is also triggered at load time, so it can be used to adapt to the :viewport size at the start of the game too.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
; this.bRealtime&lt;br /&gt;
: Return true if the game is in realtime. Note that having a distinct behavior in realtime and turn-based should be exceptional.&lt;br /&gt;
&lt;br /&gt;
; g_replayFrom&lt;br /&gt;
: Global contains replay number in live game, it is set to undefined (i.e. not set) when it is not a replay mode, so consequentially the good check is &#039;&#039;&#039;typeof g_replayFrom != &#039;undefined&#039;&#039;&#039;&#039; which returns true if the game is in replay mode &amp;lt;i&amp;gt;during the game&amp;lt;/i&amp;gt; (the game is ongoing but the user clicked &amp;quot;replay from this move&amp;quot; in the log)&lt;br /&gt;
&lt;br /&gt;
; g_archive_mode&lt;br /&gt;
: Returns true if the game is in archive mode &amp;lt;i&amp;gt;after the game&amp;lt;/i&amp;gt; (the game has ended)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
; this.instantaneousMode&lt;br /&gt;
: Returns true during replay/archive mode if animations should be skipped. Only needed if you are doing custom animations. (The BGA-provided animation functions like &amp;lt;i&amp;gt;this.slideToObject()&amp;lt;/i&amp;gt; automatically handle instantaneous mode.)&lt;br /&gt;
: Technically, when you click &amp;quot;replay from move #20&amp;quot;, the system replays the game from the very beginning with moves 0 - 19 happening in instantaneous mode and moves 20+ happening in normal mode.&lt;br /&gt;
&lt;br /&gt;
; g_tutorialwritten&lt;br /&gt;
: Returns an object like the below if the game is in tutorial mode, or undefined otherwise. Tutorial mode is a special case of archive mode where comments have been added to a previous game to teach new players the rules.&lt;br /&gt;
    {&lt;br /&gt;
        author: &amp;quot;91577332&amp;quot;,&lt;br /&gt;
        id: &amp;quot;576&amp;quot;,&lt;br /&gt;
        mode: &amp;quot;view&amp;quot;&lt;br /&gt;
        status: &amp;quot;alpha&amp;quot;&lt;br /&gt;
        version_override: null&lt;br /&gt;
        viewer_id: &amp;quot;84554161&amp;quot;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;getBgaEnvironment(): string&#039;&#039;&#039;&lt;br /&gt;
: Returns &amp;quot;studio&amp;quot; for studio and &amp;quot;prod&amp;quot; for production environment (i.e. where games current runs). Only useful for debbugging hooks.&lt;br /&gt;
Note: alpha server is also &amp;quot;prod&amp;quot;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Category:Studio]]&lt;/div&gt;</summary>
		<author><name>Sguzzer Gunayer</name></author>
	</entry>
	<entry>
		<id>https://en.doc.boardgamearena.com/index.php?title=Game_interface_logic:_Game.js&amp;diff=22739</id>
		<title>Game interface logic: Game.js</title>
		<link rel="alternate" type="text/html" href="https://en.doc.boardgamearena.com/index.php?title=Game_interface_logic:_Game.js&amp;diff=22739"/>
		<updated>2024-09-25T18:26:43Z</updated>

		<summary type="html">&lt;p&gt;Sguzzer Gunayer: /* Counters */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Studio_Framework_Navigation}}&lt;br /&gt;
&lt;br /&gt;
__TOC__&lt;br /&gt;
&lt;br /&gt;
This is the main file for your game interface. Here you will define:&lt;br /&gt;
&lt;br /&gt;
* Which actions on the page will generate calls to the server.&lt;br /&gt;
* What happens when you get a notification for a change from the server and how it will show in the browser. &lt;br /&gt;
* Setup user interface&lt;br /&gt;
&lt;br /&gt;
== File structure ==&lt;br /&gt;
&lt;br /&gt;
The details of how the file is structured are described below with comments in the code skeleton provided to you.&lt;br /&gt;
&lt;br /&gt;
Here is the basic structure:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;constructor&#039;&#039;&#039;: here you can define global variables for your whole interface.&lt;br /&gt;
* &#039;&#039;&#039;setup&#039;&#039;&#039;: this method is called when the page is refreshed, and sets up the game interface.&lt;br /&gt;
* &#039;&#039;&#039;onEnteringState&#039;&#039;&#039;: this method is called when entering a new game state. You can use it to customize the view for each game state.&lt;br /&gt;
* &#039;&#039;&#039;onLeavingState&#039;&#039;&#039;: this method is called when leaving a game state.&lt;br /&gt;
* &#039;&#039;&#039;onUpdateActionButtons&#039;&#039;&#039;: called on state changes, in order to add action buttons to the status bar. Note: in a multipleactiveplayer state, it will be called when another player has become inactive.&lt;br /&gt;
* &#039;&#039;(utility methods)&#039;&#039;: this is where you can define your utility methods.&lt;br /&gt;
* &#039;&#039;(player&#039;s actions)&#039;&#039;: this is where you can write your handlers for player actions on the interface (example: click on an item).&lt;br /&gt;
* &#039;&#039;&#039;setupNotifications&#039;&#039;&#039;: this method associates notifications with notification handlers. For each game notification, you can trigger a javascript method to handle it and update the game interface.&lt;br /&gt;
* &#039;&#039;(notification handlers)&#039;&#039;: this is where you define the notifications handlers associated with notifications in &#039;&#039;&#039;setupNotifications&#039;&#039;&#039;, above.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
More details:&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;setup(gamedatas: object)            &#039;&#039;&#039;&lt;br /&gt;
This method must set up the game user interface according to current game situation specified in parameters.&lt;br /&gt;
The method is called each time the game interface is displayed to a player, ie:&lt;br /&gt;
&lt;br /&gt;
* when the game starts&lt;br /&gt;
* when a player opens a game in the browser later &lt;br /&gt;
* when a player refreshes the game page (F5)&lt;br /&gt;
* when player does a server side Undo&lt;br /&gt;
&lt;br /&gt;
&amp;quot;gamedatas&amp;quot; argument contains all data retrieved by your &amp;quot;getAllDatas&amp;quot; PHP method and some more.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;onEnteringState(stateName: string, args: { args: any } | null): void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
This method is called each time we enter a new game state.&lt;br /&gt;
You can use this method to perform some user interface changes at this moment.&lt;br /&gt;
To access state arguments passed via calling php arg* method use args?.args.&lt;br /&gt;
Typically you would do something only for active player, using this.isCurrentPlayerActive() check.&lt;br /&gt;
It is also called (for the current game state only) when doing a browser refresh (after the setup method is called).&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Warning&#039;&#039;&#039;: for multipleactiveplayer states:&lt;br /&gt;
the active players are NOT active yet so you must use onUpdateActionButtons to perform the client side operation which depends on a player active/inactive status.&lt;br /&gt;
If you are doing initialization of some structures which do not depend on the active player, you can just replace (this.isCurrentPlayerActive()) with (!this.isSpectator) &lt;br /&gt;
for the main switch in that method.&lt;br /&gt;
&lt;br /&gt;
See more details in [[Your_game_state_machine:_states.inc.php#Difference_between_Single_active_and_Multi_active_states]]&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;onLeavingState(stateName: string): void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
This method is called each time we leave a game state.&lt;br /&gt;
You can use this method to perform some user interface changes at this point (i.e. cleanup).&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;onUpdateActionButtons(stateName: string, args: object | null): void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
In this method you can manage &amp;quot;action buttons&amp;quot; that are displayed in the action status bar and highlight active UI elements.&lt;br /&gt;
To access state arguments passed via calling php arg* method use &#039;&#039;&#039;args&#039;&#039;&#039; parameter. Note: args can be null! For &#039;&#039;&#039;game&#039;&#039;&#039; states and when you don&#039;t supply state args function - it is null.&lt;br /&gt;
This method is called when the active or multiactive player changes. In a classic &amp;quot;activePlayer&amp;quot; state this method is called before the onEnteringState state.&lt;br /&gt;
In multipleactiveplayer state it is a mess. The sequencing of calls depends on whether you get into that state from transitions OR from reloading the whole game (i.e. F5).&lt;br /&gt;
&lt;br /&gt;
See more details in [[Your_game_state_machine:_states.inc.php#Difference_between_Single_active_and_Multi_active_states]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Dojo framework ==&lt;br /&gt;
&lt;br /&gt;
BGA uses the [http://dojotoolkit.org/ Dojo Javascript framework].&lt;br /&gt;
&lt;br /&gt;
The Dojo framework allows us to do complex things more easily. The BGA framework uses Dojo extensively.&lt;br /&gt;
&lt;br /&gt;
To implement a game, you only need to use a few parts of the Dojo framework. All the Dojo methods you need are described on this page.&lt;br /&gt;
&lt;br /&gt;
== Javascript minimization (after July 2020) ==&lt;br /&gt;
&lt;br /&gt;
For performance reasons, when deploying a game the javascript code is minimized using &#039;&#039;&#039;terser&#039;&#039;&#039; (https://github.com/terser/terser). This minifier works with modern javascript syntax. From your project &amp;quot;Manage game&amp;quot; page, you can now test a minified version of your javascript on the studio (and revert to the original).&lt;br /&gt;
&lt;br /&gt;
NB: it has been reported that there is an issue with this minifier and percentage values for opacity.&lt;br /&gt;
&lt;br /&gt;
== Accessing Players Information ==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.player_id: number&#039;&#039;&#039;&lt;br /&gt;
id of the player who is looking at the game. The player may not be part of the game (i.e. spectator)&lt;br /&gt;
  if (notif.args.player_id == this.player_id) {&lt;br /&gt;
    ...&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.isSpectator: boolean&#039;&#039;&#039;&lt;br /&gt;
Flag set to true if the user at the table is a spectator (not a player).&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    if (this.isSpectator) {&lt;br /&gt;
        this.player_color = &#039;ffffff&#039;;&lt;br /&gt;
    } else {&lt;br /&gt;
        this.player_color = gamedatas.players[this.player_id].color;&lt;br /&gt;
    }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note: If you want to hide an element from spectators, you should use [[Game_interface_stylesheet:_yourgamename.css#spectatorMode|CSS &#039;spectatorMode&#039; class]].&lt;br /&gt;
&lt;br /&gt;
You may consider making a function like this, to detect if the game is in a read-only state (i.e. non-interactive):&lt;br /&gt;
  // Returns true for spectators, instant replay (during game), archive mode (after game end)&lt;br /&gt;
  isReadOnly: function () {&lt;br /&gt;
    return this.isSpectator || typeof g_replayFrom != &#039;undefined&#039; || g_archive_mode;&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.gamedatas: object&#039;&#039;&#039;&lt;br /&gt;
Contains the initial set of data to init the game, created at game start or by game refresh (F5).&lt;br /&gt;
You can update it as needed to keep an up-to-date reference of the game on the client side if you need it, however most of the time this is unnecessary.&lt;br /&gt;
&lt;br /&gt;
Note: In hotseat mode, the framework does not keep this.gamedatas of hotseat players and shares the same set as the main player to store data.&lt;br /&gt;
&lt;br /&gt;
Note: be careful when you update this data structurally, many framework functions expect data to be certain way and they will break if they see something else.&lt;br /&gt;
&lt;br /&gt;
Typical example of accessing player&#039;s info&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
for (var player_id in this.gamedatas.players) { &lt;br /&gt;
    var playerInfo = this.gamedatas.players [player_id];&lt;br /&gt;
    var c = playerInfo.color;&lt;br /&gt;
    var name = playerInfo.name;&lt;br /&gt;
    // do something &lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.isCurrentPlayerActive(): boolean&#039;&#039;&#039;&lt;br /&gt;
Returns true if the player on whose browser the code is running is currently active (it&#039;s his turn to play). Note: see remarks above about usage of this function inside onEnteringState method.&lt;br /&gt;
  if (this.isCurrentPlayerActive()) ...&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.getActivePlayerId(): number&#039;&#039;&#039;&lt;br /&gt;
Return the ID of the active player, or null if we are not in an &amp;quot;activeplayer&amp;quot; type state.&lt;br /&gt;
  if (this.player_id == this.getActivePlayerId()) ...&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.getActivePlayers(): number[]&#039;&#039;&#039;&lt;br /&gt;
Return an array with the IDs of players who are currently active (or an empty array if there are none).&lt;br /&gt;
&lt;br /&gt;
== Accessing and manipulating the DOM ==&lt;br /&gt;
&lt;br /&gt;
=== Element by Id ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;$(elementId: ElementOrId)&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
The $ function is used to get an HTML element using its &amp;quot;id&amp;quot; attribute.&lt;br /&gt;
&lt;br /&gt;
Example: modify the content of a &amp;quot;span&amp;quot; element:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
In your HTML code:&lt;br /&gt;
   &amp;lt;span id=&amp;quot;a_value_in_the_game_interface&amp;quot;&amp;gt;1234&amp;lt;/span&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In your Javascript code:&lt;br /&gt;
   $(&#039;a_value_in_the_game_interface&#039;).innerHTML = &amp;quot;9999&amp;quot;;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Note: It is safe to use if you don&#039;t know if variable is string (id of element) or element itself, i.e. &lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  foo: function(card) {&lt;br /&gt;
       card = $(card); // now its node, no need to write if (typeof card === &#039;string&#039;) ...&lt;br /&gt;
       // but its good idea to check for null here&lt;br /&gt;
       ...&lt;br /&gt;
  }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;getElementById(elementId: string)&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Note: $() is the standard method to access some HTML element with the BGA Framework. You can use &#039;&#039;&#039;getElementById&#039;&#039;&#039; but it is longer to type and less handy as it does not do some checks.&lt;br /&gt;
&lt;br /&gt;
=== Style ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;dojo.style(node: ElementOrId, styleName: string, styleValue: any): void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
With dojo.style you can modify the CSS property of any HTML element in your interface.&lt;br /&gt;
&lt;br /&gt;
Examples:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
     // Make an element disappear&lt;br /&gt;
     dojo.style( &#039;my_element&#039;, &#039;display&#039;, &#039;none&#039; );&lt;br /&gt;
&lt;br /&gt;
     // Give an element a 2px border&lt;br /&gt;
     dojo.style( &#039;my_element&#039;, &#039;borderWidth&#039;, &#039;2px&#039; );&lt;br /&gt;
&lt;br /&gt;
     // Change the background position of an element&lt;br /&gt;
     // (very practical when you are using CSS sprites to transform an element to another)&lt;br /&gt;
     dojo.style( &#039;my_element&#039;, &#039;backgroundPosition&#039;, &#039;-20px -50px&#039; );&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note: if you have to modify several CSS properties of an element, or if you have a complex CSS transformation to do, you should consider using dojo.addClass/dojo.removeClass (see below).&lt;br /&gt;
&lt;br /&gt;
You can also use object to set multiple values&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
dojo.setStyle(&amp;quot;thinger&amp;quot;, {&lt;br /&gt;
  &amp;quot;opacity&amp;quot;: 0.5,&lt;br /&gt;
  &amp;quot;border&amp;quot;: &amp;quot;3px solid black&amp;quot;,&lt;br /&gt;
  &amp;quot;height&amp;quot;: &amp;quot;300px&amp;quot;&lt;br /&gt;
});&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.addStyleToClass(cssClassName: string, styleName: string, styleValue: any):&#039;&#039;&#039; &#039;&#039;&#039;void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Same as dojo.style(), but for all the nodes set with the specified cssClassName&lt;br /&gt;
Equivalent of &lt;br /&gt;
  &lt;br /&gt;
  dojo.query(`.${aclass}`).style(styleName, styleValue)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
dojo.query(&amp;quot;#baz &amp;gt; div&amp;quot;).style({&lt;br /&gt;
  opacity:0.75,&lt;br /&gt;
  fontSize:&amp;quot;13pt&amp;quot;&lt;br /&gt;
});&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Vanilla JS style&#039;&#039;&#039;&lt;br /&gt;
  $(&#039;my_element&#039;).style.display=&#039;none&#039;; // set&lt;br /&gt;
  var display = $(&#039;my_element&#039;).style.display; // get&lt;br /&gt;
  $(&#039;my_element&#039;).style.removeProperty(&#039;display&#039;); // remove&lt;br /&gt;
&lt;br /&gt;
=== Classes ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;dojo.addClass(node: ElementOrId, classes: string): void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;dojo.removeClass(node: ElementOrId, classes: string): void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;dojo.hasClass(node: ElementOrId, aclass: string): void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;dojo.toggleClass(node: ElementOrId, aclass: string): void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
In many situations, many small CSS property updates can be replaced by a CSS class change (i.e., you add a CSS class to your element instead of applying all modifications manually).&lt;br /&gt;
&lt;br /&gt;
Advantages are:&lt;br /&gt;
* All your CSS stuff remains in your CSS file.&lt;br /&gt;
* You can add/remove a list of CSS modifications with a simple function and without error.&lt;br /&gt;
* You can test whether you applied the CSS to an element with the &#039;&#039;&#039;dojo.hasClass&#039;&#039;&#039; method.&lt;br /&gt;
&lt;br /&gt;
Example from &#039;&#039;Reversi&#039;&#039;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    // We add &amp;quot;possibleMove&amp;quot; to an element&lt;br /&gt;
    dojo.addClass( &#039;square_&#039;+x+&#039;_&#039;+y, &#039;possibleMove&#039; );&lt;br /&gt;
&lt;br /&gt;
    // In our CSS file, the class is defined as:&lt;br /&gt;
    .possibleMove {&lt;br /&gt;
      background-color: white;&lt;br /&gt;
      opacity: 0.2;&lt;br /&gt;
      filter:alpha(opacity=20); /* For IE8 and earlier */  &lt;br /&gt;
      cursor: pointer;  &lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
     // So we&#039;ve applied 4 CSS property changes in one line of code.&lt;br /&gt;
&lt;br /&gt;
     // ... and when we need to check if a square is a possible move on the client side:&lt;br /&gt;
     if( dojo.hasClass( &#039;square_&#039;+x+&#039;_&#039;+y, &#039;possibleMove&#039; ) )&lt;br /&gt;
     { ... }&lt;br /&gt;
&lt;br /&gt;
     // ... and if we want to remove all possible moves in one line of code (see &amp;quot;dojo.query&amp;quot; method):&lt;br /&gt;
     dojo.query( &#039;.possibleMove&#039; ).removeClass( &#039;possibleMove&#039; );&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Vanilla JS classList&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
This is the only exception where dojo versions are better&lt;br /&gt;
  // add class&lt;br /&gt;
  $(token_id).classList.addClass(&#039;possibleMove&#039;);&lt;br /&gt;
  // remove class&lt;br /&gt;
  $(token_id).classList.removeClass(&#039;possibleMove&#039;);&lt;br /&gt;
  // add 2 classes&lt;br /&gt;
  const myclasses = [&#039;a&#039;,&#039;b&#039;];&lt;br /&gt;
  $(token_id).classList.addClass(...myclasses);&lt;br /&gt;
  // add classes to query result&lt;br /&gt;
  document.querySelectorAll(&amp;quot;.hand .card&amp;quot;).forEach((node)=&amp;gt;node.classList.addClass(&#039;possibleMove&#039;));&lt;br /&gt;
&lt;br /&gt;
=== Attributes ===&lt;br /&gt;
&lt;br /&gt;
;dojo.attr&lt;br /&gt;
&lt;br /&gt;
With dojo.attr you can access or change the value of an attribute or property of any HTML element in your interface.&lt;br /&gt;
&lt;br /&gt;
Exemple:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
     // Get the title of a node&lt;br /&gt;
     var title = dojo.attr( id, &#039;title&#039; );&lt;br /&gt;
     // Change the height of a node&lt;br /&gt;
     dojo.attr( &#039;img_growing_tree&#039;, &#039;height&#039;, 100 );&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Vanilla JS attr&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
   $(token).id=new_id; // set attr for &amp;quot;id&amp;quot;&lt;br /&gt;
   var id = $(token).id; // get&lt;br /&gt;
&lt;br /&gt;
=== Queries ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;dojo.query(cssSelector: string): Element[]&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
With dojo.query, you can query a bunch of HTML elements with a single function, with a &amp;quot;CSS selector&amp;quot; style.&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
     // All elements with class &amp;quot;possibleMove&amp;quot;:&lt;br /&gt;
     var elements = dojo.query( &#039;.possibleMove&#039; );&lt;br /&gt;
&lt;br /&gt;
     // Count number of tokens (i.e., elements of class &amp;quot;token&amp;quot;) on the board (i.e., the element with id &amp;quot;board&amp;quot;):&lt;br /&gt;
     dojo.query( &#039;#board .token&#039; ).length;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
But what is really cool with dojo.query is that you can combine it with almost all methods above.&lt;br /&gt;
&lt;br /&gt;
Examples:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
     // Trigger a method when the mouse enter in any element with class &amp;quot;meeple&amp;quot;:&lt;br /&gt;
     dojo.query( &#039;.meeple&#039; ).connect( &#039;onmouseenter&#039;, this, &#039;myMethodToTrigger&#039; );&lt;br /&gt;
&lt;br /&gt;
     // Hide all meeples who are on the board&lt;br /&gt;
     dojo.query( &#039;#board .meeple&#039; ).style( &#039;display&#039;, &#039;none&#039; );&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Vanilla JS query&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
  var cards=document.querySelectorAll(&amp;quot;.hand .card&amp;quot;);// all cards in all hands&lt;br /&gt;
  var cards=$(&#039;hand&#039;).querySelectorAll(&amp;quot;.card&amp;quot;);// all cards in specific hand&lt;br /&gt;
  var card=document.querySelector(&amp;quot;.hand .card&amp;quot;);// first card or null if none (super handy)&lt;br /&gt;
&lt;br /&gt;
=== Creating and Destroying elements ===&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;dojo.empty(node: ElementOrId)&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Remove all children of the node element&lt;br /&gt;
   dojo.empty(&#039;my_hand&#039;);&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;dojo.destroy(node: ElementOrId)&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Remove the element&lt;br /&gt;
   dojo.destroy(&#039;my_token&#039;);&lt;br /&gt;
&lt;br /&gt;
   dojo.query(&amp;quot;.green&amp;quot;, mynode).forEach(dojo.destroy); // this remove all subnode of class green from mynode&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;dojo.create(tag: string, attributes?: obj, parent?: ElementOrId): Element&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Create element&lt;br /&gt;
&lt;br /&gt;
    dojo.create(&amp;quot;div&amp;quot;, { class: &amp;quot;yellow_arrow&amp;quot; }, parent); // this creates div with class yellow_array and places it in &amp;quot;parent&amp;quot;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.format_block(name: string, args: object): string&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
This bga function that takes global var from template file and substitute variables, typical use would be&lt;br /&gt;
&lt;br /&gt;
                var player = gamedatas.players[player_id];&lt;br /&gt;
                var div = this.format_block(&#039;jstpl_player_board&#039;, player ); // var jstpl_player_board = ... is defined in .tpl file &lt;br /&gt;
Note: result is trimmed&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.format_string(name: string, args: object): string&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
This bga function just substitute variables in a string, i.e.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
     var div = this.format_string(&#039;&amp;lt;div color=&amp;quot;${player_color}&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&#039;, {player_color: &#039;#ff0000&#039;} );&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Note: result is trimmed&lt;br /&gt;
&lt;br /&gt;
Note: this can be replaced by using backquoted string now: &lt;br /&gt;
     const player_color =  &#039;#ff0000&#039;;&lt;br /&gt;
&lt;br /&gt;
    const div = ``;&lt;br /&gt;
&#039;&#039;&#039;this.format_string_recursive&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
This bga function is similar to this.format_string but is capable of processing recursive argument structures and translations. It is used to format server notifications.&lt;br /&gt;
&lt;br /&gt;
TODO: find better place for these function docs&lt;br /&gt;
&lt;br /&gt;
=== Moving elements ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;dojo.place(node: string | Element, refNode: ElementOrId, pos?: string | number): Element&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
dojo.place is the best function to insert HTML code somewhere in your game interface without breaking something. It is much better to use than the &#039;&#039;&#039;innerHTML=&#039;&#039;&#039; method if you must insert HTML tags and not only values.&lt;br /&gt;
&lt;br /&gt;
node: can be a string or a DOM node. If it is a string starting with “&amp;lt;”, it is assumed to be an HTML fragment, which will be created. Otherwise it is assumed to be an id of a DOM node. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
     // Insert your HTML code as a child of a container element&lt;br /&gt;
     dojo.place( &amp;quot;&amp;lt;div class=&#039;foo&#039;&amp;gt;&amp;lt;/div&amp;gt;&amp;quot;, &amp;quot;your_container_element_id&amp;quot; );&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
pos: optional argument. Can be a number or one of the following strings: “before”, “after”, “replace”, “only”, “first”, or “last”. If omitted, “last” is assumed.&lt;br /&gt;
&lt;br /&gt;
* &amp;quot;replace&amp;quot;: replace the container element with my_node element&lt;br /&gt;
* &amp;quot;first&amp;quot;: places the node as a child of the reference node. The node is placed as the first child.&lt;br /&gt;
* &amp;quot;last&amp;quot; (default): places the node as a child of the reference node. The node is placed as the last child.&lt;br /&gt;
* &amp;quot;before&amp;quot;: places the node right before the reference node.&lt;br /&gt;
* &amp;quot;after&amp;quot;: places the node right after the reference node.&lt;br /&gt;
* &amp;quot;only&amp;quot;: replaces all children of the reference node with the node.&lt;br /&gt;
&lt;br /&gt;
this parameter can be a positive integer. In this case, the node will be placed as a child of the reference node with this number (counting from 0). If the number is more than number of children, the node will be appended to the reference node making it the last child. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
     // Replace all children of container with my_node &lt;br /&gt;
     dojo.place( $(&#039;my_node&#039;), &amp;quot;your_container_element_id&amp;quot;, &amp;quot;only&amp;quot; );&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
See also full doc on dojo.place: [https://dojotoolkit.org/reference-guide/1.7/dojo/place.html]&lt;br /&gt;
&lt;br /&gt;
Usually, when you want to insert some piece of HTML in your game interface, you should use &amp;quot;[[Game_layout:_view_and_template:_yourgamename.view.php_and_yourgamename_yourgamename.tpl#Javascript_templates|Javascript templates]]&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
But you can also relocate elements like that. Note: it won&#039;t animate if you do that.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.placeOnObject(mobile_obj: ElementOrId, target_obj: ElementOrId): void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
places mobile_obj on target_obj, set the absolute positions and centers the mobile_obj on target_obj,&lt;br /&gt;
effect is immediate&lt;br /&gt;
&lt;br /&gt;
This is not really an animation, but placeOnObject is frequently used before starting an animation.&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  // (We just created an object &amp;quot;my_new_token&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
  // Place the new token on current player board&lt;br /&gt;
  this.placeOnObject( &amp;quot;my_new_token&amp;quot;, &amp;quot;overall_player_board_&amp;quot;+this.player_id );&lt;br /&gt;
  &lt;br /&gt;
  // Then slide it to its position on the board&lt;br /&gt;
  this.slideToObject( &amp;quot;my_new_token&amp;quot;, &amp;quot;a_place_on_board&amp;quot; ).play();&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.placeOnObjectPos(mobile_obj: ElementOrId, target_obj: ElementOrId, target_x: number, target_y: number): void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
This method works exactly like placeOnObject, except than you can specify some (x,y) coordinates (in px). This way, the center of &amp;quot;mobile_obj&amp;quot; will be placed to the specified x,y position relatively to the center of &amp;quot;target_obj&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Note: the placement works differently from this.slideToObjectPos&#039;&#039;, since coordinates are calculated based on the center of objects.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.attachToNewParent(mobile_obj: ElementOrId, target_obj: ElementOrId): void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
With this method, you change the HTML parent of &amp;quot;mobile_obj&amp;quot; element without moving it. &lt;br /&gt;
&amp;quot;target_obj&amp;quot; is the new parent of this element. The beauty of &lt;br /&gt;
attachToNewParent is that the mobile_obj element DOES NOT MOVE during this process.&lt;br /&gt;
&lt;br /&gt;
What happens is that the method calculate a relative position of mobile_obj to make sure it does not move after the HTML parent changes.&lt;br /&gt;
&lt;br /&gt;
Why using this method?&lt;br /&gt;
&lt;br /&gt;
Changing the HTML parent of an element can be useful for the following reasons:&lt;br /&gt;
* When the HTML parent moves, all its child are moving with them. If some game elements is no more linked with a parent HTML object, you may want to attach it to another place.&lt;br /&gt;
* The z_order (vertical order of display) depends on the position in the DOM, so you may need to change the parent of some game elements when they are moving in your game area.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;CAREFUL&#039;&#039;&#039;: this function destroys original object and places a clone onto a new parent, this will break all references to this HTML element (ex: dojo.connect).&lt;br /&gt;
If you need version that does not destroy the object but the same otherwise see [[BGA_Studio_Cookbook#Attach_to_new_parent_without_destroying_the_object]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Animations ==&lt;br /&gt;
&lt;br /&gt;
===Dojo Animations===&lt;br /&gt;
&lt;br /&gt;
BGA animations is based on Dojo Animation ([http://dojotoolkit.org/documentation/tutorials/1.8/animation/ see tutorial here]).&lt;br /&gt;
&lt;br /&gt;
However, most of the time, you can just use methods below, which are built on top of Dojo Animation.&lt;br /&gt;
&lt;br /&gt;
Note: one interesting method from Dojo that could be useful from time to time is &amp;quot;Dojo.Animation&amp;quot;. It allows you to make any CSS property &amp;quot;slide&amp;quot; from one value to another.&lt;br /&gt;
&lt;br /&gt;
Note 2: the slideTo methods are not compatible with CSS transform (scale, zoom, rotate...). If possible, avoid using CSS transform on nodes that are being slided. Eventually, the only possible solution to make these 2 compatible is to disable all CSS transform properties, use slideToObjectPos/placeOnObjectPos, and then apply them again.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Sliding===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.slideToObject(mobile_obj: ElementOrId, target_obj: ElementOrId, duration?: number, delay?: number): Animation&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
You can use slideToObject to &amp;quot;slide&amp;quot; an element to a target position.&lt;br /&gt;
&lt;br /&gt;
Sliding element on the game area is the recommended and the most used way to animate your game interface. Using slides allow players to figure out what is happening on the game, as if they were playing with the real boardgame.&lt;br /&gt;
&lt;br /&gt;
The parameters are:&lt;br /&gt;
* mobile_obj: the ID of the object to move. This object must be &amp;quot;relative&amp;quot; or &amp;quot;absolute&amp;quot; positioned.&lt;br /&gt;
* target_obj: the ID of the target object. This object must be &amp;quot;relative&amp;quot; or &amp;quot;absolute&amp;quot; positioned. Note that it is not mandatory that mobile_obj and target_obj have the same size. If their size are different, the system slides the center of mobile_obj to the center of target_obj.&lt;br /&gt;
* duration: (optional) defines the duration in millisecond of the slide. The default is 500 milliseconds.&lt;br /&gt;
* delay: (optional). If you defines a delay, the slide will start only after this delay. This is particularly useful when you want to slide several object from the same position to the same position: you can give a 0ms delay to the first object, a 100ms delay to the second one, a 200ms delay to the third one, ... this way they won&#039;t be superposed during the slide.&lt;br /&gt;
&lt;br /&gt;
BE CAREFUL: The method returns an dojo.fx animation, so you can combine it with other animation if you want to. It means that you have to call the &amp;quot;play()&amp;quot; method, otherwise the animation WON&#039;T START.&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
   this.slideToObject( &amp;quot;some_token&amp;quot;, &amp;quot;some_place_on_board&amp;quot; ).play();&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.slideToObjectPos(mobile_obj: ElementOrId, target_obj: ElementOrId, target_x: number, target_y: number, duration?: number, delay?: number): Animation&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
This method does exactly the same as &amp;quot;slideToObject&amp;quot;, except than you can specify some (x,y) coordinates. This way, &amp;quot;mobile_obj&amp;quot; will slide to the specified x,y position relatively to &amp;quot;target_obj&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
Example: slide a token to some place on the board, 10 pixels from the top:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
   this.slideToObjectPos( &amp;quot;some_token&amp;quot;, &amp;quot;some_place_on_board&amp;quot;, 0, 10 ).play();&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.slideTemporaryObject(mobile_obj_html: string, parent: ElementOrId, from: ElementOrId, to: ElementOrId, duration?: number, delay?: number): Animation&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
This method is useful when you want to slide a temporary HTML object from one place to another. As this object does not exists before the animation and won&#039;t remain after, it could be complex to create this object (with dojo.place), to place it at its origin (with placeOnObject) to slide it (with slideToObject) and to make it disappear at the end.&lt;br /&gt;
&lt;br /&gt;
slideTemporaryObject does all of this for you:&lt;br /&gt;
* mobile_obj_html is a piece of HTML code that represent the object to slide.&lt;br /&gt;
* parent is the ID of an HTML element of your interface that will be the parent of this temporary HTML object.&lt;br /&gt;
* from is the ID of the origin of the slide.&lt;br /&gt;
* to is the ID of the target of the slide.&lt;br /&gt;
* duration/delay works exactly like in &amp;quot;slideToObject&amp;quot;&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
this.slideTemporaryObject( &#039;&amp;lt;div class=&amp;quot;token_icon&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&#039;, &#039;tokens&#039;, &#039;my_origin_div&#039;, &#039;my_target_div&#039; ).play();&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Destroy===&lt;br /&gt;
&#039;&#039;&#039;this.slideToObjectAndDestroy(mobile_obj: ElementOrId, target_obj: ElementOrId, duration?: number, delay?: number): void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
This method is a handy shortcut to slide an existing HTML object to some place then destroy it upon arrival. It can be used for example to move a victory token or a card from the board to the player panel to show that the player earns it, then destroy it when we don&#039;t need to keep it visible on the player panel.&lt;br /&gt;
&lt;br /&gt;
It works the same as this.slideToObject and takes the same arguments, but it starts the animation. &lt;br /&gt;
&lt;br /&gt;
CAREFUL: Make sure nothing is creating the same object at the same time the animation is running, because this will cause some random disappearing effects&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
this.slideToObjectAndDestroy( &amp;quot;some_token&amp;quot;, &amp;quot;some_place_on_board&amp;quot;, 1000, 0 );&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.fadeOutAndDestroy( node: string | Element, duration?: number, delay?: number):&#039;&#039;&#039; &#039;&#039;&#039;void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
This function fade out the target node, then destroy it. Its starts the animation.&lt;br /&gt;
* duration/delay works exactly like in &amp;quot;slideToObject&amp;quot;&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
   this.fadeOutAndDestroy( &amp;quot;a_card_that_must_disappear&amp;quot; );&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
CAREFUL: the HTML node still exists until during few milliseconds, until the fadeOut has been completed.&lt;br /&gt;
Make sure nothing is creating same object at the same time as animation is running, because you will be some random dissapearing effects&lt;br /&gt;
&lt;br /&gt;
===Rotating elements===&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
This example combines &amp;quot;Dojo.Animation&amp;quot; method and a CSS property transform that allow you to rotate the element.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
// node is Element we rotating&lt;br /&gt;
		    var animation = new dojo.Animation({&lt;br /&gt;
			    curve: [fromDegree, toDegree],&lt;br /&gt;
			    onAnimate: (v) =&amp;gt; {&lt;br /&gt;
				    node.style.transform = &#039;rotate(&#039; + v + &#039;deg)&#039;;&lt;br /&gt;
			    } &lt;br /&gt;
		    });&lt;br /&gt;
		    &lt;br /&gt;
		    animation.play();  &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
BGA has its own interface to rotate&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.rotateTo(node: string | Element, degree: number): void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
It starts the animation, and stored the rotation degree in the class, so next time you rotate object - it is additive.&lt;br /&gt;
There is no animation hooks in this one, if you need to change any parameters use dojo animation above.&lt;br /&gt;
&lt;br /&gt;
There is also &#039;&#039;&#039;rotateInstantTo&#039;&#039;&#039; with same signature which does not animate&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Animation Callbacks===&lt;br /&gt;
&lt;br /&gt;
If you wish to run some code only after an animation has completed you can do this by linking a callback method to &#039;onEnd&#039;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
var animation_id = this.slideToObject( mobile_obj, target_obj, 500 );&lt;br /&gt;
dojo.connect(animation_id, &#039;onEnd&#039;, () =&amp;gt; {&lt;br /&gt;
   // do something here&lt;br /&gt;
});&lt;br /&gt;
animation_id.play();&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If you wish to call a second animation after the first (rather than general code) then you can use a dojo animation chain (see tutorial referenced above).&lt;br /&gt;
&lt;br /&gt;
== Players input ==&lt;br /&gt;
&lt;br /&gt;
=== Connecting ===&lt;br /&gt;
&#039;&#039;&#039;dojo.connect(element: Element, event: string, context: object, method: eventHandler): any&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;dojo.connect(element: Element, event: string, handler: eventHandler): any&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Used to associate a player event with one of your notification methods.&lt;br /&gt;
&lt;br /&gt;
Example: associate a click on an element (&amp;quot;my_element&amp;quot;) with one of our methods (&amp;quot;onClickOnMyElement&amp;quot;):&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
      dojo.connect( $(&#039;my_element&#039;), &#039;onclick&#039;, this, &#039;onClickOnMyElement&#039; );&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Same idea but based on query (i.e. all element of &#039;pet&#039; class)&lt;br /&gt;
      dojo.query(&amp;quot;.pet&amp;quot;).connect(&#039;onclick&#039;, this, &#039;onPet&#039;);&lt;br /&gt;
&lt;br /&gt;
Note: if you need to disconnect the handler you have to store handler returned from this method, i.e.&lt;br /&gt;
   &lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    var handler = dojo.connect(...);&lt;br /&gt;
    ...&lt;br /&gt;
    dojo.disconnect(handler);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If you don&#039;t store the handler - you have to destroy the object to disconnect it&lt;br /&gt;
&lt;br /&gt;
Typical function that implements the input handler will look like this&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
onPet: function(event) {&lt;br /&gt;
    var id = event.currentTarget.id;&lt;br /&gt;
    console.log(&#039;onPet &#039; + id);&lt;br /&gt;
    dojo.stopEvent(event);&lt;br /&gt;
    if (this.gamedatas.gamestate.name == &#039;playerTurnPet&#039;) {&lt;br /&gt;
          this.bgaPerformAction(&#039;actPlayPet&#039;, {card: id});&lt;br /&gt;
    } else {&lt;br /&gt;
          this.showMoveUnauthorized();&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.connect(element: ElementOrId, event: string, method: eventHandler): void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Used to associate a player event with one of your notification methods.&lt;br /&gt;
&lt;br /&gt;
      this.connect( $(&#039;my_element&#039;), &#039;onclick&#039;, &#039;onClickOnMyElement&#039; );&lt;br /&gt;
&lt;br /&gt;
Or you can use an in-place handler&lt;br /&gt;
&lt;br /&gt;
      this.connect( $(&#039;my_element&#039;), &#039;onclick&#039;, (e) =&amp;gt; { console.log(&#039;boo&#039;); } );&lt;br /&gt;
&lt;br /&gt;
Note that this function stores the connection handler. That is the only real difference between &#039;&#039;&#039;this.connect&#039;&#039;&#039; and &#039;&#039;&#039;dojo.connect&#039;&#039;&#039;. If you plan to destroy the element you connected, you &#039;&#039;&#039;must&#039;&#039;&#039; call this.disconnect() to prevent memory leaks.&lt;br /&gt;
This function is mainly for permanent objects - if you just want to connect the temp object you should probably not use this method but use dojo.connect which won&#039;t require any clean-up.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.connectClass(cssClassName: string, event: string, method: eventHandler): void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Same as connect(), but for all the nodes set with the specified cssClassName.&lt;br /&gt;
 this.connectClass(&#039;pet&#039;, &#039;onclick&#039;, &#039;onPet&#039;);&lt;br /&gt;
&#039;&#039;&#039;this.disconnect(element: ElementOrId, event: string): void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Disconnect event handler (previously registered with this.connect or this.connectClass).&lt;br /&gt;
&lt;br /&gt;
   this.disconnect( $(&#039;my_element&#039;), &#039;onclick&#039;);&lt;br /&gt;
&lt;br /&gt;
Note: dynamic connect/disconnect is for advanced cases ONLY, you should always connect elements statically if possible, i.e. in setup() method.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.disconnectAll(): void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Disconnect all previously registed event handlers (registered via this.connect or this.connectClass)&lt;br /&gt;
&lt;br /&gt;
  this.disconnectAll();&lt;br /&gt;
&lt;br /&gt;
=== Actions ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.bgaPerformAction(action: string, args?: object, options: object = { lock: true, checkAction: true }): Promise&amp;lt;void&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Triggers an action on the backend. This is a combination of checkAction and ajaxcall, returning a Promise which resoves when ajaxcall ends.&lt;br /&gt;
&lt;br /&gt;
This method must be used to send a player input to the game server. &#039;&#039;&#039;It should not be triggered programmatically&#039;&#039;&#039;, especially not in loops, in callbacks, in notifications, or in onEnteringState/onUpdateActionButtons/onLeavingState, in order not to create race conditions or break replay game and tutorial features. It should be used only in reaction to a user action in the interface.&lt;br /&gt;
&lt;br /&gt;
* action: name of the action, as it is written in &amp;quot;possibleactions&amp;quot; of the current state.&lt;br /&gt;
* args: an object containing the call parameters to send to the action&lt;br /&gt;
* options: options to tweak the call with some defaults. Default is &amp;lt;code&amp;gt;{ lock: true, checkAction: true }&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Example of a standard call without args:&lt;br /&gt;
  this.bgaPerformAction(&#039;pass&#039;);&lt;br /&gt;
&lt;br /&gt;
Example of a standard call with action args:&lt;br /&gt;
  this.bgaPerformAction(&#039;actPlayCard&#039;, { id: this.selectedCardId });&lt;br /&gt;
&lt;br /&gt;
Example of a call without checking action (because player is inactive in a multiactive state):&lt;br /&gt;
&lt;br /&gt;
 this.bgaPerformAction(&#039;actChangeMind&#039;, {}, { checkAction: false });&lt;br /&gt;
&lt;br /&gt;
Example of a call without lock (because of a special action not directly related to the game flow):&lt;br /&gt;
&lt;br /&gt;
 this.bgaPerformAction(&#039;actSetAutoBid&#039;, { alwaysBidUntil: 500 }, { lock: false, checkAction: false });&lt;br /&gt;
&lt;br /&gt;
Example of call with reaction to exception:&lt;br /&gt;
  this.bgaPerformAction(&#039;actPlayCard&#039;, { id: this.selectedCardId }).catch(()=&amp;gt;{ this.selectedCardId = undefined; });&lt;br /&gt;
&lt;br /&gt;
Example of call with reaction to success:&lt;br /&gt;
  this.bgaPerformAction(&#039;actPlayCard&#039;, { id: this.selectedCardId }).then(()=&amp;gt;{ this.unselectAll(); });&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.ajaxcall(url, parameters, obj_callback, callback, callback_anycase?, ajax_method?: string)&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Note: bgaPerformAction is a simpler way to use ajax calls, ajaxcall stays in the doc for legacy reasons only and should not be used in new projects.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Same warning as &#039;&#039;&#039;this.bgaPerformAction&#039;&#039;&#039; about using on user action only.&lt;br /&gt;
&lt;br /&gt;
* url: the url of the action to perform. For a game, it must be: &amp;quot;/&amp;lt;mygame&amp;gt;/&amp;lt;mygame&amp;gt;/myAction.html&amp;quot;&lt;br /&gt;
* parameters: an array of parameter to send to the game server. &lt;br /&gt;
** Note that &amp;quot;lock: true&amp;quot; must always be specified in this list of parameters in order the interface can be locked during the server call. Cannot use lock: false - to not lock it has to be undefined.&lt;br /&gt;
** Note: Restricted parameter names (please don&#039;t use them):&lt;br /&gt;
*** &amp;quot;action&amp;quot;&lt;br /&gt;
*** &amp;quot;module&amp;quot;&lt;br /&gt;
*** &amp;quot;class&amp;quot;&lt;br /&gt;
* obj_callback: must be set to &amp;quot;this&amp;quot;.&lt;br /&gt;
* callback (non-optional but rarely used): a function to trigger when the server returns result and everything went fine (not used, as all data handling is done via notifications).&lt;br /&gt;
* callback_anycase: (optional) a function to trigger when the server returns ok OR error.  If no error this function is called with parameter value false. If an error occurred, the first parameter will be set to true, the second will contain the error message sent by the PHP back-end, and the third will contain an error code.&lt;br /&gt;
* ajax_method: (optional and rarely used) if you need to send large amounts of data (over 2048 bytes), you can set this parameter to &#039;post&#039; (all lower-case) to send a POST request as opposed to the default GET. This works, but was not officially documented, so only use if you really need to.&lt;br /&gt;
&lt;br /&gt;
Usage:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
this.ajaxcall( &#039;/mygame/mygame/actMyAction.html&#039;, { lock: true, &lt;br /&gt;
   arg1: myarg1, &lt;br /&gt;
   arg2: myarg2&lt;br /&gt;
}, this, (result)=&amp;gt;{} );&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.checkAction(action: string, nomessage?: boolean): boolean &#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Check if player can do the specified action by taking into account:&lt;br /&gt;
* if interface is locked it will return false and show message &amp;quot;An action is already in progress&amp;quot;,  unless nomessage set to true &lt;br /&gt;
* if player is not active it will return false and show message &amp;quot;This is not your turn&amp;quot;, unless nomessage set to true &lt;br /&gt;
* if action is not in list in possible actions (defined by &amp;quot;possibleaction&amp;quot; in current game state) it will return false and show &amp;quot;This move is not authorized now&amp;quot; error (unconditionally).&lt;br /&gt;
* otherwise returns true&lt;br /&gt;
Example:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  function onClickOnGameElement( evt )  {&lt;br /&gt;
     if( this.checkAction( &amp;quot;actMyAction&amp;quot; ) ) {&lt;br /&gt;
        // Do the action&lt;br /&gt;
     }&lt;br /&gt;
  }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.checkPossibleActions(action: string): boolean&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
* this is independent of the player being active, so can be used instead of this.checkAction(). This is particularly useful for multiplayer states when the player is not active in a &#039;player may like to change their mind&#039; scenario. Unlike this.checkAction, this function does NOT take interface locking into account &lt;br /&gt;
&lt;br /&gt;
* if action is not in list in possible actions (defined by &amp;quot;possibleaction&amp;quot; in current game state) it will return false and show &amp;quot;This move is not authorized now&amp;quot; error (unconditionally).&lt;br /&gt;
* otherwise returns true&lt;br /&gt;
&lt;br /&gt;
  function onChangeMyMind( evt )  {&lt;br /&gt;
     if( this.checkPossibleActions( &amp;quot;actMyAction&amp;quot; ) ) {&lt;br /&gt;
        // Do the action&lt;br /&gt;
     }&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.checkLock(nomessage?: boolean): boolean&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
When using &amp;quot;lock: true&amp;quot; in ajax call you can use this function to check if interface is in lock state (it will be locked during server call and notification processing).&lt;br /&gt;
This check can be used to block some other interactions which do not result in ajaxcall or if you want to suppress errors. Note: normally you only need to use this.checkAction(...), this is for advanced cases.&lt;br /&gt;
&lt;br /&gt;
It will also show error unless nomessage is set to true&lt;br /&gt;
&lt;br /&gt;
  function onChangeMyMind( evt )  {&lt;br /&gt;
     if( this.checkLock() ) {&lt;br /&gt;
        // Do the action&lt;br /&gt;
     }&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
== Notifications ==&lt;br /&gt;
&lt;br /&gt;
When something happens on the server side, your game interface Javascript logic received a notification.&lt;br /&gt;
If you have not done so yet check what notification are in [[Main_game_logic:_yourgamename.game.php#Notifications]]&lt;br /&gt;
&lt;br /&gt;
Here&#039;s how you can handle these notifications on the client side.&lt;br /&gt;
&lt;br /&gt;
=== Subscribe to notifications ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;dojo.subscribe(notif_type: string, callback_obj: Object, handler: string|handler)&#039;&#039;&#039;&lt;br /&gt;
* notif_type - notification type/name send by php server&lt;br /&gt;
* callback_obj - usually this&lt;br /&gt;
* handler - if string method of callback_obj with name name is called, when notification is called, with notification object as parameter (see below)&lt;br /&gt;
&lt;br /&gt;
Your Javascript &amp;quot;setupNotifications&amp;quot; method is the place where you can subscribe to notifications from your PHP code.&lt;br /&gt;
&lt;br /&gt;
Here&#039;s how you associate one of your Javascript method to a notification &amp;quot;playDisc&amp;quot; (from Reversi example):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
   setupNotifications: function() {&lt;br /&gt;
      ...&lt;br /&gt;
      dojo.subscribe(&#039;playDisc&#039;, this, &amp;quot;notif_playDisc&amp;quot;);&lt;br /&gt;
   },&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note: the &amp;quot;playDisc&amp;quot; corresponds to the name of the notification you define it in your PHP code, in your &amp;quot;notifyAllPlayers&amp;quot; or &amp;quot;notifyPlayer&amp;quot; method.&lt;br /&gt;
&lt;br /&gt;
Then, you have to define your &amp;quot;notif_playDisc&amp;quot; method:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
   notif_playDisc: function(notif) {&lt;br /&gt;
     // Remove current possible moves (makes the board more clear)&lt;br /&gt;
     dojo.query( &#039;.possibleMove&#039; ).removeClass( &#039;possibleMove&#039; );          &lt;br /&gt;
     this.addDiscOnBoard( notif.args.x, notif.args.y, notif.args.player_id );&lt;br /&gt;
   },&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In a notification handler like our &amp;quot;notif_playDisc&amp;quot; method, you can access all notifications arguments with &amp;quot;notif.args&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&lt;br /&gt;
PHP&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    $this-&amp;gt;notifyAllPlayers( &amp;quot;apples&amp;quot;, clienttranslate(&#039;player takes ${count} apples&#039;), [ &amp;quot;count&amp;quot; =&amp;gt; 3 ] );&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
JavaScript&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    setupNotifications: function() {&lt;br /&gt;
       dojo.subscribe( &#039;apples&#039;, this, &#039;notif_apples&#039; );&lt;br /&gt;
    },&lt;br /&gt;
&lt;br /&gt;
    notif_apples: function(notif) {&lt;br /&gt;
      //You can access the &amp;quot;count&amp;quot; like this:&lt;br /&gt;
       alert(&amp;quot;count = &amp;quot; + notif.args.count);&lt;br /&gt;
    }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== The notification Object received by client ===&lt;br /&gt;
&lt;br /&gt;
When sending a notification on your PHP, the client side will receive an Object with the following attributes:&lt;br /&gt;
&lt;br /&gt;
* type - type of the notification (as passed by php function)&lt;br /&gt;
* log - the log string passed from php notification&lt;br /&gt;
* args - This is the arguments that you passed on your notification method on php&lt;br /&gt;
* bIsTableMsg - is true when you use [[Main_game_logic:_yourgamename.game.php#NotifyAllPlayers|NotifyAllPlayers]] method (false otherwise)&lt;br /&gt;
* channelorig - information about table ID (formatted as : &amp;quot;/table/t[TABLE_NUMBER]&amp;quot;)&lt;br /&gt;
* gamenameorig - name of the game&lt;br /&gt;
* move_id - ID of the move associated with the notification&lt;br /&gt;
* table_id - ID of the table (comes as string)&lt;br /&gt;
* time - UNIX GMT timestamp&lt;br /&gt;
* uid - unique identifier of the notification&lt;br /&gt;
* h - unknown&lt;br /&gt;
&lt;br /&gt;
&#039;&#039; Note that those information were inferred from observation on console log. If an Admin can confirm/correct (and remove this line), you&#039;re welcome :)&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
=== Ignoring notifications ===&lt;br /&gt;
&lt;br /&gt;
Sometimes you need to ignore some notification on client side. You don&#039;t want them to be shown in game log and you don&#039;t want them to be handled.&lt;br /&gt;
&lt;br /&gt;
The most common use case is when a player gets private information. They will receive a specific notification (such as &amp;quot;You received Ace of Heart&amp;quot;), while other players would receive more generic notification (&amp;quot;Player received a card&amp;quot;).&lt;br /&gt;
&lt;br /&gt;
In X.game.php&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        $this-&amp;gt;notifyAllPlayers(&amp;quot;dealCard&amp;quot;, clienttranslate(&#039;${player_name} received a card&#039;), [&lt;br /&gt;
            &#039;player_id&#039; =&amp;gt; $playerId,&lt;br /&gt;
            &#039;player_name&#039; =&amp;gt; $this-&amp;gt;getActivePlayerName()&lt;br /&gt;
        ]);&lt;br /&gt;
&lt;br /&gt;
        $this-&amp;gt;notifyPlayer($playerId, &amp;quot;dealCardPrivate&amp;quot;, clienttranslate(&#039;You received ${cardName}&#039;), [&lt;br /&gt;
            &amp;quot;type&amp;quot; =&amp;gt; $card[&amp;quot;type&amp;quot;],&lt;br /&gt;
            &amp;quot;cardName&amp;quot; =&amp;gt; $this-&amp;gt;getCardName($card[&amp;quot;type&amp;quot;])&lt;br /&gt;
        ]);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The problem with this approach is that the active player will receive two notifications:&lt;br /&gt;
* Player1 received a card&lt;br /&gt;
* You received Ace of Hearts&lt;br /&gt;
&lt;br /&gt;
Hence, notification ignoring.&lt;br /&gt;
&lt;br /&gt;
NOTE: You can think that it would be possible to send such notification to all players except active just by using notifyPlayer and it seems to work. The problem however is that table spectators would miss such notification and their user interface (and game log) wouldn&#039;t be updated. Since there is no way to send notification just to spectators, ignoring the notification (or &amp;quot;filtering&amp;quot;) is the only reasonable solution.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;setIgnoreNotificationCheck(notif_type: string, predicate: ((notif: Notif)=&amp;gt;boolean))&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
This method will set a check whether any of notifications of specific type should be ignored.&lt;br /&gt;
&lt;br /&gt;
The parameters are:&lt;br /&gt;
* notif_type: type of the notification &lt;br /&gt;
* predicate (notif =&amp;gt; boolean): a function that will receive notif object and will return true if this specific notification should be ignored&lt;br /&gt;
&lt;br /&gt;
Before dispatching any notification of this type, the framework will call predicate to check whether notification should be ignored, if it return true - the notification will be dispatched, i.e. logged or handled.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    this.notifqueue.setIgnoreNotificationCheck( &#039;dealCard&#039;, (notif) =&amp;gt; (notif.args.player_id == this.player_id) );&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
IMPORTANT: Remember that this notification is ignored on the client side, but was still received by the client. Therefore it shouldn&#039;t contain any private information as cheaters can get it. In other words this is not a way to hide information.&lt;br /&gt;
&lt;br /&gt;
IMPORTANT: When a game is reloaded with F5 or when opening a turn based game, old notifications are replayed as history notification. They are used just to update the game log and are stripped of all arguments except player_id, i18n and any argument present in message. If you use and other argument in your predicate you should &#039;&#039;&#039;preserve&#039;&#039;&#039; it as explained [[Main_game_logic:_yourgamename.game.php#Notify_players|here]].&lt;br /&gt;
&lt;br /&gt;
=== Synchronous notifications ===&lt;br /&gt;
&lt;br /&gt;
When several notifications are received by your game interface, these notifications are processed immediately, one after the other, in the same exact order they have been generated in your PHP game logic.&lt;br /&gt;
&lt;br /&gt;
However, sometimes, you need to give some time to the players to figure out what happened on the game before jumping to the next notification. Indeed, in many games, there are a lot of automatic actions, and the computer is going to resolve all these actions very fast if you don&#039;t tell it not to do so.&lt;br /&gt;
&lt;br /&gt;
As an example, for Reversi, when someone is playing a disc, we want to wait 500 milliseconds before doing anything else in order the opponent player can figure out what move has been played.&lt;br /&gt;
&lt;br /&gt;
Here&#039;s how we do this, right after our subscription:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    dojo.subscribe( &#039;playDisc&#039;, this, &amp;quot;notif_playDisc&amp;quot; );&lt;br /&gt;
    this.notifqueue.setSynchronous( &#039;playDisc&#039;, 500 );   // Wait 500 milliseconds after executing the playDisc handler&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
-----&lt;br /&gt;
&lt;br /&gt;
It is also possible to control the delay timing dynamically (e.g., using notification args). As an example, maybe your notification &#039;cardPlayed&#039; should pause for a different amount of time depending on the number or type of cards played.&lt;br /&gt;
&lt;br /&gt;
For this case, use &#039;&#039;&#039;setSynchronous&#039;&#039;&#039; without specifying the duration and use &#039;&#039;&#039;setSynchronousDuration&#039;&#039;&#039; within the notification callback.&lt;br /&gt;
&lt;br /&gt;
* NOTE: If you forget to invoke &#039;&#039;&#039;setSynchronousDuration&#039;&#039;&#039;, the game will remain paused forever!&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
setupNotifications: function () {&lt;br /&gt;
    dojo.subscribe( &#039;cardPlayed&#039;, this, &#039;notif_cardPlayed&#039; );&lt;br /&gt;
    this.notifqueue.setSynchronous( &#039;cardPlayed&#039; ); // wait time is dynamic&lt;br /&gt;
    ...&lt;br /&gt;
},&lt;br /&gt;
&lt;br /&gt;
notif_cardPlayed: function (notif) {&lt;br /&gt;
    // MUST call setSynchronousDuration&lt;br /&gt;
&lt;br /&gt;
    // Example 1: From notification args (PHP)&lt;br /&gt;
    this.notifqueue.setSynchronousDuration(notif.args.duration);&lt;br /&gt;
    ...&lt;br /&gt;
&lt;br /&gt;
    // Or, example 2: Match the duration to a Dojo animation&lt;br /&gt;
    var anim = dojo.fx.combine([&lt;br /&gt;
        ...&lt;br /&gt;
    ]);&lt;br /&gt;
    anim.play();&lt;br /&gt;
    this.notifqueue.setSynchronousDuration(anim.duration);&lt;br /&gt;
},&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You can also manually call this.notifqueue.setSynchronousDuration(0) once client operations are finished, but be careful that even fast replay still has a path to call it.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;WARNING: combining synchronous and ignored notifications&#039;&#039;&#039;&lt;br /&gt;
You must be careful when combining dynamic synchronous durations (as described above) with ignored notifications. If you have a conditionally ignored notification like this (see below section):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;this.notifqueue.setIgnoreNotificationCheck( &#039;myNotif&#039;, (notif) =&amp;gt; (notif.args.player_id == this.player_id) /* or any other condition */ )&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
then you CANNOT do&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;this.notifqueue.setSynchronous(&#039;myNotif&#039;);&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
as, when the ignored check passes, the notification handler, in which `this.notifqueue.setSychronousDuration` is called, is never called and so the duration is never set and interface locking results.&lt;br /&gt;
&lt;br /&gt;
The workaround is to set a &amp;quot;dummy&amp;quot; time:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;this.notifqueue.setSynchronous(&#039;myNotif&#039;, 5000);&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
whose value is irrelevant but must be large enough to cover the time before the notification handler is called. The large value never actually comes into play because the notification is either ignored, or the synchronous duration is reset to a sensible value inside the handler.&lt;br /&gt;
&lt;br /&gt;
=== Pre-defined notification types ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;tableWindow&#039;&#039;&#039; - This defines notification to display [[Game_interface_logic:_yourgamename.js#Scoring_dialogs|Scoring Dialogs]], see below.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;message&#039;&#039;&#039; - This defines notification that shows on players log and have no other effect (technically any unhandled notification will do the same but its recommended to use this keyword for consistency)&lt;br /&gt;
&lt;br /&gt;
   // You can call this on php side without doing anything on client side&lt;br /&gt;
    self::notifyAllPlayers( &#039;message&#039;, clienttranslate(&#039;hello&#039;), [] );&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;simplePause&#039;&#039;&#039; - This notification will just delay other notifications, maybe useful if you know you need some extra time for animation or something. Requires a time parameter.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    self::notifyAllPlayers( &#039;simplePause&#039;, &#039;&#039;, [ &#039;time&#039; =&amp;gt; 500] ); // time is in milliseconds&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note: the following types are RESERVED by framework, do not use:&lt;br /&gt;
&lt;br /&gt;
gameStateChange gameStateChangePrivateArg gameStateMultipleActiveUpdate newActivePlayer playerstatus yourturnack clockalert tableInfosChanged playerEliminated tableDecision  archivewaitingdelay end_archivewaitingdelay replaywaitingdelay end_replaywaitingdelay replayinitialwaitingdelay end_replayinitialwaitingdelay aiPlayerWaitingDelay replay_has_ended updateSpectatorList  wouldlikethink updateReflexionTime undoRestorePoint resetInterfaceWithAllDatas zombieModeFail zombieModeFailWarning aiError skipTurnOfPlayer zombieBack allPlayersAreZombie gameResultNeutralized playerConcedeGame showTutorial showCursor showCursorClick skipTurnOfPlayerWarning  banFromTable resultsAvailable switchToTurnbased newPrivateState infomsg&lt;br /&gt;
&lt;br /&gt;
== Tooltips ==&lt;br /&gt;
&lt;br /&gt;
=== Adding static tooltips ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.addTooltip(nodeId: string, helpStringTranslated: string, actionStringTranslated: string, delay?: number): void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Add a simple text tooltip to the DOM node.&lt;br /&gt;
&lt;br /&gt;
Specify &#039;helpStringTranslated&#039; to display some information about &amp;quot;what is this game element?&amp;quot;.&lt;br /&gt;
Specify &#039;actionStringTranslated&#039; to display some information about &amp;quot;what happens when I click on this element?&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
You must specify both of the strings. You can only use one and specify an empty string (&#039;&#039;) for the other one.&lt;br /&gt;
&lt;br /&gt;
When you pass text directly function _() must be used for the text to be marked for translation! Except for empty string.&lt;br /&gt;
&lt;br /&gt;
Parameter &amp;quot;delay&amp;quot; is optional. It is primarily used to specify a zero delay for some game element when the tooltip gives really important information for the game - but remember: no essential information must be placed in tooltips as they won&#039;t be displayed in some browsers (see [[BGA_Studio_Guidelines|Guidelines]]).&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
   this.addTooltip( &#039;cardcount&#039;, _(&#039;Number of cards in hand&#039;), &#039;&#039; );&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note: this generates static tooltip and attaches to existing dom element, if you need to generate tooltip more dynamically you have to call that method every time information about object is updated or use completely different tehnique, see dynamic tooltips below.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.addTooltipHtml(nodeId: string, html: string, delay?: number): void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Add an HTML tooltip to the DOM node (for more elaborate content such as presenting a bigger version of a card).&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.addTooltipToClass(cssClass: string, helpStringTranslated: string, actionStringTranslated: string, delay?: number ): void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Add a simple text tooltip to all the DOM nodes set with this cssClass. See more details above for this.addTooltip.&lt;br /&gt;
     this.addTooltipToClass( &#039;meeple&#039;, _(&#039;This is A Meeple&#039;), _(&#039;Click to tickle&#039;) );&lt;br /&gt;
&lt;br /&gt;
IMPORTANT: all concerned nodes must exist and have IDs to get tooltips.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.addTooltipHtmlToClass(cssClass: string, html: string, delay?: number): void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Add an HTML tooltip to to all the DOM nodes set with this cssClass (for more elaborate content such as presenting a bigger version of a card).&lt;br /&gt;
&lt;br /&gt;
IMPORTANT: all concerned nodes must exist and have IDs to get tooltips.&lt;br /&gt;
&lt;br /&gt;
=== Removing static tooltips ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.removeTooltip(nodeId: string): void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Remove a tooltip from the DOM node with given id.&lt;br /&gt;
&lt;br /&gt;
=== Advanced tooltips ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;force tooltip to open&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
If you want to force tooltip to open in reaction to some other action, i.e. click you can do this&lt;br /&gt;
&lt;br /&gt;
   this.tooltips[id].open(id)&lt;br /&gt;
&lt;br /&gt;
where id is the id of the tooltip node where tooltip was installed.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;dynamic tooltips&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
See [[BGA_Studio_Cookbook#Dynamic_tooltips]]&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;tooltips on mobile&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Tooltips is very unreliable on mobile, it is recommended to implement some other method to obtaining same information,&lt;br /&gt;
such as simple click handler in dedicated &amp;quot;Help&amp;quot; mode or provide dedicated clickable areas such as corner of card.&lt;br /&gt;
&lt;br /&gt;
== Warning messages ==&lt;br /&gt;
&lt;br /&gt;
Sometimes, there is something important that is happening in the game and you have to make sure all players get the message. Most of the time, the evolution of the game situation or the game log is enough, but sometimes you need something more visible.&lt;br /&gt;
&lt;br /&gt;
Ex: someone fulfills one of the end of the game conditions, so this is the last turn.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.showMessage(msg: string, type: string): void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
showMessage shows a message in a big rectangular area on the top of the screen of the current player, and it dissapears after few seconds (also it will be in the log in some cases).&lt;br /&gt;
&lt;br /&gt;
* &amp;quot;msg&amp;quot; is the string to display. It should be translated.&lt;br /&gt;
* &amp;quot;type&amp;quot; can be set to &amp;quot;info&amp;quot;, &amp;quot;error&amp;quot;, &amp;quot;only_to_log&amp;quot; or custom string. If set to &amp;quot;info&amp;quot;, the message will be an informative message on a white background. If set to &amp;quot;error&amp;quot;, the message will be an error message on a red background and it will be added to log. If set to &amp;quot;only_to_log&amp;quot;, the message will be added to the game log but will not popup at the top of the screen.&lt;br /&gt;
If set to custom string, it will be transparent, to use custom type define &amp;quot;head_xxx&amp;quot; in css, where xxx is the type. For example if you want yellow warning, use &amp;quot;warning&amp;quot; as type and add this to css:&lt;br /&gt;
 .head_warning {&lt;br /&gt;
    background-color: #e6c66e;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
Important: the normal way to inform players about the progression of the game is the game log. The &amp;quot;showMessage&amp;quot; is intrusive and should not be used often.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    notif_messageinfo: function(notif) {&lt;br /&gt;
	if (!g_archive_mode) {&lt;br /&gt;
        	var message = this.format_string_recursive(notif.log, notif.args);&lt;br /&gt;
		this.showMessage(_(&#039;Announcement:&#039;) + &amp;quot; &amp;quot; + message, &#039;info&#039;);		&lt;br /&gt;
         }&lt;br /&gt;
    },&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Show message could be used on the client side to prevent user wrong moves before it is send to server.&lt;br /&gt;
Example from &#039;battleship&#039;:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
onGrid: function(event) {&lt;br /&gt;
     if (checkIfPlayerTriesToFireOnThemselves(event)) {&lt;br /&gt;
        this.showMessage(_(&#039;This is your own board silly!&#039;), &#039;error&#039;);&lt;br /&gt;
        return;&lt;br /&gt;
     }&lt;br /&gt;
     ...&lt;br /&gt;
},&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.showMoveUnauthorized(): void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Shows predefined user error that move is unauthorized now&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
onPet: function(event) {&lt;br /&gt;
     if (checkPet(event)==false) {&lt;br /&gt;
        this.showMoveUnauthorized();&lt;br /&gt;
        return;&lt;br /&gt;
     }&lt;br /&gt;
     ...&lt;br /&gt;
},&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Dialogs ==&lt;br /&gt;
&lt;br /&gt;
=== Confirmation dialog ===&lt;br /&gt;
&lt;br /&gt;
When an important action with a lot of consequences is triggered by the player, you may want to propose a confirmation dialog.&lt;br /&gt;
&lt;br /&gt;
CAREFUL: the general guideline of BGA is to AVOID the use of confirmation dialogs. Confirmation dialogs slow down the game and bother players. The players know that they have to pay attention to each move when they are playing online.&lt;br /&gt;
&lt;br /&gt;
The situations where you should use a confirmation dialog are the following:&lt;br /&gt;
* It must not happen very often during a game.&lt;br /&gt;
* It must be linked to an action that can really &amp;quot;kill a game&amp;quot; if the player does not pay attention.&lt;br /&gt;
* It must be something that can be done by mistake (ex: a link on the action status bar).&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.confirmationDialog(message: string, yesHandler: (param: any) =&amp;gt; void, noHandler?: (param: any) =&amp;gt; void, param?: any): void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
* message - message will be shown to user, use _() to translate&lt;br /&gt;
* yesHandler - non-optional handler to be called on yes&lt;br /&gt;
* noHandler - optional handler to called on no&lt;br /&gt;
* param - if specified, it will be passed to both handlers&lt;br /&gt;
NOTE: this is async function, it does not return anything and you should not do anything after, you must do everything in handlers&lt;br /&gt;
&lt;br /&gt;
How to display a confirmation dialog:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    this.confirmationDialog(_(&amp;quot;Are you sure you want to bake a pie?&amp;quot;), () =&amp;gt; {&lt;br /&gt;
      this.bakeThePie();&lt;br /&gt;
    });&lt;br /&gt;
    return; // nothing should be called or done after calling this, all action must be done in the handler&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
With param and both handlers&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    this.confirmationDialog(_(&amp;quot;Are you sure you want to bake a pie?&amp;quot;), &lt;br /&gt;
           (ingredient) =&amp;gt; this.bakeThePie(ingredient), &lt;br /&gt;
           (ingredient) =&amp;gt; console.log(`cancelled baking of ${ingredient}`), &lt;br /&gt;
           &#039;apple&#039;);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Multiple choice dialog ===&lt;br /&gt;
&lt;br /&gt;
You can use this dialog to give user a choice with small amount of options&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.multipleChoiceDialog(message: string, choices: string[], callback: (choice: number) =&amp;gt; void): void&#039;&#039;&#039;&lt;br /&gt;
* message - message will be shown to user, use _() to translate&lt;br /&gt;
* choices - array of choices&lt;br /&gt;
* callback - non-optional handler to be called on choice made, the choice parameter is the INDEX of the choice from the array of choices&lt;br /&gt;
&lt;br /&gt;
NOTE: this is async function, it does not return anything and you should not do anything after, you must do everything in handlers&lt;br /&gt;
NOTE: there is no cancel handler, so make sure you gave user a choice to get out of it&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    const keys = [&amp;quot;0&amp;quot;, &amp;quot;1&amp;quot;, &amp;quot;5&amp;quot;, &amp;quot;10&amp;quot;];&lt;br /&gt;
    this.multipleChoiceDialog(_(&amp;quot;How many bugs to fix?&amp;quot;), keys, (choice) =&amp;gt; {&lt;br /&gt;
      if (choice==0) return; // cancel operation, do not call server action&lt;br /&gt;
      var bugchoice = keys[choice]; // choice will be 0,1,2,3 here&lt;br /&gt;
      this.bgaPerformAction(&amp;quot;fixBugs&amp;quot;, { number: bugchoice });&lt;br /&gt;
    });&lt;br /&gt;
    return; // must return here&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Generic Dialogs ===&lt;br /&gt;
&lt;br /&gt;
As a general rule, you shouldn&#039;t use dialogs windows.&lt;br /&gt;
&lt;br /&gt;
BGA guidelines specify that all game elements should be displayed on the main screen. Players can eventually scroll down to see game elements they don&#039;t need to see anytime, and you may eventually create anchors to move between game area section. Of course dialogs windows are very practical, but the thing is: all players know how to scroll down, and not all players know how to show up your dialog window. In addition, when the dialog shows up, players can&#039;t access the other game components.&lt;br /&gt;
&lt;br /&gt;
Sometimes although, you need to display a dialog window. Here is how you do this:&lt;br /&gt;
&lt;br /&gt;
  // Create the new dialog over the play zone. You should store the handler in a member variable to access it later&lt;br /&gt;
  this.myDlg = new ebg.popindialog();&lt;br /&gt;
  this.myDlg.create( &#039;myDialogUniqueId&#039; );&lt;br /&gt;
  this.myDlg.setTitle( _(&amp;quot;my dialog title to translate&amp;quot;) );&lt;br /&gt;
  this.myDlg.setMaxWidth( 500 ); // Optional&lt;br /&gt;
  &lt;br /&gt;
  // Create the HTML of my dialog. &lt;br /&gt;
  // The best practice here is to use [[Game_layout:_view_and_template:_yourgamename.view.php_and_yourgamename_yourgamename.tpl#Javascript_templates|Javascript templates]]&lt;br /&gt;
  var html = this.format_block( &#039;jstpl_myDialogTemplate&#039;, { &lt;br /&gt;
                arg1: myArg1,&lt;br /&gt;
                arg2: myArg2,&lt;br /&gt;
                ...&lt;br /&gt;
            } );  &lt;br /&gt;
  &lt;br /&gt;
  // Show the dialog&lt;br /&gt;
  this.myDlg.setContent( html ); // Must be set before calling show() so that the size of the content is defined before positioning the dialog&lt;br /&gt;
  this.myDlg.show();&lt;br /&gt;
  &lt;br /&gt;
  // Now that the dialog has been displayed, you can connect your method to some dialog elements&lt;br /&gt;
  // Example, if you have an &amp;quot;OK&amp;quot; button in the HTML of your dialog:&lt;br /&gt;
  dojo.connect($(&#039;my_ok_button&#039;), &#039;onclick&#039;, this, (event) =&amp;gt; {&lt;br /&gt;
                event.preventDefault();&lt;br /&gt;
                this.myDlg.destroy();&lt;br /&gt;
            });&lt;br /&gt;
&lt;br /&gt;
If necessary, you can remove the default top right corner &#039;close&#039; icon, or replace the function called when it is clicked:&lt;br /&gt;
  // Removes the default close icon&lt;br /&gt;
  this.myDlg.hideCloseIcon();&lt;br /&gt;
&lt;br /&gt;
  // Replace the function call when it&#039;s clicked&lt;br /&gt;
  this.myDlg.replaceCloseCallback((event) =&amp;gt; { ... });&lt;br /&gt;
&lt;br /&gt;
=== Scoring dialogs ===&lt;br /&gt;
&lt;br /&gt;
Sometimes at the end of a round you want to display a big table that details the points wins in each section of the game.&lt;br /&gt;
&lt;br /&gt;
Example: in Hearts game, we display at the end of each round the number of &amp;quot;heart&amp;quot; cards collected by each player, the player who collected the Queen of Spades, and the total number of points loose by each player.&lt;br /&gt;
&lt;br /&gt;
Scoring dialogs are managed entirely on &#039;&#039;&#039;PHP side&#039;&#039;&#039;, but they are described here as their effects are visible only on client side.&lt;br /&gt;
&lt;br /&gt;
Displaying a scoring dialog is quite simple and is using a special notification type: &amp;quot;tableWindow&amp;quot;:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  // on PHP side:&lt;br /&gt;
  $this-&amp;gt;notifyAllPlayers( &amp;quot;tableWindow&amp;quot;, &#039;&#039;, array(&lt;br /&gt;
            &amp;quot;id&amp;quot; =&amp;gt; &#039;finalScoring&#039;,&lt;br /&gt;
            &amp;quot;title&amp;quot; =&amp;gt; clienttranslate(&amp;quot;Title of the scoring dialog&amp;quot;),&lt;br /&gt;
            &amp;quot;table&amp;quot; =&amp;gt; $table&lt;br /&gt;
        )); &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The &amp;quot;table&amp;quot; argument is a 2 dimensional PHP array that describes the table you want to display, line by line and column by column.&lt;br /&gt;
&lt;br /&gt;
Example: display an 3x3 array of strings&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
   $table = [&lt;br /&gt;
      [ &amp;quot;one&amp;quot;, &amp;quot;two&amp;quot;, &amp;quot;three&amp;quot; ],    // This is my first line&lt;br /&gt;
      [ &amp;quot;four&amp;quot;, &amp;quot;five&amp;quot;, &amp;quot;six&amp;quot; ],    // This is my second line&lt;br /&gt;
      [ &amp;quot;seven&amp;quot;, &amp;quot;height&amp;quot;, &amp;quot;nine&amp;quot; ]    // This is my third line&lt;br /&gt;
   ];&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
As you can see above, in each &amp;quot;cell&amp;quot; of your array you can display a simple string value. But you can also display a complex value with a template and associated arguments like this:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
   $table = [&lt;br /&gt;
      [ &amp;quot;one&amp;quot;, &amp;quot;two&amp;quot;, [ &amp;quot;str&amp;quot; =&amp;gt; clienttranslate(&amp;quot;a string with an ${argument}&amp;quot;), &amp;quot;args&amp;quot; =&amp;gt; [ &#039;argument&#039; =&amp;gt; &#039;argument_value&#039; ] ] ],&lt;br /&gt;
      [ &amp;quot;four&amp;quot;, &amp;quot;five&amp;quot;, &amp;quot;six&amp;quot; ], &lt;br /&gt;
      [ &amp;quot;seven&amp;quot;, &amp;quot;height&amp;quot;, &amp;quot;nine&amp;quot; ]&lt;br /&gt;
   ];&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This is especially useful when you want to display player names with colors. Example from &amp;quot;Hearts&amp;quot;:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        $firstRow = [ &#039;&#039; ];&lt;br /&gt;
        foreach( $players as $player_id =&amp;gt; $player )    {&lt;br /&gt;
            $cell = [ &#039;str&#039; =&amp;gt; &#039;${player_name}&#039;,&lt;br /&gt;
                      &#039;args&#039; =&amp;gt; [ &#039;player_name&#039; =&amp;gt; $player[&#039;player_name&#039;] ],&lt;br /&gt;
                      &#039;type&#039; =&amp;gt; &#039;header&#039;&lt;br /&gt;
                    ];&lt;br /&gt;
            $firstRow[] = $cell;&lt;br /&gt;
        }&lt;br /&gt;
        $table[] = $firstRow;&lt;br /&gt;
        ...&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You can also use three extra attributes in the parameter array for the notification:&lt;br /&gt;
* &#039;&#039;&#039;header&#039;&#039;&#039;: the content for this parameter displays before the table (also, the html will be parsed and player names will be colored according to the current game colors). &lt;br /&gt;
* &#039;&#039;&#039;footer&#039;&#039;&#039;: the content for this parameter displays after the table (no parsing for coloring the player names)&lt;br /&gt;
* &#039;&#039;&#039;closing&#039;&#039;&#039;: if this parameter is used, a button will be displayed with this label at the bottom of the popup and will allow players to close it (more easily than by clicking the top right &#039;cross&#039; icon).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
   $this-&amp;gt;notifyAllPlayers( &amp;quot;tableWindow&amp;quot;, &#039;&#039;, [&lt;br /&gt;
            &amp;quot;id&amp;quot; =&amp;gt; &#039;finalScoring&#039;,&lt;br /&gt;
            &amp;quot;title&amp;quot; =&amp;gt; clienttranslate(&amp;quot;Title of the scoring dialog&amp;quot;),&lt;br /&gt;
            &amp;quot;table&amp;quot; =&amp;gt; $table,&lt;br /&gt;
            &amp;quot;header&amp;quot; =&amp;gt; [&#039;str&#039; =&amp;gt; clienttranslate(&#039;Table header with parameter ${number}&#039;),&lt;br /&gt;
                                 &#039;args&#039; =&amp;gt; [ &#039;number&#039; =&amp;gt; 3 ],&lt;br /&gt;
                               ],&lt;br /&gt;
            &amp;quot;footer&amp;quot; =&amp;gt; &#039;&amp;lt;div class=&amp;quot;myfoot&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&#039;,&lt;br /&gt;
            &amp;quot;closing&amp;quot; =&amp;gt; clienttranslate( &amp;quot;Closing button label&amp;quot; )&lt;br /&gt;
        ] ); &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note: currently id is not used - so you cannot access resulting div by id on js side &lt;br /&gt;
&lt;br /&gt;
Note: any traslatable string have to be wrapped by clienttranslate() on top level OR it has to be recursive template. &lt;br /&gt;
&lt;br /&gt;
DO NOT DO THIS: &lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
   &amp;quot;footer&amp;quot; =&amp;gt; &#039;&amp;lt;div&amp;gt;&#039;.clienttranslate( &amp;quot;The end&amp;quot; ).&#039;&amp;lt;/div&amp;gt;&#039;, // this will not work for translations!!!&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Scoring animated display ===&lt;br /&gt;
&lt;br /&gt;
Sometimes, you may want to display a score value over an element to make the scoring easier to follow for the players (Terra Mystica final scoring for example).&lt;br /&gt;
You can do it with:&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.displayScoring(anchor_id: string, color: string, score: number | string, duration?: number, offset_x?: number, offset_y?: number): void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;anchor_id&#039;&#039;&#039;: ID of the html element to place the animated score onto (without the &#039;#&#039;) &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;color&#039;&#039;&#039;: hexadecimal RGB representation of the color (should be the color of the scoring player), but without a leading &#039;#&#039;.  For instance, &#039;ff0000&#039; for red.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;score&#039;&#039;&#039;: numeric score to display, prefixed by a &#039;+&#039; or &#039;-&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;duration&#039;&#039;&#039;: animation duration in milliseconds (optional, default is 1000)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;offset_x&#039;&#039;&#039; and &#039;&#039;&#039;offset_y&#039;&#039;&#039;: if both offset_x and offset_y are defined and not null, apply the following offset (in pixels) to the scoring animation. &lt;br /&gt;
Note that the score is centered in the anchor, so the offsets might have to be negative if you calculate the position.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Note: if you want to display successively each score, you can use &#039;&#039;this.notifqueue.setSynchronous()&#039;&#039; function.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    setupNotifications: function()   {&lt;br /&gt;
           dojo.subscribe( &#039;displayScoring&#039;, this, &amp;quot;notif_displayScoring&amp;quot; );&lt;br /&gt;
           ...&lt;br /&gt;
    }&lt;br /&gt;
...&lt;br /&gt;
&lt;br /&gt;
    notif_displayScoring: function(notif) {&lt;br /&gt;
            const duration = notif.args.duration?notif.args.duration:1000;&lt;br /&gt;
            this.notifqueue.setSynchronous(&#039;displayScoring&#039;, duration );&lt;br /&gt;
	    this.displayScoring( notif.args.target, notif.args.color, notif.args.score, duration);&lt;br /&gt;
    },&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Speech bubble ===&lt;br /&gt;
&lt;br /&gt;
For better interactivity in some games (Love Letter for example), you may use comic book style speech bubbles to express the players voices.&lt;br /&gt;
This is done with showBubble:&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.showBubble(anchor_id: string, text: string, delay?: number, duration?: number, custom_class?: string): void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
* anchor_id - where to attach the bubble&lt;br /&gt;
* text - what to put in bubble, can be html&lt;br /&gt;
* delay - delay in milliseconds (optional, default 0)&lt;br /&gt;
* duration -  duration of animation in milliseconds (optional, default 3000)&lt;br /&gt;
* custom_class - extra class to add to bubble (optional), if you need to override the default bubble style&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
   this.showBubble(&#039;meeple_2&#039;, _(&#039;Hello&#039;), 0, 1000, &#039;pink_bubble&#039;);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  notif_speechBubble(notif) {&lt;br /&gt;
    var html = this.format_string_recursive(notif.args.text, notif.args.args);&lt;br /&gt;
    this.showBubble(notif.args.target, html, notif.args.delay ?? 0, notif.args.duration ?? 1000);&lt;br /&gt;
  },&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Warning&#039;&#039;&#039;: if your bubble could overlap other active elements of the interface (buttons in particular), as it stays in place even after disappearing, you should use a custom class to give it the style &amp;quot;pointer-events: none;&amp;quot; in order to intercept click events.&lt;br /&gt;
&lt;br /&gt;
Note: If you want this visually, but want to take complete control over this bubble and its animation (for example to make it permanent) you can just use div with &#039;discussion_bubble&#039; class on it, and content of div is what will be shown.&lt;br /&gt;
&lt;br /&gt;
== Translations ==&lt;br /&gt;
&lt;br /&gt;
See [[Translations]]&lt;br /&gt;
&lt;br /&gt;
== Players panels ==&lt;br /&gt;
&lt;br /&gt;
=== Update players score ===&lt;br /&gt;
&lt;br /&gt;
The column player_score from the player table is automatically loaded into this.scoreCtrl and therefore into the stars location on the player board. This occurs sometime after the game setup() function. However this score must be updated as the game progresses using notifications.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Note: this.scoreCtrl[player_id] is object of class [[Counter]], you can use other counter API.&lt;br /&gt;
&lt;br /&gt;
Increase a player score (with a positive or negative number):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  this.scoreCtrl[ player_id ].incValue( score_delta );&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Set a player score to a specific value:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  this.scoreCtrl[ player_id ].setValue( new_score );&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Set a player score to a specific value with animation:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  this.scoreCtrl[ player_id ].toValue( new_score );&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Typical usage would be (that will process &#039;score&#039; notification):&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        setupNotifications : function() {&lt;br /&gt;
              ...&lt;br /&gt;
             dojo.subscribe(&#039;score&#039;, this, &amp;quot;notif_score&amp;quot;);&lt;br /&gt;
        },&lt;br /&gt;
        notif_score: function(notif) {&lt;br /&gt;
            this.scoreCtrl[notif.args.player_id].setValue(notif.args.player_score);&lt;br /&gt;
        },&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Adding stuff to player&#039;s panel ===&lt;br /&gt;
&lt;br /&gt;
At first, create a new &amp;quot;JS template&amp;quot; string in your template (tpl) file:&lt;br /&gt;
&lt;br /&gt;
(from Gomoku example)&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
var jstpl_player_board = &#039;\&amp;lt;div class=&amp;quot;cp_board&amp;quot;&amp;gt;\&lt;br /&gt;
    &amp;lt;div id=&amp;quot;stoneicon_p${id}&amp;quot; class=&amp;quot;gmk_stoneicon gmk_stoneicon_${color}&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&amp;lt;span id=&amp;quot;stonecount_p${id}&amp;quot;&amp;gt;0&amp;lt;/span&amp;gt;\&lt;br /&gt;
&amp;lt;/div&amp;gt;&#039;;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Then, you add this piece of code in your JS file to add this template to each player panel:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
            // Setting up player boards&lt;br /&gt;
            for( var player_id in gamedatas.players )&lt;br /&gt;
            {&lt;br /&gt;
                var player = gamedatas.players[player_id];&lt;br /&gt;
                         &lt;br /&gt;
                // Setting up players boards if needed&lt;br /&gt;
                var player_board_div = $(&#039;player_board_&#039;+player_id);&lt;br /&gt;
                dojo.place( this.format_block(&#039;jstpl_player_board&#039;, player ), player_board_div );&lt;br /&gt;
            }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
(Note: the code above is of course from your &amp;quot;setup&amp;quot; function in your Javascript).&lt;br /&gt;
&lt;br /&gt;
Very often, you have to distinguish current player and others players. In this case, you just have to create another JS template (ex: jstpl_otherplayer_board) and use it when &amp;quot;player_id&amp;quot; is different than &amp;quot;this.player_id&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Fixing Player Panel heights ===&lt;br /&gt;
&lt;br /&gt;
You may find that the player panels don&#039;t automatically resize when adding something to (or removing something from) a player panel while the display is in portrait mode (i.e. the player summary panels are at the top of the screen rather than down the right side).&lt;br /&gt;
&lt;br /&gt;
When this happens, call &amp;lt;pre&amp;gt;this.adaptPlayersPanels();&amp;lt;/pre&amp;gt; This recalculates the layout and also adjusts the position of the actionbar for you.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Player&#039;s panel disabling/enabling ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.disablePlayerPanel(player_id: number): void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Disable given player panel (the panel background become gray).&lt;br /&gt;
&lt;br /&gt;
Usually, this is used to signal that this played passes, or will be inactive during a while.&lt;br /&gt;
&lt;br /&gt;
Note that the only effect of this is visual. There are no consequences on the behaviour of the panel itself.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.enablePlayerPanel(player_id:number): void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Enable a player panel that has been disabled before.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.enableAllPlayerPanels(): void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Enable all player panels that has been disabled before.&lt;br /&gt;
&lt;br /&gt;
=== Player order ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.updatePlayerOrdering(): void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
This function makes sure that player order in player&#039;s panel matches this.gamedatas.playerorder and its normally called by framework.&lt;br /&gt;
You can call it yoursel if you change this.gamedatas.playerorder from notification.&lt;br /&gt;
Also you can override this function to change defaults  OR insert a non-player panel [[BGA_Studio_Cookbook#Inserting_non-player_panel]].&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Counters ===&lt;br /&gt;
Note: there is a bga component called  &amp;quot;ebg/counter&amp;quot;, this API is not using it. These methods below are declared right in the core game. If you need animation for counters use ebg/counter&lt;br /&gt;
&lt;br /&gt;
To use this API just create a counter dom element like this (class does not really matter)&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 &amp;lt;div class=&amp;quot;counter&amp;quot; id=&amp;quot;bread&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
 &amp;lt;div class=&amp;quot;counter&amp;quot; id=&amp;quot;coin&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
The &amp;quot;bread&amp;quot; will the counter name.&lt;br /&gt;
&lt;br /&gt;
The php code should send all &amp;quot;counters&amp;quot; data from getAllDatas() method like this&lt;br /&gt;
&lt;br /&gt;
game.php&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  protected function getAllDatas() {&lt;br /&gt;
    // (the key must match counter_name)&lt;br /&gt;
    $result[&#039;counters&#039;]=[&lt;br /&gt;
        &#039;bread&#039; =&amp;gt; [ &lt;br /&gt;
         &#039;counter_name&#039; =&amp;gt; &#039;bread&#039;, &lt;br /&gt;
         &#039;counter_value&#039; =&amp;gt; 3&lt;br /&gt;
         ], &lt;br /&gt;
        &#039;coin&#039; =&amp;gt; [&lt;br /&gt;
          &#039;counter_name&#039; =&amp;gt; &#039;coin&#039;, &lt;br /&gt;
          &#039;counter_value&#039; =&amp;gt; 5&lt;br /&gt;
        ]&lt;br /&gt;
   ];&lt;br /&gt;
   return $result;&lt;br /&gt;
  }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;setCounter(counter_name: stirng, new_value: string | number): void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
updates the global this.gamedatas.counters and value of node $(counter_name)&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  notif_counter: function(notif) { &lt;br /&gt;
    this.setCounter(notif.args.counter_name, notif.args.counter_value);&lt;br /&gt;
  },&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;incCounter(counter_name: string, delta: number): void&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  notif_counter : function(notif) {&lt;br /&gt;
    this.incCounter(notif.args.counter_name, notif.args.inc);&lt;br /&gt;
  },&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;updateCounters(counters: object): void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Useful for updating game counters in the player panel (such as resources). &lt;br /&gt;
&#039;counters&#039; arg is map of counters (the key must match counter_name)&lt;br /&gt;
  {&lt;br /&gt;
    &#039;bread&#039;: { &lt;br /&gt;
         &#039;counter_name&#039; : &#039;bread&#039;, &lt;br /&gt;
         &#039;counter_value&#039; =&amp;gt; 3&lt;br /&gt;
    }, &lt;br /&gt;
    &#039;coin&#039;: { &lt;br /&gt;
         &#039;counter_name&#039; : &#039;coin&#039;, &lt;br /&gt;
         &#039;counter_value&#039; =&amp;gt; 5&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
All counters MUST be referenced in this.gamedatas.counters (means they should be send from php) and will be updated.&lt;br /&gt;
DOM objects referenced by &#039;counter_name&#039; will have their innerHTML updated with &#039;counter_value&#039;.&lt;br /&gt;
&lt;br /&gt;
Usually you call this from notification&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
                        notif_counter : function(notif) {&lt;br /&gt;
                            this.updateCounters(notif.args.counters);&lt;br /&gt;
                        },&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== BGA GUI components ==&lt;br /&gt;
&lt;br /&gt;
BGA framework provides some useful ready-to-use components for the game interface:&lt;br /&gt;
&lt;br /&gt;
[[Studio#BGA_Studio_game_components_reference]]&lt;br /&gt;
&lt;br /&gt;
Note that each time you are using an additional component, you must declare it at the top of your Javascript file in the list of modules used.&lt;br /&gt;
&lt;br /&gt;
Example if you are using &amp;quot;ebg.stock&amp;quot;:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
define([&lt;br /&gt;
    &amp;quot;dojo&amp;quot;,&amp;quot;dojo/_base/declare&amp;quot;,&lt;br /&gt;
    &amp;quot;ebg/core/gamegui&amp;quot;,&lt;br /&gt;
    &amp;quot;ebg/counter&amp;quot;,&lt;br /&gt;
    &amp;quot;ebg/stock&amp;quot;  /// &amp;lt;=== we are using ebg.stock module&lt;br /&gt;
],&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== BGA Buttons ==&lt;br /&gt;
&lt;br /&gt;
=== Basic Button ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.addActionButton(id: string, label: string, method: string | eventhandler, destination?: string, blinking?: boolean, color?: string): void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
You can use this method to add an action button in the main action status bar (or other places).&lt;br /&gt;
&lt;br /&gt;
Arguments:&lt;br /&gt;
* id: an element ID that should be unique in your HTML DOM document.&lt;br /&gt;
* label: the text of the button. Should be translatable (use _() function). Note: this can also be any html, such as &amp;quot;&amp;lt;div class=&#039;brick&#039;&amp;gt;&amp;lt;/div&amp;gt;&amp;quot;, see example below on how to make image action buttons.&lt;br /&gt;
* method: the name of your method that must be triggered when the player clicks on this button (can be name of the method on game class or handler).&lt;br /&gt;
* destination (optional): id of parent on where to add button, ONLY use in rare cases if location is not action bar. Use &#039;&#039;&#039;null&#039;&#039;&#039; as value if you need to specify other arguments.&lt;br /&gt;
* blinking (optional): if set to &#039;&#039;&#039;true&#039;&#039;&#039;, the button is going blink to catch player&#039;s attention. Please DO NOT abuse blinking button. If you need button to blink after some time passed add class &#039;blinking&#039; to the button later.&lt;br /&gt;
* color: could be &#039;&#039;&#039;blue&#039;&#039;&#039; (default), &#039;&#039;&#039;red&#039;&#039;&#039;,&#039;&#039;&#039;gray&#039;&#039;&#039; or &#039;&#039;&#039;none&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
You should only use this method in your &amp;quot;onUpdateActionButtons&amp;quot; method. Usually, you use it like this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        onUpdateActionButtons: function( stateName, args ) {                      &lt;br /&gt;
            if (this.isCurrentPlayerActive()) {            &lt;br /&gt;
                switch( stateName ) {&lt;br /&gt;
                case &#039;giveCards&#039;:&lt;br /&gt;
                    this.addActionButton( &#039;giveCards_button&#039;, _(&#039;Give selected cards&#039;), &#039;onGiveCards&#039; ); &lt;br /&gt;
                    this.addActionButton( &#039;pass_button&#039;, _(&#039;Pass&#039;), () =&amp;gt; this.bgaPerformAction(&#039;actPass&#039;) ); &lt;br /&gt;
                    break;&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        },   &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In the example above, we are adding a &amp;quot;Give selected cards&amp;quot; button in the case we are on game state &amp;quot;giveCards&amp;quot;. When player clicks on this button, it triggers our &amp;quot;onGiveCards&amp;quot; method.&lt;br /&gt;
&lt;br /&gt;
Example using blinking red button:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    this.addActionButton( &#039;button_confirm&#039;, _(&#039;Confirm?&#039;), &#039;onConfirm&#039;, null, true, &#039;red&#039;); &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If you want to call the handler with arguments, you can use arrow functions, like this:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
     this.addActionButton( &#039;commit_button&#039;, _(&#039;Confirm&#039;), () =&amp;gt; this.onConfirm(this.selectedCardId), null, false, &#039;red&#039;); &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Image Button ===&lt;br /&gt;
&lt;br /&gt;
You can use the same method, but add extra class to a button to disable the padding and style it, i.e.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
this.addActionButton( &#039;button_brick&#039;, &#039;&amp;lt;div class=&amp;quot;brick&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&#039;, ()=&amp;gt;{... on brick ...}, null, null, &#039;gray&#039;); &lt;br /&gt;
dojo.addClass(&#039;button_brick&#039;,&#039;bgaimagebutton&#039;);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
where&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
.bgaimagebutton {&lt;br /&gt;
  padding: 0px 12px;&lt;br /&gt;
  min-height: 28px;&lt;br /&gt;
  border: none;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If you use this a lot, you can define a helper function, i.e.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
 * This method can be used instead of addActionButton, to add a button which is an image (i.e. resource). Can be useful when player&lt;br /&gt;
 * need to make a choice of resources or tokens.&lt;br /&gt;
 */&lt;br /&gt;
addImageActionButton: function(id, div, handler, bcolor, tooltip) {&lt;br /&gt;
	if (typeof bcolor == &amp;quot;undefined&amp;quot;) {&lt;br /&gt;
		bcolor = &amp;quot;gray&amp;quot;;&lt;br /&gt;
	}&lt;br /&gt;
	// this will actually make a transparent button id color = gray&lt;br /&gt;
	this.addActionButton(id, div, handler, null, false, bcolor);&lt;br /&gt;
	// remove border, for images it better without&lt;br /&gt;
	dojo.style(id, &amp;quot;border&amp;quot;, &amp;quot;none&amp;quot;);&lt;br /&gt;
	// but add shadow style (box-shadow, see css)&lt;br /&gt;
	dojo.addClass(id, &amp;quot;shadow bgaimagebutton&amp;quot;);&lt;br /&gt;
	// you can also add additional styles, such as background&lt;br /&gt;
	if (tooltip) {&lt;br /&gt;
		dojo.attr(id, &amp;quot;title&amp;quot;, tooltip);&lt;br /&gt;
	}&lt;br /&gt;
	return $(id);&lt;br /&gt;
},&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Disabling Button ===&lt;br /&gt;
&lt;br /&gt;
You can disable the &#039;&#039;&#039;bgabutton&#039;&#039;&#039; by adding the css class &#039;&#039;&#039;disabled&#039;&#039;&#039; in you js. The disabled button is still visible but is grey and not clickable.&lt;br /&gt;
For example in the &#039;&#039;&#039;onUpdateActionButtons&#039;&#039;&#039; : &lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
this.addActionButton(&#039;play_button_id&#039;, _(&#039;Play 1 to 3 cards&#039;), &#039;playFunctionButton&#039;); &lt;br /&gt;
if (condition) {&lt;br /&gt;
  dojo.addClass(&#039;play_button_id&#039;, &#039;disabled&#039;);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Custom Buttons ===&lt;br /&gt;
&lt;br /&gt;
You can create a custom button, but the BGA framework provides a standard button that requires only .css classes: &#039;&#039;&#039;bgabutton&#039;&#039;&#039; and &#039;&#039;&#039;bgabutton_${color}&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Examples:&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;a href=&amp;quot;#&amp;quot; id=&amp;quot;my_button_id&amp;quot; class=&amp;quot;bgabutton bgabutton_blue&amp;quot;&amp;gt;&amp;lt;span&amp;gt;My blue button&amp;lt;/span&amp;gt;&amp;lt;/a&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;a href=&amp;quot;#&amp;quot; id=&amp;quot;my_button_id&amp;quot; class=&amp;quot;bgabutton bgabutton_red bgabutton_big&amp;quot;&amp;gt;&amp;lt;span&amp;gt;My big red button&amp;lt;/span&amp;gt;&amp;lt;/a&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note&#039;&#039;&#039;: To see it in action, check out &#039;&#039;Coloretto&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
=== Button outside of action bar ===&lt;br /&gt;
&lt;br /&gt;
Use addActionButton() method with destination argument set&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
this.addActionButton( &#039;commit_button&#039;, _(&#039;Confirm&#039;), &#039;onConfirm&#039;, &#039;player_board&#039;, true, &#039;red&#039;); &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
in example above the button will be place on object with id &#039;player_board&#039;&lt;br /&gt;
&lt;br /&gt;
== Image loading ==&lt;br /&gt;
&lt;br /&gt;
See also [[Game_art:_img_directory]].&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Be careful&#039;&#039;&#039;: by default, ALL images of your img directory are loaded on a player&#039;s browser when he loads the game. For this reason, don&#039;t let in your img directory images that are not useful, otherwise it&#039;s going to slowdown the game load.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.dontPreloadImage(image_file_name: string)&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Using dontPreloadImage, you tell the interface to not preload a specific image in your img directory.&lt;br /&gt;
&lt;br /&gt;
Example of use:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
this.dontPreloadImage( &#039;cards.png&#039; );&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This is particularly useful if for example you have 2 different themes for a game. To accelerate the loading of the game, you can specify to not preload images corresponding to the other theme.&lt;br /&gt;
&lt;br /&gt;
Another example of use: in &amp;quot;Gosu&amp;quot; game with Kamakor extension, you play with 5 sets of cards among 10 available. Cards images are organized by sets, and we only preload the images corresponding to the 5 current sets with &#039;&#039;&#039;ensureSpecificGameImageLoading( image_file_names_array )&#039;&#039;&#039;.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
// By default, do not preload anything&lt;br /&gt;
this.dontPreloadImage( &#039;cards.png&#039; );&lt;br /&gt;
this.dontPreloadImage( &#039;clan1.png&#039; );&lt;br /&gt;
this.dontPreloadImage( &#039;clan2.png&#039; );&lt;br /&gt;
this.dontPreloadImage( &#039;clan3.png&#039; );&lt;br /&gt;
this.dontPreloadImage( &#039;clan4.png&#039; );&lt;br /&gt;
this.dontPreloadImage( &#039;clan5.png&#039; );&lt;br /&gt;
this.dontPreloadImage( &#039;clan6.png&#039; );&lt;br /&gt;
this.dontPreloadImage( &#039;clan7.png&#039; );&lt;br /&gt;
this.dontPreloadImage( &#039;clan8.png&#039; );&lt;br /&gt;
this.dontPreloadImage( &#039;clan9.png&#039; );&lt;br /&gt;
this.dontPreloadImage( &#039;clan10.png&#039; );&lt;br /&gt;
var to_preload = [];&lt;br /&gt;
for( i in this.gamedatas.clans )&lt;br /&gt;
{&lt;br /&gt;
	var clan_id = this.gamedatas.clans[i];&lt;br /&gt;
	to_preload.push( &#039;clan&#039;+clan_id+&#039;.png&#039; );&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
this.ensureSpecificGameImageLoading( to_preload );&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note:&#039;&#039;&#039; You don&#039;t need to specify to not preload game box images (game_box.png, game_box75.png...) since they are not preloaded by default.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.ensureSpecificGameImageLoading(list: string[])&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
This is oppostive of dontPreloadImage - its ensure specific images is loaded. Note: only makes sense if preload list is empty, otherwise everything is loaded anyway&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;load specific images&#039;&#039;&#039;&lt;br /&gt;
All images that will be preloaded stored in g_img_preload. If you want to override it directly - there is no API, but you can do this in GAME constructor&lt;br /&gt;
&lt;br /&gt;
          g_img_preload = [&#039;tokens.png&#039;, &#039;trains.png&#039;, &#039;loc_plan.png&#039;, &#039;eng.png&#039;, &#039;eng-back.png&#039;];&lt;br /&gt;
&lt;br /&gt;
You can also set it to empty array and call ensureSpecificGameImageLoading() on specific images&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Sounds ==&lt;br /&gt;
&lt;br /&gt;
Add a custom sound and make it load with your interface:&lt;br /&gt;
&lt;br /&gt;
Add this in your template (.tpl) file:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;audio id=&amp;quot;audiosrc_&amp;lt;gamename&amp;gt;_&amp;lt;yoursoundname&amp;gt;&amp;quot; src=&amp;quot;{GAMETHEMEURL}img/&amp;lt;gamename&amp;gt;_&amp;lt;yoursoundname&amp;gt;.mp3&amp;quot; preload=&amp;quot;none&amp;quot; autobuffer&amp;gt;&amp;lt;/audio&amp;gt;&lt;br /&gt;
&amp;lt;audio id=&amp;quot;audiosrc_o_&amp;lt;gamename&amp;gt;_&amp;lt;yoursoundname&amp;gt;&amp;quot; src=&amp;quot;{GAMETHEMEURL}img/&amp;lt;gamename&amp;gt;_&amp;lt;yoursoundname&amp;gt;.ogg&amp;quot; preload=&amp;quot;none&amp;quot; autobuffer&amp;gt;&amp;lt;/audio&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note: this is a requirement to provide both a mp3 and a ogg file with the names &amp;lt;code&amp;gt;&amp;lt;gamename&amp;gt;_&amp;lt;yoursoundname&amp;gt;[.ogg][.mp3]&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Play the sound (from your .js file):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
playSound(&#039;&amp;lt;gamename&amp;gt;_&amp;lt;yoursoundname&amp;gt;&#039;);   // do not add &#039;this.&#039; - its a global function&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Disable the standard &amp;quot;move&amp;quot; sound for this move (to replace it with your custom sound):&lt;br /&gt;
&lt;br /&gt;
Add this to your notification handler:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
this.disableNextMoveSound();&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note: it only disable the sound for the next move.&lt;br /&gt;
&lt;br /&gt;
== Title bar and states ==&lt;br /&gt;
&lt;br /&gt;
=== Client states ===&lt;br /&gt;
&lt;br /&gt;
Client states is a way to simulate the state transition but without actually going&lt;br /&gt;
to server. It is usefull when you need to ask user multiple questions before you&lt;br /&gt;
send things to server&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.setClientState(newState: string, args: object)&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
     this.setClientState(&amp;quot;client_playerPicksLocation&amp;quot;, {&lt;br /&gt;
                               descriptionmyturn : _(&amp;quot;${you} must select location&amp;quot;),&lt;br /&gt;
                           });&lt;br /&gt;
&lt;br /&gt;
For more information see [[BGA_Studio_Cookbook#Multi_Step_Interactions:_Select_Worker.2FPlace_Worker_-_Using_Client_States]]&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.restoreServerGameState()&#039;&#039;&#039;&lt;br /&gt;
If you are in client state it will restore the current server state (cheap undo)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.on_client_state&#039;&#039;&#039;&lt;br /&gt;
Boolean indicating that we are in client state&lt;br /&gt;
&lt;br /&gt;
=== Title bar ===&lt;br /&gt;
If you simply want to show something in title bar you can do it directly &lt;br /&gt;
     $(&#039;pagemaintitletext&#039;).innerHTML = text;&lt;br /&gt;
&lt;br /&gt;
This however will not work with parameters and will not draw You in color,&lt;br /&gt;
if you want to do proper args rendering use method below&lt;br /&gt;
&lt;br /&gt;
;&#039;&#039;&#039;this.removeActionButtons()&#039;&#039;&#039;&lt;br /&gt;
Removes all buttons from title bar&lt;br /&gt;
&lt;br /&gt;
;&#039;&#039;&#039;this.updatePageTitle()&#039;&#039;&#039;&lt;br /&gt;
:This function allows to update the current page title and turn description according to the game state arguments. If the current game state description this.gamedatas.gamestate.descriptionmyturn is modified before calling this function it allows to update the turn description without changing state. This will handle arguments substitutions properly.&lt;br /&gt;
&lt;br /&gt;
Note: this functional also will calls this.onUpdateActionButtons, if you want different buttons then state defaults, use method in example to replace them, if it becomes too clumsy use client states (see above)&lt;br /&gt;
&lt;br /&gt;
Example from Terra Mystica:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
onClickFavorTile: function( evt ) {&lt;br /&gt;
    ...&lt;br /&gt;
    if ( ... ) {&lt;br /&gt;
        this.gamedatas.gamestate.descriptionmyturn = _(&#039;Special action: &#039;) + _(&#039;Advance 1 space	on a Cult track&#039;);&lt;br /&gt;
        this.updatePageTitle();&lt;br /&gt;
        this.removeActionButtons();&lt;br /&gt;
        this.addActionButton( ... );&lt;br /&gt;
         ...&lt;br /&gt;
        return;&lt;br /&gt;
    }&lt;br /&gt;
    ...&lt;br /&gt;
&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== User preferences ==&lt;br /&gt;
&#039;&#039;&#039;this.getGameUserPreference(pref_id)&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Return the value of a user preference. It will return the value currently selected in the select combo box, in the top-right menu.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.setGameUserPreference(pref_id, value)&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Programmatically change a user preference. It will have the same effect as if the player changed the value in the select combo box, in the top-right menu.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.onGameUserPreferenceChanged&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
A callback you can define if you want to be notified when a user changes a user preference.&lt;br /&gt;
&lt;br /&gt;
Example:&amp;lt;pre&amp;gt;&lt;br /&gt;
onGameUserPreferenceChanged: function(pref_id, pref_value) {&lt;br /&gt;
  switch (pref_id) {&lt;br /&gt;
    case 201: &lt;br /&gt;
      document.getElementsByTagName(&#039;html&#039;)[0].classList.toggle(&#039;dark-background&#039;, pref_value == 2);&lt;br /&gt;
      break;&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Other useful stuff ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;dojo.hitch&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
With dojo.hitch, you can create a callback function that will run with your game object context whatever happen.&lt;br /&gt;
&lt;br /&gt;
Typical example: display a BGA confirmation dialog with a callback function created with dojo.hitch:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        this.confirmationDialog( _(&#039;Are you sure you want to make this?&#039;), dojo.hitch( this, function() {&lt;br /&gt;
            this.bgaPerformAction(&#039;makeThis&#039;);&lt;br /&gt;
        } ) );   &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In the example above, using dojo.hitch, we ensure that the &amp;quot;this&amp;quot; object will be set when the callback is called.&lt;br /&gt;
&lt;br /&gt;
NOTE: In modern JS there are lambdas that eliminate need for that, the example above will look like this&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        this.confirmationDialog( _(&#039;Are you sure you want to make this?&#039;), () =&amp;gt; this.bgaPerformAction( &#039;makeThis&#039;) );   &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
;&#039;&#039;&#039;onScreenWidthChange()&#039;&#039;&#039;&lt;br /&gt;
:This function can be overridden in your game to manage some resizing on the client side when the browser window is resized. This function is also triggered at load time, so it can be used to adapt to the :viewport size at the start of the game too.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
; this.bRealtime&lt;br /&gt;
: Return true if the game is in realtime. Note that having a distinct behavior in realtime and turn-based should be exceptional.&lt;br /&gt;
&lt;br /&gt;
; g_replayFrom&lt;br /&gt;
: Global contains replay number in live game, it is set to undefined (i.e. not set) when it is not a replay mode, so consequentially the good check is &#039;&#039;&#039;typeof g_replayFrom != &#039;undefined&#039;&#039;&#039;&#039; which returns true if the game is in replay mode &amp;lt;i&amp;gt;during the game&amp;lt;/i&amp;gt; (the game is ongoing but the user clicked &amp;quot;replay from this move&amp;quot; in the log)&lt;br /&gt;
&lt;br /&gt;
; g_archive_mode&lt;br /&gt;
: Returns true if the game is in archive mode &amp;lt;i&amp;gt;after the game&amp;lt;/i&amp;gt; (the game has ended)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
; this.instantaneousMode&lt;br /&gt;
: Returns true during replay/archive mode if animations should be skipped. Only needed if you are doing custom animations. (The BGA-provided animation functions like &amp;lt;i&amp;gt;this.slideToObject()&amp;lt;/i&amp;gt; automatically handle instantaneous mode.)&lt;br /&gt;
: Technically, when you click &amp;quot;replay from move #20&amp;quot;, the system replays the game from the very beginning with moves 0 - 19 happening in instantaneous mode and moves 20+ happening in normal mode.&lt;br /&gt;
&lt;br /&gt;
; g_tutorialwritten&lt;br /&gt;
: Returns an object like the below if the game is in tutorial mode, or undefined otherwise. Tutorial mode is a special case of archive mode where comments have been added to a previous game to teach new players the rules.&lt;br /&gt;
    {&lt;br /&gt;
        author: &amp;quot;91577332&amp;quot;,&lt;br /&gt;
        id: &amp;quot;576&amp;quot;,&lt;br /&gt;
        mode: &amp;quot;view&amp;quot;&lt;br /&gt;
        status: &amp;quot;alpha&amp;quot;&lt;br /&gt;
        version_override: null&lt;br /&gt;
        viewer_id: &amp;quot;84554161&amp;quot;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;getBgaEnvironment(): string&#039;&#039;&#039;&lt;br /&gt;
: Returns &amp;quot;studio&amp;quot; for studio and &amp;quot;prod&amp;quot; for production environment (i.e. where games current runs). Only useful for debbugging hooks.&lt;br /&gt;
Note: alpha server is also &amp;quot;prod&amp;quot;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Category:Studio]]&lt;/div&gt;</summary>
		<author><name>Sguzzer Gunayer</name></author>
	</entry>
	<entry>
		<id>https://en.doc.boardgamearena.com/index.php?title=Game_interface_logic:_Game.js&amp;diff=22738</id>
		<title>Game interface logic: Game.js</title>
		<link rel="alternate" type="text/html" href="https://en.doc.boardgamearena.com/index.php?title=Game_interface_logic:_Game.js&amp;diff=22738"/>
		<updated>2024-09-25T18:21:19Z</updated>

		<summary type="html">&lt;p&gt;Sguzzer Gunayer: /* Scoring dialogs */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Studio_Framework_Navigation}}&lt;br /&gt;
&lt;br /&gt;
__TOC__&lt;br /&gt;
&lt;br /&gt;
This is the main file for your game interface. Here you will define:&lt;br /&gt;
&lt;br /&gt;
* Which actions on the page will generate calls to the server.&lt;br /&gt;
* What happens when you get a notification for a change from the server and how it will show in the browser. &lt;br /&gt;
* Setup user interface&lt;br /&gt;
&lt;br /&gt;
== File structure ==&lt;br /&gt;
&lt;br /&gt;
The details of how the file is structured are described below with comments in the code skeleton provided to you.&lt;br /&gt;
&lt;br /&gt;
Here is the basic structure:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;constructor&#039;&#039;&#039;: here you can define global variables for your whole interface.&lt;br /&gt;
* &#039;&#039;&#039;setup&#039;&#039;&#039;: this method is called when the page is refreshed, and sets up the game interface.&lt;br /&gt;
* &#039;&#039;&#039;onEnteringState&#039;&#039;&#039;: this method is called when entering a new game state. You can use it to customize the view for each game state.&lt;br /&gt;
* &#039;&#039;&#039;onLeavingState&#039;&#039;&#039;: this method is called when leaving a game state.&lt;br /&gt;
* &#039;&#039;&#039;onUpdateActionButtons&#039;&#039;&#039;: called on state changes, in order to add action buttons to the status bar. Note: in a multipleactiveplayer state, it will be called when another player has become inactive.&lt;br /&gt;
* &#039;&#039;(utility methods)&#039;&#039;: this is where you can define your utility methods.&lt;br /&gt;
* &#039;&#039;(player&#039;s actions)&#039;&#039;: this is where you can write your handlers for player actions on the interface (example: click on an item).&lt;br /&gt;
* &#039;&#039;&#039;setupNotifications&#039;&#039;&#039;: this method associates notifications with notification handlers. For each game notification, you can trigger a javascript method to handle it and update the game interface.&lt;br /&gt;
* &#039;&#039;(notification handlers)&#039;&#039;: this is where you define the notifications handlers associated with notifications in &#039;&#039;&#039;setupNotifications&#039;&#039;&#039;, above.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
More details:&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;setup(gamedatas: object)            &#039;&#039;&#039;&lt;br /&gt;
This method must set up the game user interface according to current game situation specified in parameters.&lt;br /&gt;
The method is called each time the game interface is displayed to a player, ie:&lt;br /&gt;
&lt;br /&gt;
* when the game starts&lt;br /&gt;
* when a player opens a game in the browser later &lt;br /&gt;
* when a player refreshes the game page (F5)&lt;br /&gt;
* when player does a server side Undo&lt;br /&gt;
&lt;br /&gt;
&amp;quot;gamedatas&amp;quot; argument contains all data retrieved by your &amp;quot;getAllDatas&amp;quot; PHP method and some more.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;onEnteringState(stateName: string, args: { args: any } | null): void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
This method is called each time we enter a new game state.&lt;br /&gt;
You can use this method to perform some user interface changes at this moment.&lt;br /&gt;
To access state arguments passed via calling php arg* method use args?.args.&lt;br /&gt;
Typically you would do something only for active player, using this.isCurrentPlayerActive() check.&lt;br /&gt;
It is also called (for the current game state only) when doing a browser refresh (after the setup method is called).&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Warning&#039;&#039;&#039;: for multipleactiveplayer states:&lt;br /&gt;
the active players are NOT active yet so you must use onUpdateActionButtons to perform the client side operation which depends on a player active/inactive status.&lt;br /&gt;
If you are doing initialization of some structures which do not depend on the active player, you can just replace (this.isCurrentPlayerActive()) with (!this.isSpectator) &lt;br /&gt;
for the main switch in that method.&lt;br /&gt;
&lt;br /&gt;
See more details in [[Your_game_state_machine:_states.inc.php#Difference_between_Single_active_and_Multi_active_states]]&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;onLeavingState(stateName: string): void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
This method is called each time we leave a game state.&lt;br /&gt;
You can use this method to perform some user interface changes at this point (i.e. cleanup).&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;onUpdateActionButtons(stateName: string, args: object | null): void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
In this method you can manage &amp;quot;action buttons&amp;quot; that are displayed in the action status bar and highlight active UI elements.&lt;br /&gt;
To access state arguments passed via calling php arg* method use &#039;&#039;&#039;args&#039;&#039;&#039; parameter. Note: args can be null! For &#039;&#039;&#039;game&#039;&#039;&#039; states and when you don&#039;t supply state args function - it is null.&lt;br /&gt;
This method is called when the active or multiactive player changes. In a classic &amp;quot;activePlayer&amp;quot; state this method is called before the onEnteringState state.&lt;br /&gt;
In multipleactiveplayer state it is a mess. The sequencing of calls depends on whether you get into that state from transitions OR from reloading the whole game (i.e. F5).&lt;br /&gt;
&lt;br /&gt;
See more details in [[Your_game_state_machine:_states.inc.php#Difference_between_Single_active_and_Multi_active_states]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Dojo framework ==&lt;br /&gt;
&lt;br /&gt;
BGA uses the [http://dojotoolkit.org/ Dojo Javascript framework].&lt;br /&gt;
&lt;br /&gt;
The Dojo framework allows us to do complex things more easily. The BGA framework uses Dojo extensively.&lt;br /&gt;
&lt;br /&gt;
To implement a game, you only need to use a few parts of the Dojo framework. All the Dojo methods you need are described on this page.&lt;br /&gt;
&lt;br /&gt;
== Javascript minimization (after July 2020) ==&lt;br /&gt;
&lt;br /&gt;
For performance reasons, when deploying a game the javascript code is minimized using &#039;&#039;&#039;terser&#039;&#039;&#039; (https://github.com/terser/terser). This minifier works with modern javascript syntax. From your project &amp;quot;Manage game&amp;quot; page, you can now test a minified version of your javascript on the studio (and revert to the original).&lt;br /&gt;
&lt;br /&gt;
NB: it has been reported that there is an issue with this minifier and percentage values for opacity.&lt;br /&gt;
&lt;br /&gt;
== Accessing Players Information ==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.player_id: number&#039;&#039;&#039;&lt;br /&gt;
id of the player who is looking at the game. The player may not be part of the game (i.e. spectator)&lt;br /&gt;
  if (notif.args.player_id == this.player_id) {&lt;br /&gt;
    ...&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.isSpectator: boolean&#039;&#039;&#039;&lt;br /&gt;
Flag set to true if the user at the table is a spectator (not a player).&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    if (this.isSpectator) {&lt;br /&gt;
        this.player_color = &#039;ffffff&#039;;&lt;br /&gt;
    } else {&lt;br /&gt;
        this.player_color = gamedatas.players[this.player_id].color;&lt;br /&gt;
    }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note: If you want to hide an element from spectators, you should use [[Game_interface_stylesheet:_yourgamename.css#spectatorMode|CSS &#039;spectatorMode&#039; class]].&lt;br /&gt;
&lt;br /&gt;
You may consider making a function like this, to detect if the game is in a read-only state (i.e. non-interactive):&lt;br /&gt;
  // Returns true for spectators, instant replay (during game), archive mode (after game end)&lt;br /&gt;
  isReadOnly: function () {&lt;br /&gt;
    return this.isSpectator || typeof g_replayFrom != &#039;undefined&#039; || g_archive_mode;&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.gamedatas: object&#039;&#039;&#039;&lt;br /&gt;
Contains the initial set of data to init the game, created at game start or by game refresh (F5).&lt;br /&gt;
You can update it as needed to keep an up-to-date reference of the game on the client side if you need it, however most of the time this is unnecessary.&lt;br /&gt;
&lt;br /&gt;
Note: In hotseat mode, the framework does not keep this.gamedatas of hotseat players and shares the same set as the main player to store data.&lt;br /&gt;
&lt;br /&gt;
Note: be careful when you update this data structurally, many framework functions expect data to be certain way and they will break if they see something else.&lt;br /&gt;
&lt;br /&gt;
Typical example of accessing player&#039;s info&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
for (var player_id in this.gamedatas.players) { &lt;br /&gt;
    var playerInfo = this.gamedatas.players [player_id];&lt;br /&gt;
    var c = playerInfo.color;&lt;br /&gt;
    var name = playerInfo.name;&lt;br /&gt;
    // do something &lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.isCurrentPlayerActive(): boolean&#039;&#039;&#039;&lt;br /&gt;
Returns true if the player on whose browser the code is running is currently active (it&#039;s his turn to play). Note: see remarks above about usage of this function inside onEnteringState method.&lt;br /&gt;
  if (this.isCurrentPlayerActive()) ...&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.getActivePlayerId(): number&#039;&#039;&#039;&lt;br /&gt;
Return the ID of the active player, or null if we are not in an &amp;quot;activeplayer&amp;quot; type state.&lt;br /&gt;
  if (this.player_id == this.getActivePlayerId()) ...&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.getActivePlayers(): number[]&#039;&#039;&#039;&lt;br /&gt;
Return an array with the IDs of players who are currently active (or an empty array if there are none).&lt;br /&gt;
&lt;br /&gt;
== Accessing and manipulating the DOM ==&lt;br /&gt;
&lt;br /&gt;
=== Element by Id ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;$(elementId: ElementOrId)&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
The $ function is used to get an HTML element using its &amp;quot;id&amp;quot; attribute.&lt;br /&gt;
&lt;br /&gt;
Example: modify the content of a &amp;quot;span&amp;quot; element:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
In your HTML code:&lt;br /&gt;
   &amp;lt;span id=&amp;quot;a_value_in_the_game_interface&amp;quot;&amp;gt;1234&amp;lt;/span&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In your Javascript code:&lt;br /&gt;
   $(&#039;a_value_in_the_game_interface&#039;).innerHTML = &amp;quot;9999&amp;quot;;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Note: It is safe to use if you don&#039;t know if variable is string (id of element) or element itself, i.e. &lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  foo: function(card) {&lt;br /&gt;
       card = $(card); // now its node, no need to write if (typeof card === &#039;string&#039;) ...&lt;br /&gt;
       // but its good idea to check for null here&lt;br /&gt;
       ...&lt;br /&gt;
  }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;getElementById(elementId: string)&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Note: $() is the standard method to access some HTML element with the BGA Framework. You can use &#039;&#039;&#039;getElementById&#039;&#039;&#039; but it is longer to type and less handy as it does not do some checks.&lt;br /&gt;
&lt;br /&gt;
=== Style ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;dojo.style(node: ElementOrId, styleName: string, styleValue: any): void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
With dojo.style you can modify the CSS property of any HTML element in your interface.&lt;br /&gt;
&lt;br /&gt;
Examples:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
     // Make an element disappear&lt;br /&gt;
     dojo.style( &#039;my_element&#039;, &#039;display&#039;, &#039;none&#039; );&lt;br /&gt;
&lt;br /&gt;
     // Give an element a 2px border&lt;br /&gt;
     dojo.style( &#039;my_element&#039;, &#039;borderWidth&#039;, &#039;2px&#039; );&lt;br /&gt;
&lt;br /&gt;
     // Change the background position of an element&lt;br /&gt;
     // (very practical when you are using CSS sprites to transform an element to another)&lt;br /&gt;
     dojo.style( &#039;my_element&#039;, &#039;backgroundPosition&#039;, &#039;-20px -50px&#039; );&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note: if you have to modify several CSS properties of an element, or if you have a complex CSS transformation to do, you should consider using dojo.addClass/dojo.removeClass (see below).&lt;br /&gt;
&lt;br /&gt;
You can also use object to set multiple values&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
dojo.setStyle(&amp;quot;thinger&amp;quot;, {&lt;br /&gt;
  &amp;quot;opacity&amp;quot;: 0.5,&lt;br /&gt;
  &amp;quot;border&amp;quot;: &amp;quot;3px solid black&amp;quot;,&lt;br /&gt;
  &amp;quot;height&amp;quot;: &amp;quot;300px&amp;quot;&lt;br /&gt;
});&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.addStyleToClass(cssClassName: string, styleName: string, styleValue: any):&#039;&#039;&#039; &#039;&#039;&#039;void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Same as dojo.style(), but for all the nodes set with the specified cssClassName&lt;br /&gt;
Equivalent of &lt;br /&gt;
  &lt;br /&gt;
  dojo.query(`.${aclass}`).style(styleName, styleValue)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
dojo.query(&amp;quot;#baz &amp;gt; div&amp;quot;).style({&lt;br /&gt;
  opacity:0.75,&lt;br /&gt;
  fontSize:&amp;quot;13pt&amp;quot;&lt;br /&gt;
});&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Vanilla JS style&#039;&#039;&#039;&lt;br /&gt;
  $(&#039;my_element&#039;).style.display=&#039;none&#039;; // set&lt;br /&gt;
  var display = $(&#039;my_element&#039;).style.display; // get&lt;br /&gt;
  $(&#039;my_element&#039;).style.removeProperty(&#039;display&#039;); // remove&lt;br /&gt;
&lt;br /&gt;
=== Classes ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;dojo.addClass(node: ElementOrId, classes: string): void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;dojo.removeClass(node: ElementOrId, classes: string): void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;dojo.hasClass(node: ElementOrId, aclass: string): void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;dojo.toggleClass(node: ElementOrId, aclass: string): void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
In many situations, many small CSS property updates can be replaced by a CSS class change (i.e., you add a CSS class to your element instead of applying all modifications manually).&lt;br /&gt;
&lt;br /&gt;
Advantages are:&lt;br /&gt;
* All your CSS stuff remains in your CSS file.&lt;br /&gt;
* You can add/remove a list of CSS modifications with a simple function and without error.&lt;br /&gt;
* You can test whether you applied the CSS to an element with the &#039;&#039;&#039;dojo.hasClass&#039;&#039;&#039; method.&lt;br /&gt;
&lt;br /&gt;
Example from &#039;&#039;Reversi&#039;&#039;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    // We add &amp;quot;possibleMove&amp;quot; to an element&lt;br /&gt;
    dojo.addClass( &#039;square_&#039;+x+&#039;_&#039;+y, &#039;possibleMove&#039; );&lt;br /&gt;
&lt;br /&gt;
    // In our CSS file, the class is defined as:&lt;br /&gt;
    .possibleMove {&lt;br /&gt;
      background-color: white;&lt;br /&gt;
      opacity: 0.2;&lt;br /&gt;
      filter:alpha(opacity=20); /* For IE8 and earlier */  &lt;br /&gt;
      cursor: pointer;  &lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
     // So we&#039;ve applied 4 CSS property changes in one line of code.&lt;br /&gt;
&lt;br /&gt;
     // ... and when we need to check if a square is a possible move on the client side:&lt;br /&gt;
     if( dojo.hasClass( &#039;square_&#039;+x+&#039;_&#039;+y, &#039;possibleMove&#039; ) )&lt;br /&gt;
     { ... }&lt;br /&gt;
&lt;br /&gt;
     // ... and if we want to remove all possible moves in one line of code (see &amp;quot;dojo.query&amp;quot; method):&lt;br /&gt;
     dojo.query( &#039;.possibleMove&#039; ).removeClass( &#039;possibleMove&#039; );&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Vanilla JS classList&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
This is the only exception where dojo versions are better&lt;br /&gt;
  // add class&lt;br /&gt;
  $(token_id).classList.addClass(&#039;possibleMove&#039;);&lt;br /&gt;
  // remove class&lt;br /&gt;
  $(token_id).classList.removeClass(&#039;possibleMove&#039;);&lt;br /&gt;
  // add 2 classes&lt;br /&gt;
  const myclasses = [&#039;a&#039;,&#039;b&#039;];&lt;br /&gt;
  $(token_id).classList.addClass(...myclasses);&lt;br /&gt;
  // add classes to query result&lt;br /&gt;
  document.querySelectorAll(&amp;quot;.hand .card&amp;quot;).forEach((node)=&amp;gt;node.classList.addClass(&#039;possibleMove&#039;));&lt;br /&gt;
&lt;br /&gt;
=== Attributes ===&lt;br /&gt;
&lt;br /&gt;
;dojo.attr&lt;br /&gt;
&lt;br /&gt;
With dojo.attr you can access or change the value of an attribute or property of any HTML element in your interface.&lt;br /&gt;
&lt;br /&gt;
Exemple:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
     // Get the title of a node&lt;br /&gt;
     var title = dojo.attr( id, &#039;title&#039; );&lt;br /&gt;
     // Change the height of a node&lt;br /&gt;
     dojo.attr( &#039;img_growing_tree&#039;, &#039;height&#039;, 100 );&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Vanilla JS attr&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
   $(token).id=new_id; // set attr for &amp;quot;id&amp;quot;&lt;br /&gt;
   var id = $(token).id; // get&lt;br /&gt;
&lt;br /&gt;
=== Queries ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;dojo.query(cssSelector: string): Element[]&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
With dojo.query, you can query a bunch of HTML elements with a single function, with a &amp;quot;CSS selector&amp;quot; style.&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
     // All elements with class &amp;quot;possibleMove&amp;quot;:&lt;br /&gt;
     var elements = dojo.query( &#039;.possibleMove&#039; );&lt;br /&gt;
&lt;br /&gt;
     // Count number of tokens (i.e., elements of class &amp;quot;token&amp;quot;) on the board (i.e., the element with id &amp;quot;board&amp;quot;):&lt;br /&gt;
     dojo.query( &#039;#board .token&#039; ).length;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
But what is really cool with dojo.query is that you can combine it with almost all methods above.&lt;br /&gt;
&lt;br /&gt;
Examples:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
     // Trigger a method when the mouse enter in any element with class &amp;quot;meeple&amp;quot;:&lt;br /&gt;
     dojo.query( &#039;.meeple&#039; ).connect( &#039;onmouseenter&#039;, this, &#039;myMethodToTrigger&#039; );&lt;br /&gt;
&lt;br /&gt;
     // Hide all meeples who are on the board&lt;br /&gt;
     dojo.query( &#039;#board .meeple&#039; ).style( &#039;display&#039;, &#039;none&#039; );&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Vanilla JS query&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
  var cards=document.querySelectorAll(&amp;quot;.hand .card&amp;quot;);// all cards in all hands&lt;br /&gt;
  var cards=$(&#039;hand&#039;).querySelectorAll(&amp;quot;.card&amp;quot;);// all cards in specific hand&lt;br /&gt;
  var card=document.querySelector(&amp;quot;.hand .card&amp;quot;);// first card or null if none (super handy)&lt;br /&gt;
&lt;br /&gt;
=== Creating and Destroying elements ===&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;dojo.empty(node: ElementOrId)&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Remove all children of the node element&lt;br /&gt;
   dojo.empty(&#039;my_hand&#039;);&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;dojo.destroy(node: ElementOrId)&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Remove the element&lt;br /&gt;
   dojo.destroy(&#039;my_token&#039;);&lt;br /&gt;
&lt;br /&gt;
   dojo.query(&amp;quot;.green&amp;quot;, mynode).forEach(dojo.destroy); // this remove all subnode of class green from mynode&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;dojo.create(tag: string, attributes?: obj, parent?: ElementOrId): Element&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Create element&lt;br /&gt;
&lt;br /&gt;
    dojo.create(&amp;quot;div&amp;quot;, { class: &amp;quot;yellow_arrow&amp;quot; }, parent); // this creates div with class yellow_array and places it in &amp;quot;parent&amp;quot;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.format_block(name: string, args: object): string&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
This bga function that takes global var from template file and substitute variables, typical use would be&lt;br /&gt;
&lt;br /&gt;
                var player = gamedatas.players[player_id];&lt;br /&gt;
                var div = this.format_block(&#039;jstpl_player_board&#039;, player ); // var jstpl_player_board = ... is defined in .tpl file &lt;br /&gt;
Note: result is trimmed&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.format_string(name: string, args: object): string&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
This bga function just substitute variables in a string, i.e.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
     var div = this.format_string(&#039;&amp;lt;div color=&amp;quot;${player_color}&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&#039;, {player_color: &#039;#ff0000&#039;} );&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Note: result is trimmed&lt;br /&gt;
&lt;br /&gt;
Note: this can be replaced by using backquoted string now: &lt;br /&gt;
     const player_color =  &#039;#ff0000&#039;;&lt;br /&gt;
&lt;br /&gt;
    const div = ``;&lt;br /&gt;
&#039;&#039;&#039;this.format_string_recursive&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
This bga function is similar to this.format_string but is capable of processing recursive argument structures and translations. It is used to format server notifications.&lt;br /&gt;
&lt;br /&gt;
TODO: find better place for these function docs&lt;br /&gt;
&lt;br /&gt;
=== Moving elements ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;dojo.place(node: string | Element, refNode: ElementOrId, pos?: string | number): Element&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
dojo.place is the best function to insert HTML code somewhere in your game interface without breaking something. It is much better to use than the &#039;&#039;&#039;innerHTML=&#039;&#039;&#039; method if you must insert HTML tags and not only values.&lt;br /&gt;
&lt;br /&gt;
node: can be a string or a DOM node. If it is a string starting with “&amp;lt;”, it is assumed to be an HTML fragment, which will be created. Otherwise it is assumed to be an id of a DOM node. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
     // Insert your HTML code as a child of a container element&lt;br /&gt;
     dojo.place( &amp;quot;&amp;lt;div class=&#039;foo&#039;&amp;gt;&amp;lt;/div&amp;gt;&amp;quot;, &amp;quot;your_container_element_id&amp;quot; );&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
pos: optional argument. Can be a number or one of the following strings: “before”, “after”, “replace”, “only”, “first”, or “last”. If omitted, “last” is assumed.&lt;br /&gt;
&lt;br /&gt;
* &amp;quot;replace&amp;quot;: replace the container element with my_node element&lt;br /&gt;
* &amp;quot;first&amp;quot;: places the node as a child of the reference node. The node is placed as the first child.&lt;br /&gt;
* &amp;quot;last&amp;quot; (default): places the node as a child of the reference node. The node is placed as the last child.&lt;br /&gt;
* &amp;quot;before&amp;quot;: places the node right before the reference node.&lt;br /&gt;
* &amp;quot;after&amp;quot;: places the node right after the reference node.&lt;br /&gt;
* &amp;quot;only&amp;quot;: replaces all children of the reference node with the node.&lt;br /&gt;
&lt;br /&gt;
this parameter can be a positive integer. In this case, the node will be placed as a child of the reference node with this number (counting from 0). If the number is more than number of children, the node will be appended to the reference node making it the last child. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
     // Replace all children of container with my_node &lt;br /&gt;
     dojo.place( $(&#039;my_node&#039;), &amp;quot;your_container_element_id&amp;quot;, &amp;quot;only&amp;quot; );&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
See also full doc on dojo.place: [https://dojotoolkit.org/reference-guide/1.7/dojo/place.html]&lt;br /&gt;
&lt;br /&gt;
Usually, when you want to insert some piece of HTML in your game interface, you should use &amp;quot;[[Game_layout:_view_and_template:_yourgamename.view.php_and_yourgamename_yourgamename.tpl#Javascript_templates|Javascript templates]]&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
But you can also relocate elements like that. Note: it won&#039;t animate if you do that.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.placeOnObject(mobile_obj: ElementOrId, target_obj: ElementOrId): void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
places mobile_obj on target_obj, set the absolute positions and centers the mobile_obj on target_obj,&lt;br /&gt;
effect is immediate&lt;br /&gt;
&lt;br /&gt;
This is not really an animation, but placeOnObject is frequently used before starting an animation.&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  // (We just created an object &amp;quot;my_new_token&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
  // Place the new token on current player board&lt;br /&gt;
  this.placeOnObject( &amp;quot;my_new_token&amp;quot;, &amp;quot;overall_player_board_&amp;quot;+this.player_id );&lt;br /&gt;
  &lt;br /&gt;
  // Then slide it to its position on the board&lt;br /&gt;
  this.slideToObject( &amp;quot;my_new_token&amp;quot;, &amp;quot;a_place_on_board&amp;quot; ).play();&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.placeOnObjectPos(mobile_obj: ElementOrId, target_obj: ElementOrId, target_x: number, target_y: number): void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
This method works exactly like placeOnObject, except than you can specify some (x,y) coordinates (in px). This way, the center of &amp;quot;mobile_obj&amp;quot; will be placed to the specified x,y position relatively to the center of &amp;quot;target_obj&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Note: the placement works differently from this.slideToObjectPos&#039;&#039;, since coordinates are calculated based on the center of objects.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.attachToNewParent(mobile_obj: ElementOrId, target_obj: ElementOrId): void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
With this method, you change the HTML parent of &amp;quot;mobile_obj&amp;quot; element without moving it. &lt;br /&gt;
&amp;quot;target_obj&amp;quot; is the new parent of this element. The beauty of &lt;br /&gt;
attachToNewParent is that the mobile_obj element DOES NOT MOVE during this process.&lt;br /&gt;
&lt;br /&gt;
What happens is that the method calculate a relative position of mobile_obj to make sure it does not move after the HTML parent changes.&lt;br /&gt;
&lt;br /&gt;
Why using this method?&lt;br /&gt;
&lt;br /&gt;
Changing the HTML parent of an element can be useful for the following reasons:&lt;br /&gt;
* When the HTML parent moves, all its child are moving with them. If some game elements is no more linked with a parent HTML object, you may want to attach it to another place.&lt;br /&gt;
* The z_order (vertical order of display) depends on the position in the DOM, so you may need to change the parent of some game elements when they are moving in your game area.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;CAREFUL&#039;&#039;&#039;: this function destroys original object and places a clone onto a new parent, this will break all references to this HTML element (ex: dojo.connect).&lt;br /&gt;
If you need version that does not destroy the object but the same otherwise see [[BGA_Studio_Cookbook#Attach_to_new_parent_without_destroying_the_object]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Animations ==&lt;br /&gt;
&lt;br /&gt;
===Dojo Animations===&lt;br /&gt;
&lt;br /&gt;
BGA animations is based on Dojo Animation ([http://dojotoolkit.org/documentation/tutorials/1.8/animation/ see tutorial here]).&lt;br /&gt;
&lt;br /&gt;
However, most of the time, you can just use methods below, which are built on top of Dojo Animation.&lt;br /&gt;
&lt;br /&gt;
Note: one interesting method from Dojo that could be useful from time to time is &amp;quot;Dojo.Animation&amp;quot;. It allows you to make any CSS property &amp;quot;slide&amp;quot; from one value to another.&lt;br /&gt;
&lt;br /&gt;
Note 2: the slideTo methods are not compatible with CSS transform (scale, zoom, rotate...). If possible, avoid using CSS transform on nodes that are being slided. Eventually, the only possible solution to make these 2 compatible is to disable all CSS transform properties, use slideToObjectPos/placeOnObjectPos, and then apply them again.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Sliding===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.slideToObject(mobile_obj: ElementOrId, target_obj: ElementOrId, duration?: number, delay?: number): Animation&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
You can use slideToObject to &amp;quot;slide&amp;quot; an element to a target position.&lt;br /&gt;
&lt;br /&gt;
Sliding element on the game area is the recommended and the most used way to animate your game interface. Using slides allow players to figure out what is happening on the game, as if they were playing with the real boardgame.&lt;br /&gt;
&lt;br /&gt;
The parameters are:&lt;br /&gt;
* mobile_obj: the ID of the object to move. This object must be &amp;quot;relative&amp;quot; or &amp;quot;absolute&amp;quot; positioned.&lt;br /&gt;
* target_obj: the ID of the target object. This object must be &amp;quot;relative&amp;quot; or &amp;quot;absolute&amp;quot; positioned. Note that it is not mandatory that mobile_obj and target_obj have the same size. If their size are different, the system slides the center of mobile_obj to the center of target_obj.&lt;br /&gt;
* duration: (optional) defines the duration in millisecond of the slide. The default is 500 milliseconds.&lt;br /&gt;
* delay: (optional). If you defines a delay, the slide will start only after this delay. This is particularly useful when you want to slide several object from the same position to the same position: you can give a 0ms delay to the first object, a 100ms delay to the second one, a 200ms delay to the third one, ... this way they won&#039;t be superposed during the slide.&lt;br /&gt;
&lt;br /&gt;
BE CAREFUL: The method returns an dojo.fx animation, so you can combine it with other animation if you want to. It means that you have to call the &amp;quot;play()&amp;quot; method, otherwise the animation WON&#039;T START.&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
   this.slideToObject( &amp;quot;some_token&amp;quot;, &amp;quot;some_place_on_board&amp;quot; ).play();&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.slideToObjectPos(mobile_obj: ElementOrId, target_obj: ElementOrId, target_x: number, target_y: number, duration?: number, delay?: number): Animation&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
This method does exactly the same as &amp;quot;slideToObject&amp;quot;, except than you can specify some (x,y) coordinates. This way, &amp;quot;mobile_obj&amp;quot; will slide to the specified x,y position relatively to &amp;quot;target_obj&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
Example: slide a token to some place on the board, 10 pixels from the top:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
   this.slideToObjectPos( &amp;quot;some_token&amp;quot;, &amp;quot;some_place_on_board&amp;quot;, 0, 10 ).play();&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.slideTemporaryObject(mobile_obj_html: string, parent: ElementOrId, from: ElementOrId, to: ElementOrId, duration?: number, delay?: number): Animation&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
This method is useful when you want to slide a temporary HTML object from one place to another. As this object does not exists before the animation and won&#039;t remain after, it could be complex to create this object (with dojo.place), to place it at its origin (with placeOnObject) to slide it (with slideToObject) and to make it disappear at the end.&lt;br /&gt;
&lt;br /&gt;
slideTemporaryObject does all of this for you:&lt;br /&gt;
* mobile_obj_html is a piece of HTML code that represent the object to slide.&lt;br /&gt;
* parent is the ID of an HTML element of your interface that will be the parent of this temporary HTML object.&lt;br /&gt;
* from is the ID of the origin of the slide.&lt;br /&gt;
* to is the ID of the target of the slide.&lt;br /&gt;
* duration/delay works exactly like in &amp;quot;slideToObject&amp;quot;&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
this.slideTemporaryObject( &#039;&amp;lt;div class=&amp;quot;token_icon&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&#039;, &#039;tokens&#039;, &#039;my_origin_div&#039;, &#039;my_target_div&#039; ).play();&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Destroy===&lt;br /&gt;
&#039;&#039;&#039;this.slideToObjectAndDestroy(mobile_obj: ElementOrId, target_obj: ElementOrId, duration?: number, delay?: number): void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
This method is a handy shortcut to slide an existing HTML object to some place then destroy it upon arrival. It can be used for example to move a victory token or a card from the board to the player panel to show that the player earns it, then destroy it when we don&#039;t need to keep it visible on the player panel.&lt;br /&gt;
&lt;br /&gt;
It works the same as this.slideToObject and takes the same arguments, but it starts the animation. &lt;br /&gt;
&lt;br /&gt;
CAREFUL: Make sure nothing is creating the same object at the same time the animation is running, because this will cause some random disappearing effects&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
this.slideToObjectAndDestroy( &amp;quot;some_token&amp;quot;, &amp;quot;some_place_on_board&amp;quot;, 1000, 0 );&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.fadeOutAndDestroy( node: string | Element, duration?: number, delay?: number):&#039;&#039;&#039; &#039;&#039;&#039;void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
This function fade out the target node, then destroy it. Its starts the animation.&lt;br /&gt;
* duration/delay works exactly like in &amp;quot;slideToObject&amp;quot;&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
   this.fadeOutAndDestroy( &amp;quot;a_card_that_must_disappear&amp;quot; );&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
CAREFUL: the HTML node still exists until during few milliseconds, until the fadeOut has been completed.&lt;br /&gt;
Make sure nothing is creating same object at the same time as animation is running, because you will be some random dissapearing effects&lt;br /&gt;
&lt;br /&gt;
===Rotating elements===&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
This example combines &amp;quot;Dojo.Animation&amp;quot; method and a CSS property transform that allow you to rotate the element.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
// node is Element we rotating&lt;br /&gt;
		    var animation = new dojo.Animation({&lt;br /&gt;
			    curve: [fromDegree, toDegree],&lt;br /&gt;
			    onAnimate: (v) =&amp;gt; {&lt;br /&gt;
				    node.style.transform = &#039;rotate(&#039; + v + &#039;deg)&#039;;&lt;br /&gt;
			    } &lt;br /&gt;
		    });&lt;br /&gt;
		    &lt;br /&gt;
		    animation.play();  &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
BGA has its own interface to rotate&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.rotateTo(node: string | Element, degree: number): void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
It starts the animation, and stored the rotation degree in the class, so next time you rotate object - it is additive.&lt;br /&gt;
There is no animation hooks in this one, if you need to change any parameters use dojo animation above.&lt;br /&gt;
&lt;br /&gt;
There is also &#039;&#039;&#039;rotateInstantTo&#039;&#039;&#039; with same signature which does not animate&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Animation Callbacks===&lt;br /&gt;
&lt;br /&gt;
If you wish to run some code only after an animation has completed you can do this by linking a callback method to &#039;onEnd&#039;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
var animation_id = this.slideToObject( mobile_obj, target_obj, 500 );&lt;br /&gt;
dojo.connect(animation_id, &#039;onEnd&#039;, () =&amp;gt; {&lt;br /&gt;
   // do something here&lt;br /&gt;
});&lt;br /&gt;
animation_id.play();&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If you wish to call a second animation after the first (rather than general code) then you can use a dojo animation chain (see tutorial referenced above).&lt;br /&gt;
&lt;br /&gt;
== Players input ==&lt;br /&gt;
&lt;br /&gt;
=== Connecting ===&lt;br /&gt;
&#039;&#039;&#039;dojo.connect(element: Element, event: string, context: object, method: eventHandler): any&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;dojo.connect(element: Element, event: string, handler: eventHandler): any&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Used to associate a player event with one of your notification methods.&lt;br /&gt;
&lt;br /&gt;
Example: associate a click on an element (&amp;quot;my_element&amp;quot;) with one of our methods (&amp;quot;onClickOnMyElement&amp;quot;):&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
      dojo.connect( $(&#039;my_element&#039;), &#039;onclick&#039;, this, &#039;onClickOnMyElement&#039; );&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Same idea but based on query (i.e. all element of &#039;pet&#039; class)&lt;br /&gt;
      dojo.query(&amp;quot;.pet&amp;quot;).connect(&#039;onclick&#039;, this, &#039;onPet&#039;);&lt;br /&gt;
&lt;br /&gt;
Note: if you need to disconnect the handler you have to store handler returned from this method, i.e.&lt;br /&gt;
   &lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    var handler = dojo.connect(...);&lt;br /&gt;
    ...&lt;br /&gt;
    dojo.disconnect(handler);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If you don&#039;t store the handler - you have to destroy the object to disconnect it&lt;br /&gt;
&lt;br /&gt;
Typical function that implements the input handler will look like this&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
onPet: function(event) {&lt;br /&gt;
    var id = event.currentTarget.id;&lt;br /&gt;
    console.log(&#039;onPet &#039; + id);&lt;br /&gt;
    dojo.stopEvent(event);&lt;br /&gt;
    if (this.gamedatas.gamestate.name == &#039;playerTurnPet&#039;) {&lt;br /&gt;
          this.bgaPerformAction(&#039;actPlayPet&#039;, {card: id});&lt;br /&gt;
    } else {&lt;br /&gt;
          this.showMoveUnauthorized();&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.connect(element: ElementOrId, event: string, method: eventHandler): void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Used to associate a player event with one of your notification methods.&lt;br /&gt;
&lt;br /&gt;
      this.connect( $(&#039;my_element&#039;), &#039;onclick&#039;, &#039;onClickOnMyElement&#039; );&lt;br /&gt;
&lt;br /&gt;
Or you can use an in-place handler&lt;br /&gt;
&lt;br /&gt;
      this.connect( $(&#039;my_element&#039;), &#039;onclick&#039;, (e) =&amp;gt; { console.log(&#039;boo&#039;); } );&lt;br /&gt;
&lt;br /&gt;
Note that this function stores the connection handler. That is the only real difference between &#039;&#039;&#039;this.connect&#039;&#039;&#039; and &#039;&#039;&#039;dojo.connect&#039;&#039;&#039;. If you plan to destroy the element you connected, you &#039;&#039;&#039;must&#039;&#039;&#039; call this.disconnect() to prevent memory leaks.&lt;br /&gt;
This function is mainly for permanent objects - if you just want to connect the temp object you should probably not use this method but use dojo.connect which won&#039;t require any clean-up.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.connectClass(cssClassName: string, event: string, method: eventHandler): void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Same as connect(), but for all the nodes set with the specified cssClassName.&lt;br /&gt;
 this.connectClass(&#039;pet&#039;, &#039;onclick&#039;, &#039;onPet&#039;);&lt;br /&gt;
&#039;&#039;&#039;this.disconnect(element: ElementOrId, event: string): void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Disconnect event handler (previously registered with this.connect or this.connectClass).&lt;br /&gt;
&lt;br /&gt;
   this.disconnect( $(&#039;my_element&#039;), &#039;onclick&#039;);&lt;br /&gt;
&lt;br /&gt;
Note: dynamic connect/disconnect is for advanced cases ONLY, you should always connect elements statically if possible, i.e. in setup() method.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.disconnectAll(): void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Disconnect all previously registed event handlers (registered via this.connect or this.connectClass)&lt;br /&gt;
&lt;br /&gt;
  this.disconnectAll();&lt;br /&gt;
&lt;br /&gt;
=== Actions ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.bgaPerformAction(action: string, args?: object, options: object = { lock: true, checkAction: true }): Promise&amp;lt;void&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Triggers an action on the backend. This is a combination of checkAction and ajaxcall, returning a Promise which resoves when ajaxcall ends.&lt;br /&gt;
&lt;br /&gt;
This method must be used to send a player input to the game server. &#039;&#039;&#039;It should not be triggered programmatically&#039;&#039;&#039;, especially not in loops, in callbacks, in notifications, or in onEnteringState/onUpdateActionButtons/onLeavingState, in order not to create race conditions or break replay game and tutorial features. It should be used only in reaction to a user action in the interface.&lt;br /&gt;
&lt;br /&gt;
* action: name of the action, as it is written in &amp;quot;possibleactions&amp;quot; of the current state.&lt;br /&gt;
* args: an object containing the call parameters to send to the action&lt;br /&gt;
* options: options to tweak the call with some defaults. Default is &amp;lt;code&amp;gt;{ lock: true, checkAction: true }&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Example of a standard call without args:&lt;br /&gt;
  this.bgaPerformAction(&#039;pass&#039;);&lt;br /&gt;
&lt;br /&gt;
Example of a standard call with action args:&lt;br /&gt;
  this.bgaPerformAction(&#039;actPlayCard&#039;, { id: this.selectedCardId });&lt;br /&gt;
&lt;br /&gt;
Example of a call without checking action (because player is inactive in a multiactive state):&lt;br /&gt;
&lt;br /&gt;
 this.bgaPerformAction(&#039;actChangeMind&#039;, {}, { checkAction: false });&lt;br /&gt;
&lt;br /&gt;
Example of a call without lock (because of a special action not directly related to the game flow):&lt;br /&gt;
&lt;br /&gt;
 this.bgaPerformAction(&#039;actSetAutoBid&#039;, { alwaysBidUntil: 500 }, { lock: false, checkAction: false });&lt;br /&gt;
&lt;br /&gt;
Example of call with reaction to exception:&lt;br /&gt;
  this.bgaPerformAction(&#039;actPlayCard&#039;, { id: this.selectedCardId }).catch(()=&amp;gt;{ this.selectedCardId = undefined; });&lt;br /&gt;
&lt;br /&gt;
Example of call with reaction to success:&lt;br /&gt;
  this.bgaPerformAction(&#039;actPlayCard&#039;, { id: this.selectedCardId }).then(()=&amp;gt;{ this.unselectAll(); });&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.ajaxcall(url, parameters, obj_callback, callback, callback_anycase?, ajax_method?: string)&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Note: bgaPerformAction is a simpler way to use ajax calls, ajaxcall stays in the doc for legacy reasons only and should not be used in new projects.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Same warning as &#039;&#039;&#039;this.bgaPerformAction&#039;&#039;&#039; about using on user action only.&lt;br /&gt;
&lt;br /&gt;
* url: the url of the action to perform. For a game, it must be: &amp;quot;/&amp;lt;mygame&amp;gt;/&amp;lt;mygame&amp;gt;/myAction.html&amp;quot;&lt;br /&gt;
* parameters: an array of parameter to send to the game server. &lt;br /&gt;
** Note that &amp;quot;lock: true&amp;quot; must always be specified in this list of parameters in order the interface can be locked during the server call. Cannot use lock: false - to not lock it has to be undefined.&lt;br /&gt;
** Note: Restricted parameter names (please don&#039;t use them):&lt;br /&gt;
*** &amp;quot;action&amp;quot;&lt;br /&gt;
*** &amp;quot;module&amp;quot;&lt;br /&gt;
*** &amp;quot;class&amp;quot;&lt;br /&gt;
* obj_callback: must be set to &amp;quot;this&amp;quot;.&lt;br /&gt;
* callback (non-optional but rarely used): a function to trigger when the server returns result and everything went fine (not used, as all data handling is done via notifications).&lt;br /&gt;
* callback_anycase: (optional) a function to trigger when the server returns ok OR error.  If no error this function is called with parameter value false. If an error occurred, the first parameter will be set to true, the second will contain the error message sent by the PHP back-end, and the third will contain an error code.&lt;br /&gt;
* ajax_method: (optional and rarely used) if you need to send large amounts of data (over 2048 bytes), you can set this parameter to &#039;post&#039; (all lower-case) to send a POST request as opposed to the default GET. This works, but was not officially documented, so only use if you really need to.&lt;br /&gt;
&lt;br /&gt;
Usage:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
this.ajaxcall( &#039;/mygame/mygame/actMyAction.html&#039;, { lock: true, &lt;br /&gt;
   arg1: myarg1, &lt;br /&gt;
   arg2: myarg2&lt;br /&gt;
}, this, (result)=&amp;gt;{} );&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.checkAction(action: string, nomessage?: boolean): boolean &#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Check if player can do the specified action by taking into account:&lt;br /&gt;
* if interface is locked it will return false and show message &amp;quot;An action is already in progress&amp;quot;,  unless nomessage set to true &lt;br /&gt;
* if player is not active it will return false and show message &amp;quot;This is not your turn&amp;quot;, unless nomessage set to true &lt;br /&gt;
* if action is not in list in possible actions (defined by &amp;quot;possibleaction&amp;quot; in current game state) it will return false and show &amp;quot;This move is not authorized now&amp;quot; error (unconditionally).&lt;br /&gt;
* otherwise returns true&lt;br /&gt;
Example:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  function onClickOnGameElement( evt )  {&lt;br /&gt;
     if( this.checkAction( &amp;quot;actMyAction&amp;quot; ) ) {&lt;br /&gt;
        // Do the action&lt;br /&gt;
     }&lt;br /&gt;
  }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.checkPossibleActions(action: string): boolean&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
* this is independent of the player being active, so can be used instead of this.checkAction(). This is particularly useful for multiplayer states when the player is not active in a &#039;player may like to change their mind&#039; scenario. Unlike this.checkAction, this function does NOT take interface locking into account &lt;br /&gt;
&lt;br /&gt;
* if action is not in list in possible actions (defined by &amp;quot;possibleaction&amp;quot; in current game state) it will return false and show &amp;quot;This move is not authorized now&amp;quot; error (unconditionally).&lt;br /&gt;
* otherwise returns true&lt;br /&gt;
&lt;br /&gt;
  function onChangeMyMind( evt )  {&lt;br /&gt;
     if( this.checkPossibleActions( &amp;quot;actMyAction&amp;quot; ) ) {&lt;br /&gt;
        // Do the action&lt;br /&gt;
     }&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.checkLock(nomessage?: boolean): boolean&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
When using &amp;quot;lock: true&amp;quot; in ajax call you can use this function to check if interface is in lock state (it will be locked during server call and notification processing).&lt;br /&gt;
This check can be used to block some other interactions which do not result in ajaxcall or if you want to suppress errors. Note: normally you only need to use this.checkAction(...), this is for advanced cases.&lt;br /&gt;
&lt;br /&gt;
It will also show error unless nomessage is set to true&lt;br /&gt;
&lt;br /&gt;
  function onChangeMyMind( evt )  {&lt;br /&gt;
     if( this.checkLock() ) {&lt;br /&gt;
        // Do the action&lt;br /&gt;
     }&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
== Notifications ==&lt;br /&gt;
&lt;br /&gt;
When something happens on the server side, your game interface Javascript logic received a notification.&lt;br /&gt;
If you have not done so yet check what notification are in [[Main_game_logic:_yourgamename.game.php#Notifications]]&lt;br /&gt;
&lt;br /&gt;
Here&#039;s how you can handle these notifications on the client side.&lt;br /&gt;
&lt;br /&gt;
=== Subscribe to notifications ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;dojo.subscribe(notif_type: string, callback_obj: Object, handler: string|handler)&#039;&#039;&#039;&lt;br /&gt;
* notif_type - notification type/name send by php server&lt;br /&gt;
* callback_obj - usually this&lt;br /&gt;
* handler - if string method of callback_obj with name name is called, when notification is called, with notification object as parameter (see below)&lt;br /&gt;
&lt;br /&gt;
Your Javascript &amp;quot;setupNotifications&amp;quot; method is the place where you can subscribe to notifications from your PHP code.&lt;br /&gt;
&lt;br /&gt;
Here&#039;s how you associate one of your Javascript method to a notification &amp;quot;playDisc&amp;quot; (from Reversi example):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
   setupNotifications: function() {&lt;br /&gt;
      ...&lt;br /&gt;
      dojo.subscribe(&#039;playDisc&#039;, this, &amp;quot;notif_playDisc&amp;quot;);&lt;br /&gt;
   },&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note: the &amp;quot;playDisc&amp;quot; corresponds to the name of the notification you define it in your PHP code, in your &amp;quot;notifyAllPlayers&amp;quot; or &amp;quot;notifyPlayer&amp;quot; method.&lt;br /&gt;
&lt;br /&gt;
Then, you have to define your &amp;quot;notif_playDisc&amp;quot; method:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
   notif_playDisc: function(notif) {&lt;br /&gt;
     // Remove current possible moves (makes the board more clear)&lt;br /&gt;
     dojo.query( &#039;.possibleMove&#039; ).removeClass( &#039;possibleMove&#039; );          &lt;br /&gt;
     this.addDiscOnBoard( notif.args.x, notif.args.y, notif.args.player_id );&lt;br /&gt;
   },&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In a notification handler like our &amp;quot;notif_playDisc&amp;quot; method, you can access all notifications arguments with &amp;quot;notif.args&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&lt;br /&gt;
PHP&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    $this-&amp;gt;notifyAllPlayers( &amp;quot;apples&amp;quot;, clienttranslate(&#039;player takes ${count} apples&#039;), [ &amp;quot;count&amp;quot; =&amp;gt; 3 ] );&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
JavaScript&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    setupNotifications: function() {&lt;br /&gt;
       dojo.subscribe( &#039;apples&#039;, this, &#039;notif_apples&#039; );&lt;br /&gt;
    },&lt;br /&gt;
&lt;br /&gt;
    notif_apples: function(notif) {&lt;br /&gt;
      //You can access the &amp;quot;count&amp;quot; like this:&lt;br /&gt;
       alert(&amp;quot;count = &amp;quot; + notif.args.count);&lt;br /&gt;
    }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== The notification Object received by client ===&lt;br /&gt;
&lt;br /&gt;
When sending a notification on your PHP, the client side will receive an Object with the following attributes:&lt;br /&gt;
&lt;br /&gt;
* type - type of the notification (as passed by php function)&lt;br /&gt;
* log - the log string passed from php notification&lt;br /&gt;
* args - This is the arguments that you passed on your notification method on php&lt;br /&gt;
* bIsTableMsg - is true when you use [[Main_game_logic:_yourgamename.game.php#NotifyAllPlayers|NotifyAllPlayers]] method (false otherwise)&lt;br /&gt;
* channelorig - information about table ID (formatted as : &amp;quot;/table/t[TABLE_NUMBER]&amp;quot;)&lt;br /&gt;
* gamenameorig - name of the game&lt;br /&gt;
* move_id - ID of the move associated with the notification&lt;br /&gt;
* table_id - ID of the table (comes as string)&lt;br /&gt;
* time - UNIX GMT timestamp&lt;br /&gt;
* uid - unique identifier of the notification&lt;br /&gt;
* h - unknown&lt;br /&gt;
&lt;br /&gt;
&#039;&#039; Note that those information were inferred from observation on console log. If an Admin can confirm/correct (and remove this line), you&#039;re welcome :)&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
=== Ignoring notifications ===&lt;br /&gt;
&lt;br /&gt;
Sometimes you need to ignore some notification on client side. You don&#039;t want them to be shown in game log and you don&#039;t want them to be handled.&lt;br /&gt;
&lt;br /&gt;
The most common use case is when a player gets private information. They will receive a specific notification (such as &amp;quot;You received Ace of Heart&amp;quot;), while other players would receive more generic notification (&amp;quot;Player received a card&amp;quot;).&lt;br /&gt;
&lt;br /&gt;
In X.game.php&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        $this-&amp;gt;notifyAllPlayers(&amp;quot;dealCard&amp;quot;, clienttranslate(&#039;${player_name} received a card&#039;), [&lt;br /&gt;
            &#039;player_id&#039; =&amp;gt; $playerId,&lt;br /&gt;
            &#039;player_name&#039; =&amp;gt; $this-&amp;gt;getActivePlayerName()&lt;br /&gt;
        ]);&lt;br /&gt;
&lt;br /&gt;
        $this-&amp;gt;notifyPlayer($playerId, &amp;quot;dealCardPrivate&amp;quot;, clienttranslate(&#039;You received ${cardName}&#039;), [&lt;br /&gt;
            &amp;quot;type&amp;quot; =&amp;gt; $card[&amp;quot;type&amp;quot;],&lt;br /&gt;
            &amp;quot;cardName&amp;quot; =&amp;gt; $this-&amp;gt;getCardName($card[&amp;quot;type&amp;quot;])&lt;br /&gt;
        ]);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The problem with this approach is that the active player will receive two notifications:&lt;br /&gt;
* Player1 received a card&lt;br /&gt;
* You received Ace of Hearts&lt;br /&gt;
&lt;br /&gt;
Hence, notification ignoring.&lt;br /&gt;
&lt;br /&gt;
NOTE: You can think that it would be possible to send such notification to all players except active just by using notifyPlayer and it seems to work. The problem however is that table spectators would miss such notification and their user interface (and game log) wouldn&#039;t be updated. Since there is no way to send notification just to spectators, ignoring the notification (or &amp;quot;filtering&amp;quot;) is the only reasonable solution.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;setIgnoreNotificationCheck(notif_type: string, predicate: ((notif: Notif)=&amp;gt;boolean))&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
This method will set a check whether any of notifications of specific type should be ignored.&lt;br /&gt;
&lt;br /&gt;
The parameters are:&lt;br /&gt;
* notif_type: type of the notification &lt;br /&gt;
* predicate (notif =&amp;gt; boolean): a function that will receive notif object and will return true if this specific notification should be ignored&lt;br /&gt;
&lt;br /&gt;
Before dispatching any notification of this type, the framework will call predicate to check whether notification should be ignored, if it return true - the notification will be dispatched, i.e. logged or handled.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    this.notifqueue.setIgnoreNotificationCheck( &#039;dealCard&#039;, (notif) =&amp;gt; (notif.args.player_id == this.player_id) );&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
IMPORTANT: Remember that this notification is ignored on the client side, but was still received by the client. Therefore it shouldn&#039;t contain any private information as cheaters can get it. In other words this is not a way to hide information.&lt;br /&gt;
&lt;br /&gt;
IMPORTANT: When a game is reloaded with F5 or when opening a turn based game, old notifications are replayed as history notification. They are used just to update the game log and are stripped of all arguments except player_id, i18n and any argument present in message. If you use and other argument in your predicate you should &#039;&#039;&#039;preserve&#039;&#039;&#039; it as explained [[Main_game_logic:_yourgamename.game.php#Notify_players|here]].&lt;br /&gt;
&lt;br /&gt;
=== Synchronous notifications ===&lt;br /&gt;
&lt;br /&gt;
When several notifications are received by your game interface, these notifications are processed immediately, one after the other, in the same exact order they have been generated in your PHP game logic.&lt;br /&gt;
&lt;br /&gt;
However, sometimes, you need to give some time to the players to figure out what happened on the game before jumping to the next notification. Indeed, in many games, there are a lot of automatic actions, and the computer is going to resolve all these actions very fast if you don&#039;t tell it not to do so.&lt;br /&gt;
&lt;br /&gt;
As an example, for Reversi, when someone is playing a disc, we want to wait 500 milliseconds before doing anything else in order the opponent player can figure out what move has been played.&lt;br /&gt;
&lt;br /&gt;
Here&#039;s how we do this, right after our subscription:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    dojo.subscribe( &#039;playDisc&#039;, this, &amp;quot;notif_playDisc&amp;quot; );&lt;br /&gt;
    this.notifqueue.setSynchronous( &#039;playDisc&#039;, 500 );   // Wait 500 milliseconds after executing the playDisc handler&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
-----&lt;br /&gt;
&lt;br /&gt;
It is also possible to control the delay timing dynamically (e.g., using notification args). As an example, maybe your notification &#039;cardPlayed&#039; should pause for a different amount of time depending on the number or type of cards played.&lt;br /&gt;
&lt;br /&gt;
For this case, use &#039;&#039;&#039;setSynchronous&#039;&#039;&#039; without specifying the duration and use &#039;&#039;&#039;setSynchronousDuration&#039;&#039;&#039; within the notification callback.&lt;br /&gt;
&lt;br /&gt;
* NOTE: If you forget to invoke &#039;&#039;&#039;setSynchronousDuration&#039;&#039;&#039;, the game will remain paused forever!&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
setupNotifications: function () {&lt;br /&gt;
    dojo.subscribe( &#039;cardPlayed&#039;, this, &#039;notif_cardPlayed&#039; );&lt;br /&gt;
    this.notifqueue.setSynchronous( &#039;cardPlayed&#039; ); // wait time is dynamic&lt;br /&gt;
    ...&lt;br /&gt;
},&lt;br /&gt;
&lt;br /&gt;
notif_cardPlayed: function (notif) {&lt;br /&gt;
    // MUST call setSynchronousDuration&lt;br /&gt;
&lt;br /&gt;
    // Example 1: From notification args (PHP)&lt;br /&gt;
    this.notifqueue.setSynchronousDuration(notif.args.duration);&lt;br /&gt;
    ...&lt;br /&gt;
&lt;br /&gt;
    // Or, example 2: Match the duration to a Dojo animation&lt;br /&gt;
    var anim = dojo.fx.combine([&lt;br /&gt;
        ...&lt;br /&gt;
    ]);&lt;br /&gt;
    anim.play();&lt;br /&gt;
    this.notifqueue.setSynchronousDuration(anim.duration);&lt;br /&gt;
},&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You can also manually call this.notifqueue.setSynchronousDuration(0) once client operations are finished, but be careful that even fast replay still has a path to call it.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;WARNING: combining synchronous and ignored notifications&#039;&#039;&#039;&lt;br /&gt;
You must be careful when combining dynamic synchronous durations (as described above) with ignored notifications. If you have a conditionally ignored notification like this (see below section):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;this.notifqueue.setIgnoreNotificationCheck( &#039;myNotif&#039;, (notif) =&amp;gt; (notif.args.player_id == this.player_id) /* or any other condition */ )&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
then you CANNOT do&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;this.notifqueue.setSynchronous(&#039;myNotif&#039;);&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
as, when the ignored check passes, the notification handler, in which `this.notifqueue.setSychronousDuration` is called, is never called and so the duration is never set and interface locking results.&lt;br /&gt;
&lt;br /&gt;
The workaround is to set a &amp;quot;dummy&amp;quot; time:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;this.notifqueue.setSynchronous(&#039;myNotif&#039;, 5000);&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
whose value is irrelevant but must be large enough to cover the time before the notification handler is called. The large value never actually comes into play because the notification is either ignored, or the synchronous duration is reset to a sensible value inside the handler.&lt;br /&gt;
&lt;br /&gt;
=== Pre-defined notification types ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;tableWindow&#039;&#039;&#039; - This defines notification to display [[Game_interface_logic:_yourgamename.js#Scoring_dialogs|Scoring Dialogs]], see below.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;message&#039;&#039;&#039; - This defines notification that shows on players log and have no other effect (technically any unhandled notification will do the same but its recommended to use this keyword for consistency)&lt;br /&gt;
&lt;br /&gt;
   // You can call this on php side without doing anything on client side&lt;br /&gt;
    self::notifyAllPlayers( &#039;message&#039;, clienttranslate(&#039;hello&#039;), [] );&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;simplePause&#039;&#039;&#039; - This notification will just delay other notifications, maybe useful if you know you need some extra time for animation or something. Requires a time parameter.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    self::notifyAllPlayers( &#039;simplePause&#039;, &#039;&#039;, [ &#039;time&#039; =&amp;gt; 500] ); // time is in milliseconds&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note: the following types are RESERVED by framework, do not use:&lt;br /&gt;
&lt;br /&gt;
gameStateChange gameStateChangePrivateArg gameStateMultipleActiveUpdate newActivePlayer playerstatus yourturnack clockalert tableInfosChanged playerEliminated tableDecision  archivewaitingdelay end_archivewaitingdelay replaywaitingdelay end_replaywaitingdelay replayinitialwaitingdelay end_replayinitialwaitingdelay aiPlayerWaitingDelay replay_has_ended updateSpectatorList  wouldlikethink updateReflexionTime undoRestorePoint resetInterfaceWithAllDatas zombieModeFail zombieModeFailWarning aiError skipTurnOfPlayer zombieBack allPlayersAreZombie gameResultNeutralized playerConcedeGame showTutorial showCursor showCursorClick skipTurnOfPlayerWarning  banFromTable resultsAvailable switchToTurnbased newPrivateState infomsg&lt;br /&gt;
&lt;br /&gt;
== Tooltips ==&lt;br /&gt;
&lt;br /&gt;
=== Adding static tooltips ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.addTooltip(nodeId: string, helpStringTranslated: string, actionStringTranslated: string, delay?: number): void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Add a simple text tooltip to the DOM node.&lt;br /&gt;
&lt;br /&gt;
Specify &#039;helpStringTranslated&#039; to display some information about &amp;quot;what is this game element?&amp;quot;.&lt;br /&gt;
Specify &#039;actionStringTranslated&#039; to display some information about &amp;quot;what happens when I click on this element?&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
You must specify both of the strings. You can only use one and specify an empty string (&#039;&#039;) for the other one.&lt;br /&gt;
&lt;br /&gt;
When you pass text directly function _() must be used for the text to be marked for translation! Except for empty string.&lt;br /&gt;
&lt;br /&gt;
Parameter &amp;quot;delay&amp;quot; is optional. It is primarily used to specify a zero delay for some game element when the tooltip gives really important information for the game - but remember: no essential information must be placed in tooltips as they won&#039;t be displayed in some browsers (see [[BGA_Studio_Guidelines|Guidelines]]).&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
   this.addTooltip( &#039;cardcount&#039;, _(&#039;Number of cards in hand&#039;), &#039;&#039; );&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note: this generates static tooltip and attaches to existing dom element, if you need to generate tooltip more dynamically you have to call that method every time information about object is updated or use completely different tehnique, see dynamic tooltips below.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.addTooltipHtml(nodeId: string, html: string, delay?: number): void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Add an HTML tooltip to the DOM node (for more elaborate content such as presenting a bigger version of a card).&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.addTooltipToClass(cssClass: string, helpStringTranslated: string, actionStringTranslated: string, delay?: number ): void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Add a simple text tooltip to all the DOM nodes set with this cssClass. See more details above for this.addTooltip.&lt;br /&gt;
     this.addTooltipToClass( &#039;meeple&#039;, _(&#039;This is A Meeple&#039;), _(&#039;Click to tickle&#039;) );&lt;br /&gt;
&lt;br /&gt;
IMPORTANT: all concerned nodes must exist and have IDs to get tooltips.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.addTooltipHtmlToClass(cssClass: string, html: string, delay?: number): void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Add an HTML tooltip to to all the DOM nodes set with this cssClass (for more elaborate content such as presenting a bigger version of a card).&lt;br /&gt;
&lt;br /&gt;
IMPORTANT: all concerned nodes must exist and have IDs to get tooltips.&lt;br /&gt;
&lt;br /&gt;
=== Removing static tooltips ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.removeTooltip(nodeId: string): void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Remove a tooltip from the DOM node with given id.&lt;br /&gt;
&lt;br /&gt;
=== Advanced tooltips ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;force tooltip to open&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
If you want to force tooltip to open in reaction to some other action, i.e. click you can do this&lt;br /&gt;
&lt;br /&gt;
   this.tooltips[id].open(id)&lt;br /&gt;
&lt;br /&gt;
where id is the id of the tooltip node where tooltip was installed.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;dynamic tooltips&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
See [[BGA_Studio_Cookbook#Dynamic_tooltips]]&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;tooltips on mobile&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Tooltips is very unreliable on mobile, it is recommended to implement some other method to obtaining same information,&lt;br /&gt;
such as simple click handler in dedicated &amp;quot;Help&amp;quot; mode or provide dedicated clickable areas such as corner of card.&lt;br /&gt;
&lt;br /&gt;
== Warning messages ==&lt;br /&gt;
&lt;br /&gt;
Sometimes, there is something important that is happening in the game and you have to make sure all players get the message. Most of the time, the evolution of the game situation or the game log is enough, but sometimes you need something more visible.&lt;br /&gt;
&lt;br /&gt;
Ex: someone fulfills one of the end of the game conditions, so this is the last turn.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.showMessage(msg: string, type: string): void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
showMessage shows a message in a big rectangular area on the top of the screen of the current player, and it dissapears after few seconds (also it will be in the log in some cases).&lt;br /&gt;
&lt;br /&gt;
* &amp;quot;msg&amp;quot; is the string to display. It should be translated.&lt;br /&gt;
* &amp;quot;type&amp;quot; can be set to &amp;quot;info&amp;quot;, &amp;quot;error&amp;quot;, &amp;quot;only_to_log&amp;quot; or custom string. If set to &amp;quot;info&amp;quot;, the message will be an informative message on a white background. If set to &amp;quot;error&amp;quot;, the message will be an error message on a red background and it will be added to log. If set to &amp;quot;only_to_log&amp;quot;, the message will be added to the game log but will not popup at the top of the screen.&lt;br /&gt;
If set to custom string, it will be transparent, to use custom type define &amp;quot;head_xxx&amp;quot; in css, where xxx is the type. For example if you want yellow warning, use &amp;quot;warning&amp;quot; as type and add this to css:&lt;br /&gt;
 .head_warning {&lt;br /&gt;
    background-color: #e6c66e;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
Important: the normal way to inform players about the progression of the game is the game log. The &amp;quot;showMessage&amp;quot; is intrusive and should not be used often.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    notif_messageinfo: function(notif) {&lt;br /&gt;
	if (!g_archive_mode) {&lt;br /&gt;
        	var message = this.format_string_recursive(notif.log, notif.args);&lt;br /&gt;
		this.showMessage(_(&#039;Announcement:&#039;) + &amp;quot; &amp;quot; + message, &#039;info&#039;);		&lt;br /&gt;
         }&lt;br /&gt;
    },&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Show message could be used on the client side to prevent user wrong moves before it is send to server.&lt;br /&gt;
Example from &#039;battleship&#039;:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
onGrid: function(event) {&lt;br /&gt;
     if (checkIfPlayerTriesToFireOnThemselves(event)) {&lt;br /&gt;
        this.showMessage(_(&#039;This is your own board silly!&#039;), &#039;error&#039;);&lt;br /&gt;
        return;&lt;br /&gt;
     }&lt;br /&gt;
     ...&lt;br /&gt;
},&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.showMoveUnauthorized(): void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Shows predefined user error that move is unauthorized now&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
onPet: function(event) {&lt;br /&gt;
     if (checkPet(event)==false) {&lt;br /&gt;
        this.showMoveUnauthorized();&lt;br /&gt;
        return;&lt;br /&gt;
     }&lt;br /&gt;
     ...&lt;br /&gt;
},&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Dialogs ==&lt;br /&gt;
&lt;br /&gt;
=== Confirmation dialog ===&lt;br /&gt;
&lt;br /&gt;
When an important action with a lot of consequences is triggered by the player, you may want to propose a confirmation dialog.&lt;br /&gt;
&lt;br /&gt;
CAREFUL: the general guideline of BGA is to AVOID the use of confirmation dialogs. Confirmation dialogs slow down the game and bother players. The players know that they have to pay attention to each move when they are playing online.&lt;br /&gt;
&lt;br /&gt;
The situations where you should use a confirmation dialog are the following:&lt;br /&gt;
* It must not happen very often during a game.&lt;br /&gt;
* It must be linked to an action that can really &amp;quot;kill a game&amp;quot; if the player does not pay attention.&lt;br /&gt;
* It must be something that can be done by mistake (ex: a link on the action status bar).&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.confirmationDialog(message: string, yesHandler: (param: any) =&amp;gt; void, noHandler?: (param: any) =&amp;gt; void, param?: any): void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
* message - message will be shown to user, use _() to translate&lt;br /&gt;
* yesHandler - non-optional handler to be called on yes&lt;br /&gt;
* noHandler - optional handler to called on no&lt;br /&gt;
* param - if specified, it will be passed to both handlers&lt;br /&gt;
NOTE: this is async function, it does not return anything and you should not do anything after, you must do everything in handlers&lt;br /&gt;
&lt;br /&gt;
How to display a confirmation dialog:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    this.confirmationDialog(_(&amp;quot;Are you sure you want to bake a pie?&amp;quot;), () =&amp;gt; {&lt;br /&gt;
      this.bakeThePie();&lt;br /&gt;
    });&lt;br /&gt;
    return; // nothing should be called or done after calling this, all action must be done in the handler&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
With param and both handlers&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    this.confirmationDialog(_(&amp;quot;Are you sure you want to bake a pie?&amp;quot;), &lt;br /&gt;
           (ingredient) =&amp;gt; this.bakeThePie(ingredient), &lt;br /&gt;
           (ingredient) =&amp;gt; console.log(`cancelled baking of ${ingredient}`), &lt;br /&gt;
           &#039;apple&#039;);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Multiple choice dialog ===&lt;br /&gt;
&lt;br /&gt;
You can use this dialog to give user a choice with small amount of options&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.multipleChoiceDialog(message: string, choices: string[], callback: (choice: number) =&amp;gt; void): void&#039;&#039;&#039;&lt;br /&gt;
* message - message will be shown to user, use _() to translate&lt;br /&gt;
* choices - array of choices&lt;br /&gt;
* callback - non-optional handler to be called on choice made, the choice parameter is the INDEX of the choice from the array of choices&lt;br /&gt;
&lt;br /&gt;
NOTE: this is async function, it does not return anything and you should not do anything after, you must do everything in handlers&lt;br /&gt;
NOTE: there is no cancel handler, so make sure you gave user a choice to get out of it&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    const keys = [&amp;quot;0&amp;quot;, &amp;quot;1&amp;quot;, &amp;quot;5&amp;quot;, &amp;quot;10&amp;quot;];&lt;br /&gt;
    this.multipleChoiceDialog(_(&amp;quot;How many bugs to fix?&amp;quot;), keys, (choice) =&amp;gt; {&lt;br /&gt;
      if (choice==0) return; // cancel operation, do not call server action&lt;br /&gt;
      var bugchoice = keys[choice]; // choice will be 0,1,2,3 here&lt;br /&gt;
      this.bgaPerformAction(&amp;quot;fixBugs&amp;quot;, { number: bugchoice });&lt;br /&gt;
    });&lt;br /&gt;
    return; // must return here&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Generic Dialogs ===&lt;br /&gt;
&lt;br /&gt;
As a general rule, you shouldn&#039;t use dialogs windows.&lt;br /&gt;
&lt;br /&gt;
BGA guidelines specify that all game elements should be displayed on the main screen. Players can eventually scroll down to see game elements they don&#039;t need to see anytime, and you may eventually create anchors to move between game area section. Of course dialogs windows are very practical, but the thing is: all players know how to scroll down, and not all players know how to show up your dialog window. In addition, when the dialog shows up, players can&#039;t access the other game components.&lt;br /&gt;
&lt;br /&gt;
Sometimes although, you need to display a dialog window. Here is how you do this:&lt;br /&gt;
&lt;br /&gt;
  // Create the new dialog over the play zone. You should store the handler in a member variable to access it later&lt;br /&gt;
  this.myDlg = new ebg.popindialog();&lt;br /&gt;
  this.myDlg.create( &#039;myDialogUniqueId&#039; );&lt;br /&gt;
  this.myDlg.setTitle( _(&amp;quot;my dialog title to translate&amp;quot;) );&lt;br /&gt;
  this.myDlg.setMaxWidth( 500 ); // Optional&lt;br /&gt;
  &lt;br /&gt;
  // Create the HTML of my dialog. &lt;br /&gt;
  // The best practice here is to use [[Game_layout:_view_and_template:_yourgamename.view.php_and_yourgamename_yourgamename.tpl#Javascript_templates|Javascript templates]]&lt;br /&gt;
  var html = this.format_block( &#039;jstpl_myDialogTemplate&#039;, { &lt;br /&gt;
                arg1: myArg1,&lt;br /&gt;
                arg2: myArg2,&lt;br /&gt;
                ...&lt;br /&gt;
            } );  &lt;br /&gt;
  &lt;br /&gt;
  // Show the dialog&lt;br /&gt;
  this.myDlg.setContent( html ); // Must be set before calling show() so that the size of the content is defined before positioning the dialog&lt;br /&gt;
  this.myDlg.show();&lt;br /&gt;
  &lt;br /&gt;
  // Now that the dialog has been displayed, you can connect your method to some dialog elements&lt;br /&gt;
  // Example, if you have an &amp;quot;OK&amp;quot; button in the HTML of your dialog:&lt;br /&gt;
  dojo.connect($(&#039;my_ok_button&#039;), &#039;onclick&#039;, this, (event) =&amp;gt; {&lt;br /&gt;
                event.preventDefault();&lt;br /&gt;
                this.myDlg.destroy();&lt;br /&gt;
            });&lt;br /&gt;
&lt;br /&gt;
If necessary, you can remove the default top right corner &#039;close&#039; icon, or replace the function called when it is clicked:&lt;br /&gt;
  // Removes the default close icon&lt;br /&gt;
  this.myDlg.hideCloseIcon();&lt;br /&gt;
&lt;br /&gt;
  // Replace the function call when it&#039;s clicked&lt;br /&gt;
  this.myDlg.replaceCloseCallback((event) =&amp;gt; { ... });&lt;br /&gt;
&lt;br /&gt;
=== Scoring dialogs ===&lt;br /&gt;
&lt;br /&gt;
Sometimes at the end of a round you want to display a big table that details the points wins in each section of the game.&lt;br /&gt;
&lt;br /&gt;
Example: in Hearts game, we display at the end of each round the number of &amp;quot;heart&amp;quot; cards collected by each player, the player who collected the Queen of Spades, and the total number of points loose by each player.&lt;br /&gt;
&lt;br /&gt;
Scoring dialogs are managed entirely on &#039;&#039;&#039;PHP side&#039;&#039;&#039;, but they are described here as their effects are visible only on client side.&lt;br /&gt;
&lt;br /&gt;
Displaying a scoring dialog is quite simple and is using a special notification type: &amp;quot;tableWindow&amp;quot;:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  // on PHP side:&lt;br /&gt;
  $this-&amp;gt;notifyAllPlayers( &amp;quot;tableWindow&amp;quot;, &#039;&#039;, array(&lt;br /&gt;
            &amp;quot;id&amp;quot; =&amp;gt; &#039;finalScoring&#039;,&lt;br /&gt;
            &amp;quot;title&amp;quot; =&amp;gt; clienttranslate(&amp;quot;Title of the scoring dialog&amp;quot;),&lt;br /&gt;
            &amp;quot;table&amp;quot; =&amp;gt; $table&lt;br /&gt;
        )); &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The &amp;quot;table&amp;quot; argument is a 2 dimensional PHP array that describes the table you want to display, line by line and column by column.&lt;br /&gt;
&lt;br /&gt;
Example: display an 3x3 array of strings&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
   $table = [&lt;br /&gt;
      [ &amp;quot;one&amp;quot;, &amp;quot;two&amp;quot;, &amp;quot;three&amp;quot; ],    // This is my first line&lt;br /&gt;
      [ &amp;quot;four&amp;quot;, &amp;quot;five&amp;quot;, &amp;quot;six&amp;quot; ],    // This is my second line&lt;br /&gt;
      [ &amp;quot;seven&amp;quot;, &amp;quot;height&amp;quot;, &amp;quot;nine&amp;quot; ]    // This is my third line&lt;br /&gt;
   ];&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
As you can see above, in each &amp;quot;cell&amp;quot; of your array you can display a simple string value. But you can also display a complex value with a template and associated arguments like this:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
   $table = [&lt;br /&gt;
      [ &amp;quot;one&amp;quot;, &amp;quot;two&amp;quot;, [ &amp;quot;str&amp;quot; =&amp;gt; clienttranslate(&amp;quot;a string with an ${argument}&amp;quot;), &amp;quot;args&amp;quot; =&amp;gt; [ &#039;argument&#039; =&amp;gt; &#039;argument_value&#039; ] ] ],&lt;br /&gt;
      [ &amp;quot;four&amp;quot;, &amp;quot;five&amp;quot;, &amp;quot;six&amp;quot; ], &lt;br /&gt;
      [ &amp;quot;seven&amp;quot;, &amp;quot;height&amp;quot;, &amp;quot;nine&amp;quot; ]&lt;br /&gt;
   ];&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This is especially useful when you want to display player names with colors. Example from &amp;quot;Hearts&amp;quot;:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        $firstRow = [ &#039;&#039; ];&lt;br /&gt;
        foreach( $players as $player_id =&amp;gt; $player )    {&lt;br /&gt;
            $cell = [ &#039;str&#039; =&amp;gt; &#039;${player_name}&#039;,&lt;br /&gt;
                      &#039;args&#039; =&amp;gt; [ &#039;player_name&#039; =&amp;gt; $player[&#039;player_name&#039;] ],&lt;br /&gt;
                      &#039;type&#039; =&amp;gt; &#039;header&#039;&lt;br /&gt;
                    ];&lt;br /&gt;
            $firstRow[] = $cell;&lt;br /&gt;
        }&lt;br /&gt;
        $table[] = $firstRow;&lt;br /&gt;
        ...&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You can also use three extra attributes in the parameter array for the notification:&lt;br /&gt;
* &#039;&#039;&#039;header&#039;&#039;&#039;: the content for this parameter displays before the table (also, the html will be parsed and player names will be colored according to the current game colors). &lt;br /&gt;
* &#039;&#039;&#039;footer&#039;&#039;&#039;: the content for this parameter displays after the table (no parsing for coloring the player names)&lt;br /&gt;
* &#039;&#039;&#039;closing&#039;&#039;&#039;: if this parameter is used, a button will be displayed with this label at the bottom of the popup and will allow players to close it (more easily than by clicking the top right &#039;cross&#039; icon).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
   $this-&amp;gt;notifyAllPlayers( &amp;quot;tableWindow&amp;quot;, &#039;&#039;, [&lt;br /&gt;
            &amp;quot;id&amp;quot; =&amp;gt; &#039;finalScoring&#039;,&lt;br /&gt;
            &amp;quot;title&amp;quot; =&amp;gt; clienttranslate(&amp;quot;Title of the scoring dialog&amp;quot;),&lt;br /&gt;
            &amp;quot;table&amp;quot; =&amp;gt; $table,&lt;br /&gt;
            &amp;quot;header&amp;quot; =&amp;gt; [&#039;str&#039; =&amp;gt; clienttranslate(&#039;Table header with parameter ${number}&#039;),&lt;br /&gt;
                                 &#039;args&#039; =&amp;gt; [ &#039;number&#039; =&amp;gt; 3 ],&lt;br /&gt;
                               ],&lt;br /&gt;
            &amp;quot;footer&amp;quot; =&amp;gt; &#039;&amp;lt;div class=&amp;quot;myfoot&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&#039;,&lt;br /&gt;
            &amp;quot;closing&amp;quot; =&amp;gt; clienttranslate( &amp;quot;Closing button label&amp;quot; )&lt;br /&gt;
        ] ); &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note: currently id is not used - so you cannot access resulting div by id on js side &lt;br /&gt;
&lt;br /&gt;
Note: any traslatable string have to be wrapped by clienttranslate() on top level OR it has to be recursive template. &lt;br /&gt;
&lt;br /&gt;
DO NOT DO THIS: &lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
   &amp;quot;footer&amp;quot; =&amp;gt; &#039;&amp;lt;div&amp;gt;&#039;.clienttranslate( &amp;quot;The end&amp;quot; ).&#039;&amp;lt;/div&amp;gt;&#039;, // this will not work for translations!!!&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Scoring animated display ===&lt;br /&gt;
&lt;br /&gt;
Sometimes, you may want to display a score value over an element to make the scoring easier to follow for the players (Terra Mystica final scoring for example).&lt;br /&gt;
You can do it with:&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.displayScoring(anchor_id: string, color: string, score: number | string, duration?: number, offset_x?: number, offset_y?: number): void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;anchor_id&#039;&#039;&#039;: ID of the html element to place the animated score onto (without the &#039;#&#039;) &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;color&#039;&#039;&#039;: hexadecimal RGB representation of the color (should be the color of the scoring player), but without a leading &#039;#&#039;.  For instance, &#039;ff0000&#039; for red.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;score&#039;&#039;&#039;: numeric score to display, prefixed by a &#039;+&#039; or &#039;-&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;duration&#039;&#039;&#039;: animation duration in milliseconds (optional, default is 1000)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;offset_x&#039;&#039;&#039; and &#039;&#039;&#039;offset_y&#039;&#039;&#039;: if both offset_x and offset_y are defined and not null, apply the following offset (in pixels) to the scoring animation. &lt;br /&gt;
Note that the score is centered in the anchor, so the offsets might have to be negative if you calculate the position.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Note: if you want to display successively each score, you can use &#039;&#039;this.notifqueue.setSynchronous()&#039;&#039; function.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    setupNotifications: function()   {&lt;br /&gt;
           dojo.subscribe( &#039;displayScoring&#039;, this, &amp;quot;notif_displayScoring&amp;quot; );&lt;br /&gt;
           ...&lt;br /&gt;
    }&lt;br /&gt;
...&lt;br /&gt;
&lt;br /&gt;
    notif_displayScoring: function(notif) {&lt;br /&gt;
            const duration = notif.args.duration?notif.args.duration:1000;&lt;br /&gt;
            this.notifqueue.setSynchronous(&#039;displayScoring&#039;, duration );&lt;br /&gt;
	    this.displayScoring( notif.args.target, notif.args.color, notif.args.score, duration);&lt;br /&gt;
    },&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Speech bubble ===&lt;br /&gt;
&lt;br /&gt;
For better interactivity in some games (Love Letter for example), you may use comic book style speech bubbles to express the players voices.&lt;br /&gt;
This is done with showBubble:&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.showBubble(anchor_id: string, text: string, delay?: number, duration?: number, custom_class?: string): void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
* anchor_id - where to attach the bubble&lt;br /&gt;
* text - what to put in bubble, can be html&lt;br /&gt;
* delay - delay in milliseconds (optional, default 0)&lt;br /&gt;
* duration -  duration of animation in milliseconds (optional, default 3000)&lt;br /&gt;
* custom_class - extra class to add to bubble (optional), if you need to override the default bubble style&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
   this.showBubble(&#039;meeple_2&#039;, _(&#039;Hello&#039;), 0, 1000, &#039;pink_bubble&#039;);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  notif_speechBubble(notif) {&lt;br /&gt;
    var html = this.format_string_recursive(notif.args.text, notif.args.args);&lt;br /&gt;
    this.showBubble(notif.args.target, html, notif.args.delay ?? 0, notif.args.duration ?? 1000);&lt;br /&gt;
  },&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Warning&#039;&#039;&#039;: if your bubble could overlap other active elements of the interface (buttons in particular), as it stays in place even after disappearing, you should use a custom class to give it the style &amp;quot;pointer-events: none;&amp;quot; in order to intercept click events.&lt;br /&gt;
&lt;br /&gt;
Note: If you want this visually, but want to take complete control over this bubble and its animation (for example to make it permanent) you can just use div with &#039;discussion_bubble&#039; class on it, and content of div is what will be shown.&lt;br /&gt;
&lt;br /&gt;
== Translations ==&lt;br /&gt;
&lt;br /&gt;
See [[Translations]]&lt;br /&gt;
&lt;br /&gt;
== Players panels ==&lt;br /&gt;
&lt;br /&gt;
=== Update players score ===&lt;br /&gt;
&lt;br /&gt;
The column player_score from the player table is automatically loaded into this.scoreCtrl and therefore into the stars location on the player board. This occurs sometime after the game setup() function. However this score must be updated as the game progresses using notifications.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Note: this.scoreCtrl[player_id] is object of class [[Counter]], you can use other counter API.&lt;br /&gt;
&lt;br /&gt;
Increase a player score (with a positive or negative number):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  this.scoreCtrl[ player_id ].incValue( score_delta );&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Set a player score to a specific value:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  this.scoreCtrl[ player_id ].setValue( new_score );&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Set a player score to a specific value with animation:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  this.scoreCtrl[ player_id ].toValue( new_score );&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Typical usage would be (that will process &#039;score&#039; notification):&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        setupNotifications : function() {&lt;br /&gt;
              ...&lt;br /&gt;
             dojo.subscribe(&#039;score&#039;, this, &amp;quot;notif_score&amp;quot;);&lt;br /&gt;
        },&lt;br /&gt;
        notif_score: function(notif) {&lt;br /&gt;
            this.scoreCtrl[notif.args.player_id].setValue(notif.args.player_score);&lt;br /&gt;
        },&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Adding stuff to player&#039;s panel ===&lt;br /&gt;
&lt;br /&gt;
At first, create a new &amp;quot;JS template&amp;quot; string in your template (tpl) file:&lt;br /&gt;
&lt;br /&gt;
(from Gomoku example)&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
var jstpl_player_board = &#039;\&amp;lt;div class=&amp;quot;cp_board&amp;quot;&amp;gt;\&lt;br /&gt;
    &amp;lt;div id=&amp;quot;stoneicon_p${id}&amp;quot; class=&amp;quot;gmk_stoneicon gmk_stoneicon_${color}&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&amp;lt;span id=&amp;quot;stonecount_p${id}&amp;quot;&amp;gt;0&amp;lt;/span&amp;gt;\&lt;br /&gt;
&amp;lt;/div&amp;gt;&#039;;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Then, you add this piece of code in your JS file to add this template to each player panel:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
            // Setting up player boards&lt;br /&gt;
            for( var player_id in gamedatas.players )&lt;br /&gt;
            {&lt;br /&gt;
                var player = gamedatas.players[player_id];&lt;br /&gt;
                         &lt;br /&gt;
                // Setting up players boards if needed&lt;br /&gt;
                var player_board_div = $(&#039;player_board_&#039;+player_id);&lt;br /&gt;
                dojo.place( this.format_block(&#039;jstpl_player_board&#039;, player ), player_board_div );&lt;br /&gt;
            }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
(Note: the code above is of course from your &amp;quot;setup&amp;quot; function in your Javascript).&lt;br /&gt;
&lt;br /&gt;
Very often, you have to distinguish current player and others players. In this case, you just have to create another JS template (ex: jstpl_otherplayer_board) and use it when &amp;quot;player_id&amp;quot; is different than &amp;quot;this.player_id&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Fixing Player Panel heights ===&lt;br /&gt;
&lt;br /&gt;
You may find that the player panels don&#039;t automatically resize when adding something to (or removing something from) a player panel while the display is in portrait mode (i.e. the player summary panels are at the top of the screen rather than down the right side).&lt;br /&gt;
&lt;br /&gt;
When this happens, call &amp;lt;pre&amp;gt;this.adaptPlayersPanels();&amp;lt;/pre&amp;gt; This recalculates the layout and also adjusts the position of the actionbar for you.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Player&#039;s panel disabling/enabling ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.disablePlayerPanel(player_id: number): void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Disable given player panel (the panel background become gray).&lt;br /&gt;
&lt;br /&gt;
Usually, this is used to signal that this played passes, or will be inactive during a while.&lt;br /&gt;
&lt;br /&gt;
Note that the only effect of this is visual. There are no consequences on the behaviour of the panel itself.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.enablePlayerPanel(player_id:number): void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Enable a player panel that has been disabled before.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.enableAllPlayerPanels(): void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Enable all player panels that has been disabled before.&lt;br /&gt;
&lt;br /&gt;
=== Player order ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.updatePlayerOrdering(): void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
This function makes sure that player order in player&#039;s panel matches this.gamedatas.playerorder and its normally called by framework.&lt;br /&gt;
You can call it yoursel if you change this.gamedatas.playerorder from notification.&lt;br /&gt;
Also you can override this function to change defaults  OR insert a non-player panel [[BGA_Studio_Cookbook#Inserting_non-player_panel]].&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Counters ===&lt;br /&gt;
Note: there is bga component called  &amp;quot;ebg/counter&amp;quot; this API is not using it, these methods&lt;br /&gt;
below declared right in core game. If you need animation for counters use ebg/counter&lt;br /&gt;
&lt;br /&gt;
To use this API just create a counter dom element like this (class does not really matter)&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 &amp;lt;div class=&amp;quot;counter&amp;quot; id=&amp;quot;bread&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
 &amp;lt;div class=&amp;quot;counter&amp;quot; id=&amp;quot;coin&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
The &amp;quot;bread&amp;quot; will the counter name.&lt;br /&gt;
&lt;br /&gt;
The php code should send all &amp;quot;counters&amp;quot; data from getAllDatas() method like this&lt;br /&gt;
&lt;br /&gt;
game.php&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  protected function getAllDatas() {&lt;br /&gt;
    // (the key must match counter_name)&lt;br /&gt;
    $result[&#039;counters&#039;]=[&lt;br /&gt;
        &#039;bread&#039; =&amp;gt; [ &lt;br /&gt;
         &#039;counter_name&#039; =&amp;gt; &#039;bread&#039;, &lt;br /&gt;
         &#039;counter_value&#039; =&amp;gt; 3&lt;br /&gt;
         ], &lt;br /&gt;
        &#039;coin&#039; =&amp;gt; [&lt;br /&gt;
          &#039;counter_name&#039; =&amp;gt; &#039;coin&#039;, &lt;br /&gt;
          &#039;counter_value&#039; =&amp;gt; 5&lt;br /&gt;
        ]&lt;br /&gt;
   ];&lt;br /&gt;
   return $result;&lt;br /&gt;
  }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;setCounter(counter_name: stirng, new_value: string | number): void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
updates the global this.gamedatas.counters and value of node $(counter_name)&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  notif_counter: function(notif) { &lt;br /&gt;
    this.setCounter(notif.args.counter_name, notif.args.counter_value);&lt;br /&gt;
  },&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;incCounter(counter_name: string, delta: number): void&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  notif_counter : function(notif) {&lt;br /&gt;
    this.incCounter(notif.args.counter_name, notif.args.inc);&lt;br /&gt;
  },&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;updateCounters(counters: object): void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Useful for updating game counters in the player panel (such as resources). &lt;br /&gt;
&#039;counters&#039; arg is map of counters (the key must match counter_name)&lt;br /&gt;
  {&lt;br /&gt;
    &#039;bread&#039;: { &lt;br /&gt;
         &#039;counter_name&#039; : &#039;bread&#039;, &lt;br /&gt;
         &#039;counter_value&#039; =&amp;gt; 3&lt;br /&gt;
    }, &lt;br /&gt;
    &#039;coin&#039;: { &lt;br /&gt;
         &#039;counter_name&#039; : &#039;coin&#039;, &lt;br /&gt;
         &#039;counter_value&#039; =&amp;gt; 5&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
All counters MUST be referenced in this.gamedatas.counters (means they should be send from php) and will be updated.&lt;br /&gt;
DOM objects referenced by &#039;counter_name&#039; will have their innerHTML updated with &#039;counter_value&#039;.&lt;br /&gt;
&lt;br /&gt;
Usually you call this from notification&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
                        notif_counter : function(notif) {&lt;br /&gt;
                            this.updateCounters(notif.args.counters);&lt;br /&gt;
                        },&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== BGA GUI components ==&lt;br /&gt;
&lt;br /&gt;
BGA framework provides some useful ready-to-use components for the game interface:&lt;br /&gt;
&lt;br /&gt;
[[Studio#BGA_Studio_game_components_reference]]&lt;br /&gt;
&lt;br /&gt;
Note that each time you are using an additional component, you must declare it at the top of your Javascript file in the list of modules used.&lt;br /&gt;
&lt;br /&gt;
Example if you are using &amp;quot;ebg.stock&amp;quot;:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
define([&lt;br /&gt;
    &amp;quot;dojo&amp;quot;,&amp;quot;dojo/_base/declare&amp;quot;,&lt;br /&gt;
    &amp;quot;ebg/core/gamegui&amp;quot;,&lt;br /&gt;
    &amp;quot;ebg/counter&amp;quot;,&lt;br /&gt;
    &amp;quot;ebg/stock&amp;quot;  /// &amp;lt;=== we are using ebg.stock module&lt;br /&gt;
],&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== BGA Buttons ==&lt;br /&gt;
&lt;br /&gt;
=== Basic Button ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.addActionButton(id: string, label: string, method: string | eventhandler, destination?: string, blinking?: boolean, color?: string): void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
You can use this method to add an action button in the main action status bar (or other places).&lt;br /&gt;
&lt;br /&gt;
Arguments:&lt;br /&gt;
* id: an element ID that should be unique in your HTML DOM document.&lt;br /&gt;
* label: the text of the button. Should be translatable (use _() function). Note: this can also be any html, such as &amp;quot;&amp;lt;div class=&#039;brick&#039;&amp;gt;&amp;lt;/div&amp;gt;&amp;quot;, see example below on how to make image action buttons.&lt;br /&gt;
* method: the name of your method that must be triggered when the player clicks on this button (can be name of the method on game class or handler).&lt;br /&gt;
* destination (optional): id of parent on where to add button, ONLY use in rare cases if location is not action bar. Use &#039;&#039;&#039;null&#039;&#039;&#039; as value if you need to specify other arguments.&lt;br /&gt;
* blinking (optional): if set to &#039;&#039;&#039;true&#039;&#039;&#039;, the button is going blink to catch player&#039;s attention. Please DO NOT abuse blinking button. If you need button to blink after some time passed add class &#039;blinking&#039; to the button later.&lt;br /&gt;
* color: could be &#039;&#039;&#039;blue&#039;&#039;&#039; (default), &#039;&#039;&#039;red&#039;&#039;&#039;,&#039;&#039;&#039;gray&#039;&#039;&#039; or &#039;&#039;&#039;none&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
You should only use this method in your &amp;quot;onUpdateActionButtons&amp;quot; method. Usually, you use it like this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        onUpdateActionButtons: function( stateName, args ) {                      &lt;br /&gt;
            if (this.isCurrentPlayerActive()) {            &lt;br /&gt;
                switch( stateName ) {&lt;br /&gt;
                case &#039;giveCards&#039;:&lt;br /&gt;
                    this.addActionButton( &#039;giveCards_button&#039;, _(&#039;Give selected cards&#039;), &#039;onGiveCards&#039; ); &lt;br /&gt;
                    this.addActionButton( &#039;pass_button&#039;, _(&#039;Pass&#039;), () =&amp;gt; this.bgaPerformAction(&#039;actPass&#039;) ); &lt;br /&gt;
                    break;&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        },   &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In the example above, we are adding a &amp;quot;Give selected cards&amp;quot; button in the case we are on game state &amp;quot;giveCards&amp;quot;. When player clicks on this button, it triggers our &amp;quot;onGiveCards&amp;quot; method.&lt;br /&gt;
&lt;br /&gt;
Example using blinking red button:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    this.addActionButton( &#039;button_confirm&#039;, _(&#039;Confirm?&#039;), &#039;onConfirm&#039;, null, true, &#039;red&#039;); &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If you want to call the handler with arguments, you can use arrow functions, like this:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
     this.addActionButton( &#039;commit_button&#039;, _(&#039;Confirm&#039;), () =&amp;gt; this.onConfirm(this.selectedCardId), null, false, &#039;red&#039;); &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Image Button ===&lt;br /&gt;
&lt;br /&gt;
You can use the same method, but add extra class to a button to disable the padding and style it, i.e.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
this.addActionButton( &#039;button_brick&#039;, &#039;&amp;lt;div class=&amp;quot;brick&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&#039;, ()=&amp;gt;{... on brick ...}, null, null, &#039;gray&#039;); &lt;br /&gt;
dojo.addClass(&#039;button_brick&#039;,&#039;bgaimagebutton&#039;);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
where&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
.bgaimagebutton {&lt;br /&gt;
  padding: 0px 12px;&lt;br /&gt;
  min-height: 28px;&lt;br /&gt;
  border: none;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If you use this a lot, you can define a helper function, i.e.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
 * This method can be used instead of addActionButton, to add a button which is an image (i.e. resource). Can be useful when player&lt;br /&gt;
 * need to make a choice of resources or tokens.&lt;br /&gt;
 */&lt;br /&gt;
addImageActionButton: function(id, div, handler, bcolor, tooltip) {&lt;br /&gt;
	if (typeof bcolor == &amp;quot;undefined&amp;quot;) {&lt;br /&gt;
		bcolor = &amp;quot;gray&amp;quot;;&lt;br /&gt;
	}&lt;br /&gt;
	// this will actually make a transparent button id color = gray&lt;br /&gt;
	this.addActionButton(id, div, handler, null, false, bcolor);&lt;br /&gt;
	// remove border, for images it better without&lt;br /&gt;
	dojo.style(id, &amp;quot;border&amp;quot;, &amp;quot;none&amp;quot;);&lt;br /&gt;
	// but add shadow style (box-shadow, see css)&lt;br /&gt;
	dojo.addClass(id, &amp;quot;shadow bgaimagebutton&amp;quot;);&lt;br /&gt;
	// you can also add additional styles, such as background&lt;br /&gt;
	if (tooltip) {&lt;br /&gt;
		dojo.attr(id, &amp;quot;title&amp;quot;, tooltip);&lt;br /&gt;
	}&lt;br /&gt;
	return $(id);&lt;br /&gt;
},&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Disabling Button ===&lt;br /&gt;
&lt;br /&gt;
You can disable the &#039;&#039;&#039;bgabutton&#039;&#039;&#039; by adding the css class &#039;&#039;&#039;disabled&#039;&#039;&#039; in you js. The disabled button is still visible but is grey and not clickable.&lt;br /&gt;
For example in the &#039;&#039;&#039;onUpdateActionButtons&#039;&#039;&#039; : &lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
this.addActionButton(&#039;play_button_id&#039;, _(&#039;Play 1 to 3 cards&#039;), &#039;playFunctionButton&#039;); &lt;br /&gt;
if (condition) {&lt;br /&gt;
  dojo.addClass(&#039;play_button_id&#039;, &#039;disabled&#039;);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Custom Buttons ===&lt;br /&gt;
&lt;br /&gt;
You can create a custom button, but the BGA framework provides a standard button that requires only .css classes: &#039;&#039;&#039;bgabutton&#039;&#039;&#039; and &#039;&#039;&#039;bgabutton_${color}&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Examples:&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;a href=&amp;quot;#&amp;quot; id=&amp;quot;my_button_id&amp;quot; class=&amp;quot;bgabutton bgabutton_blue&amp;quot;&amp;gt;&amp;lt;span&amp;gt;My blue button&amp;lt;/span&amp;gt;&amp;lt;/a&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;a href=&amp;quot;#&amp;quot; id=&amp;quot;my_button_id&amp;quot; class=&amp;quot;bgabutton bgabutton_red bgabutton_big&amp;quot;&amp;gt;&amp;lt;span&amp;gt;My big red button&amp;lt;/span&amp;gt;&amp;lt;/a&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note&#039;&#039;&#039;: To see it in action, check out &#039;&#039;Coloretto&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
=== Button outside of action bar ===&lt;br /&gt;
&lt;br /&gt;
Use addActionButton() method with destination argument set&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
this.addActionButton( &#039;commit_button&#039;, _(&#039;Confirm&#039;), &#039;onConfirm&#039;, &#039;player_board&#039;, true, &#039;red&#039;); &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
in example above the button will be place on object with id &#039;player_board&#039;&lt;br /&gt;
&lt;br /&gt;
== Image loading ==&lt;br /&gt;
&lt;br /&gt;
See also [[Game_art:_img_directory]].&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Be careful&#039;&#039;&#039;: by default, ALL images of your img directory are loaded on a player&#039;s browser when he loads the game. For this reason, don&#039;t let in your img directory images that are not useful, otherwise it&#039;s going to slowdown the game load.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.dontPreloadImage(image_file_name: string)&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Using dontPreloadImage, you tell the interface to not preload a specific image in your img directory.&lt;br /&gt;
&lt;br /&gt;
Example of use:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
this.dontPreloadImage( &#039;cards.png&#039; );&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This is particularly useful if for example you have 2 different themes for a game. To accelerate the loading of the game, you can specify to not preload images corresponding to the other theme.&lt;br /&gt;
&lt;br /&gt;
Another example of use: in &amp;quot;Gosu&amp;quot; game with Kamakor extension, you play with 5 sets of cards among 10 available. Cards images are organized by sets, and we only preload the images corresponding to the 5 current sets with &#039;&#039;&#039;ensureSpecificGameImageLoading( image_file_names_array )&#039;&#039;&#039;.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
// By default, do not preload anything&lt;br /&gt;
this.dontPreloadImage( &#039;cards.png&#039; );&lt;br /&gt;
this.dontPreloadImage( &#039;clan1.png&#039; );&lt;br /&gt;
this.dontPreloadImage( &#039;clan2.png&#039; );&lt;br /&gt;
this.dontPreloadImage( &#039;clan3.png&#039; );&lt;br /&gt;
this.dontPreloadImage( &#039;clan4.png&#039; );&lt;br /&gt;
this.dontPreloadImage( &#039;clan5.png&#039; );&lt;br /&gt;
this.dontPreloadImage( &#039;clan6.png&#039; );&lt;br /&gt;
this.dontPreloadImage( &#039;clan7.png&#039; );&lt;br /&gt;
this.dontPreloadImage( &#039;clan8.png&#039; );&lt;br /&gt;
this.dontPreloadImage( &#039;clan9.png&#039; );&lt;br /&gt;
this.dontPreloadImage( &#039;clan10.png&#039; );&lt;br /&gt;
var to_preload = [];&lt;br /&gt;
for( i in this.gamedatas.clans )&lt;br /&gt;
{&lt;br /&gt;
	var clan_id = this.gamedatas.clans[i];&lt;br /&gt;
	to_preload.push( &#039;clan&#039;+clan_id+&#039;.png&#039; );&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
this.ensureSpecificGameImageLoading( to_preload );&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note:&#039;&#039;&#039; You don&#039;t need to specify to not preload game box images (game_box.png, game_box75.png...) since they are not preloaded by default.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.ensureSpecificGameImageLoading(list: string[])&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
This is oppostive of dontPreloadImage - its ensure specific images is loaded. Note: only makes sense if preload list is empty, otherwise everything is loaded anyway&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;load specific images&#039;&#039;&#039;&lt;br /&gt;
All images that will be preloaded stored in g_img_preload. If you want to override it directly - there is no API, but you can do this in GAME constructor&lt;br /&gt;
&lt;br /&gt;
          g_img_preload = [&#039;tokens.png&#039;, &#039;trains.png&#039;, &#039;loc_plan.png&#039;, &#039;eng.png&#039;, &#039;eng-back.png&#039;];&lt;br /&gt;
&lt;br /&gt;
You can also set it to empty array and call ensureSpecificGameImageLoading() on specific images&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Sounds ==&lt;br /&gt;
&lt;br /&gt;
Add a custom sound and make it load with your interface:&lt;br /&gt;
&lt;br /&gt;
Add this in your template (.tpl) file:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;audio id=&amp;quot;audiosrc_&amp;lt;gamename&amp;gt;_&amp;lt;yoursoundname&amp;gt;&amp;quot; src=&amp;quot;{GAMETHEMEURL}img/&amp;lt;gamename&amp;gt;_&amp;lt;yoursoundname&amp;gt;.mp3&amp;quot; preload=&amp;quot;none&amp;quot; autobuffer&amp;gt;&amp;lt;/audio&amp;gt;&lt;br /&gt;
&amp;lt;audio id=&amp;quot;audiosrc_o_&amp;lt;gamename&amp;gt;_&amp;lt;yoursoundname&amp;gt;&amp;quot; src=&amp;quot;{GAMETHEMEURL}img/&amp;lt;gamename&amp;gt;_&amp;lt;yoursoundname&amp;gt;.ogg&amp;quot; preload=&amp;quot;none&amp;quot; autobuffer&amp;gt;&amp;lt;/audio&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note: this is a requirement to provide both a mp3 and a ogg file with the names &amp;lt;code&amp;gt;&amp;lt;gamename&amp;gt;_&amp;lt;yoursoundname&amp;gt;[.ogg][.mp3]&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Play the sound (from your .js file):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
playSound(&#039;&amp;lt;gamename&amp;gt;_&amp;lt;yoursoundname&amp;gt;&#039;);   // do not add &#039;this.&#039; - its a global function&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Disable the standard &amp;quot;move&amp;quot; sound for this move (to replace it with your custom sound):&lt;br /&gt;
&lt;br /&gt;
Add this to your notification handler:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
this.disableNextMoveSound();&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note: it only disable the sound for the next move.&lt;br /&gt;
&lt;br /&gt;
== Title bar and states ==&lt;br /&gt;
&lt;br /&gt;
=== Client states ===&lt;br /&gt;
&lt;br /&gt;
Client states is a way to simulate the state transition but without actually going&lt;br /&gt;
to server. It is usefull when you need to ask user multiple questions before you&lt;br /&gt;
send things to server&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.setClientState(newState: string, args: object)&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
     this.setClientState(&amp;quot;client_playerPicksLocation&amp;quot;, {&lt;br /&gt;
                               descriptionmyturn : _(&amp;quot;${you} must select location&amp;quot;),&lt;br /&gt;
                           });&lt;br /&gt;
&lt;br /&gt;
For more information see [[BGA_Studio_Cookbook#Multi_Step_Interactions:_Select_Worker.2FPlace_Worker_-_Using_Client_States]]&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.restoreServerGameState()&#039;&#039;&#039;&lt;br /&gt;
If you are in client state it will restore the current server state (cheap undo)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.on_client_state&#039;&#039;&#039;&lt;br /&gt;
Boolean indicating that we are in client state&lt;br /&gt;
&lt;br /&gt;
=== Title bar ===&lt;br /&gt;
If you simply want to show something in title bar you can do it directly &lt;br /&gt;
     $(&#039;pagemaintitletext&#039;).innerHTML = text;&lt;br /&gt;
&lt;br /&gt;
This however will not work with parameters and will not draw You in color,&lt;br /&gt;
if you want to do proper args rendering use method below&lt;br /&gt;
&lt;br /&gt;
;&#039;&#039;&#039;this.removeActionButtons()&#039;&#039;&#039;&lt;br /&gt;
Removes all buttons from title bar&lt;br /&gt;
&lt;br /&gt;
;&#039;&#039;&#039;this.updatePageTitle()&#039;&#039;&#039;&lt;br /&gt;
:This function allows to update the current page title and turn description according to the game state arguments. If the current game state description this.gamedatas.gamestate.descriptionmyturn is modified before calling this function it allows to update the turn description without changing state. This will handle arguments substitutions properly.&lt;br /&gt;
&lt;br /&gt;
Note: this functional also will calls this.onUpdateActionButtons, if you want different buttons then state defaults, use method in example to replace them, if it becomes too clumsy use client states (see above)&lt;br /&gt;
&lt;br /&gt;
Example from Terra Mystica:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
onClickFavorTile: function( evt ) {&lt;br /&gt;
    ...&lt;br /&gt;
    if ( ... ) {&lt;br /&gt;
        this.gamedatas.gamestate.descriptionmyturn = _(&#039;Special action: &#039;) + _(&#039;Advance 1 space	on a Cult track&#039;);&lt;br /&gt;
        this.updatePageTitle();&lt;br /&gt;
        this.removeActionButtons();&lt;br /&gt;
        this.addActionButton( ... );&lt;br /&gt;
         ...&lt;br /&gt;
        return;&lt;br /&gt;
    }&lt;br /&gt;
    ...&lt;br /&gt;
&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== User preferences ==&lt;br /&gt;
&#039;&#039;&#039;this.getGameUserPreference(pref_id)&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Return the value of a user preference. It will return the value currently selected in the select combo box, in the top-right menu.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.setGameUserPreference(pref_id, value)&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Programmatically change a user preference. It will have the same effect as if the player changed the value in the select combo box, in the top-right menu.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.onGameUserPreferenceChanged&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
A callback you can define if you want to be notified when a user changes a user preference.&lt;br /&gt;
&lt;br /&gt;
Example:&amp;lt;pre&amp;gt;&lt;br /&gt;
onGameUserPreferenceChanged: function(pref_id, pref_value) {&lt;br /&gt;
  switch (pref_id) {&lt;br /&gt;
    case 201: &lt;br /&gt;
      document.getElementsByTagName(&#039;html&#039;)[0].classList.toggle(&#039;dark-background&#039;, pref_value == 2);&lt;br /&gt;
      break;&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Other useful stuff ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;dojo.hitch&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
With dojo.hitch, you can create a callback function that will run with your game object context whatever happen.&lt;br /&gt;
&lt;br /&gt;
Typical example: display a BGA confirmation dialog with a callback function created with dojo.hitch:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        this.confirmationDialog( _(&#039;Are you sure you want to make this?&#039;), dojo.hitch( this, function() {&lt;br /&gt;
            this.bgaPerformAction(&#039;makeThis&#039;);&lt;br /&gt;
        } ) );   &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In the example above, using dojo.hitch, we ensure that the &amp;quot;this&amp;quot; object will be set when the callback is called.&lt;br /&gt;
&lt;br /&gt;
NOTE: In modern JS there are lambdas that eliminate need for that, the example above will look like this&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        this.confirmationDialog( _(&#039;Are you sure you want to make this?&#039;), () =&amp;gt; this.bgaPerformAction( &#039;makeThis&#039;) );   &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
;&#039;&#039;&#039;onScreenWidthChange()&#039;&#039;&#039;&lt;br /&gt;
:This function can be overridden in your game to manage some resizing on the client side when the browser window is resized. This function is also triggered at load time, so it can be used to adapt to the :viewport size at the start of the game too.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
; this.bRealtime&lt;br /&gt;
: Return true if the game is in realtime. Note that having a distinct behavior in realtime and turn-based should be exceptional.&lt;br /&gt;
&lt;br /&gt;
; g_replayFrom&lt;br /&gt;
: Global contains replay number in live game, it is set to undefined (i.e. not set) when it is not a replay mode, so consequentially the good check is &#039;&#039;&#039;typeof g_replayFrom != &#039;undefined&#039;&#039;&#039;&#039; which returns true if the game is in replay mode &amp;lt;i&amp;gt;during the game&amp;lt;/i&amp;gt; (the game is ongoing but the user clicked &amp;quot;replay from this move&amp;quot; in the log)&lt;br /&gt;
&lt;br /&gt;
; g_archive_mode&lt;br /&gt;
: Returns true if the game is in archive mode &amp;lt;i&amp;gt;after the game&amp;lt;/i&amp;gt; (the game has ended)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
; this.instantaneousMode&lt;br /&gt;
: Returns true during replay/archive mode if animations should be skipped. Only needed if you are doing custom animations. (The BGA-provided animation functions like &amp;lt;i&amp;gt;this.slideToObject()&amp;lt;/i&amp;gt; automatically handle instantaneous mode.)&lt;br /&gt;
: Technically, when you click &amp;quot;replay from move #20&amp;quot;, the system replays the game from the very beginning with moves 0 - 19 happening in instantaneous mode and moves 20+ happening in normal mode.&lt;br /&gt;
&lt;br /&gt;
; g_tutorialwritten&lt;br /&gt;
: Returns an object like the below if the game is in tutorial mode, or undefined otherwise. Tutorial mode is a special case of archive mode where comments have been added to a previous game to teach new players the rules.&lt;br /&gt;
    {&lt;br /&gt;
        author: &amp;quot;91577332&amp;quot;,&lt;br /&gt;
        id: &amp;quot;576&amp;quot;,&lt;br /&gt;
        mode: &amp;quot;view&amp;quot;&lt;br /&gt;
        status: &amp;quot;alpha&amp;quot;&lt;br /&gt;
        version_override: null&lt;br /&gt;
        viewer_id: &amp;quot;84554161&amp;quot;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;getBgaEnvironment(): string&#039;&#039;&#039;&lt;br /&gt;
: Returns &amp;quot;studio&amp;quot; for studio and &amp;quot;prod&amp;quot; for production environment (i.e. where games current runs). Only useful for debbugging hooks.&lt;br /&gt;
Note: alpha server is also &amp;quot;prod&amp;quot;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Category:Studio]]&lt;/div&gt;</summary>
		<author><name>Sguzzer Gunayer</name></author>
	</entry>
	<entry>
		<id>https://en.doc.boardgamearena.com/index.php?title=Game_interface_logic:_Game.js&amp;diff=22737</id>
		<title>Game interface logic: Game.js</title>
		<link rel="alternate" type="text/html" href="https://en.doc.boardgamearena.com/index.php?title=Game_interface_logic:_Game.js&amp;diff=22737"/>
		<updated>2024-09-25T18:10:32Z</updated>

		<summary type="html">&lt;p&gt;Sguzzer Gunayer: /* Ignoring notifications */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Studio_Framework_Navigation}}&lt;br /&gt;
&lt;br /&gt;
__TOC__&lt;br /&gt;
&lt;br /&gt;
This is the main file for your game interface. Here you will define:&lt;br /&gt;
&lt;br /&gt;
* Which actions on the page will generate calls to the server.&lt;br /&gt;
* What happens when you get a notification for a change from the server and how it will show in the browser. &lt;br /&gt;
* Setup user interface&lt;br /&gt;
&lt;br /&gt;
== File structure ==&lt;br /&gt;
&lt;br /&gt;
The details of how the file is structured are described below with comments in the code skeleton provided to you.&lt;br /&gt;
&lt;br /&gt;
Here is the basic structure:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;constructor&#039;&#039;&#039;: here you can define global variables for your whole interface.&lt;br /&gt;
* &#039;&#039;&#039;setup&#039;&#039;&#039;: this method is called when the page is refreshed, and sets up the game interface.&lt;br /&gt;
* &#039;&#039;&#039;onEnteringState&#039;&#039;&#039;: this method is called when entering a new game state. You can use it to customize the view for each game state.&lt;br /&gt;
* &#039;&#039;&#039;onLeavingState&#039;&#039;&#039;: this method is called when leaving a game state.&lt;br /&gt;
* &#039;&#039;&#039;onUpdateActionButtons&#039;&#039;&#039;: called on state changes, in order to add action buttons to the status bar. Note: in a multipleactiveplayer state, it will be called when another player has become inactive.&lt;br /&gt;
* &#039;&#039;(utility methods)&#039;&#039;: this is where you can define your utility methods.&lt;br /&gt;
* &#039;&#039;(player&#039;s actions)&#039;&#039;: this is where you can write your handlers for player actions on the interface (example: click on an item).&lt;br /&gt;
* &#039;&#039;&#039;setupNotifications&#039;&#039;&#039;: this method associates notifications with notification handlers. For each game notification, you can trigger a javascript method to handle it and update the game interface.&lt;br /&gt;
* &#039;&#039;(notification handlers)&#039;&#039;: this is where you define the notifications handlers associated with notifications in &#039;&#039;&#039;setupNotifications&#039;&#039;&#039;, above.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
More details:&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;setup(gamedatas: object)            &#039;&#039;&#039;&lt;br /&gt;
This method must set up the game user interface according to current game situation specified in parameters.&lt;br /&gt;
The method is called each time the game interface is displayed to a player, ie:&lt;br /&gt;
&lt;br /&gt;
* when the game starts&lt;br /&gt;
* when a player opens a game in the browser later &lt;br /&gt;
* when a player refreshes the game page (F5)&lt;br /&gt;
* when player does a server side Undo&lt;br /&gt;
&lt;br /&gt;
&amp;quot;gamedatas&amp;quot; argument contains all data retrieved by your &amp;quot;getAllDatas&amp;quot; PHP method and some more.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;onEnteringState(stateName: string, args: { args: any } | null): void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
This method is called each time we enter a new game state.&lt;br /&gt;
You can use this method to perform some user interface changes at this moment.&lt;br /&gt;
To access state arguments passed via calling php arg* method use args?.args.&lt;br /&gt;
Typically you would do something only for active player, using this.isCurrentPlayerActive() check.&lt;br /&gt;
It is also called (for the current game state only) when doing a browser refresh (after the setup method is called).&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Warning&#039;&#039;&#039;: for multipleactiveplayer states:&lt;br /&gt;
the active players are NOT active yet so you must use onUpdateActionButtons to perform the client side operation which depends on a player active/inactive status.&lt;br /&gt;
If you are doing initialization of some structures which do not depend on the active player, you can just replace (this.isCurrentPlayerActive()) with (!this.isSpectator) &lt;br /&gt;
for the main switch in that method.&lt;br /&gt;
&lt;br /&gt;
See more details in [[Your_game_state_machine:_states.inc.php#Difference_between_Single_active_and_Multi_active_states]]&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;onLeavingState(stateName: string): void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
This method is called each time we leave a game state.&lt;br /&gt;
You can use this method to perform some user interface changes at this point (i.e. cleanup).&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;onUpdateActionButtons(stateName: string, args: object | null): void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
In this method you can manage &amp;quot;action buttons&amp;quot; that are displayed in the action status bar and highlight active UI elements.&lt;br /&gt;
To access state arguments passed via calling php arg* method use &#039;&#039;&#039;args&#039;&#039;&#039; parameter. Note: args can be null! For &#039;&#039;&#039;game&#039;&#039;&#039; states and when you don&#039;t supply state args function - it is null.&lt;br /&gt;
This method is called when the active or multiactive player changes. In a classic &amp;quot;activePlayer&amp;quot; state this method is called before the onEnteringState state.&lt;br /&gt;
In multipleactiveplayer state it is a mess. The sequencing of calls depends on whether you get into that state from transitions OR from reloading the whole game (i.e. F5).&lt;br /&gt;
&lt;br /&gt;
See more details in [[Your_game_state_machine:_states.inc.php#Difference_between_Single_active_and_Multi_active_states]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Dojo framework ==&lt;br /&gt;
&lt;br /&gt;
BGA uses the [http://dojotoolkit.org/ Dojo Javascript framework].&lt;br /&gt;
&lt;br /&gt;
The Dojo framework allows us to do complex things more easily. The BGA framework uses Dojo extensively.&lt;br /&gt;
&lt;br /&gt;
To implement a game, you only need to use a few parts of the Dojo framework. All the Dojo methods you need are described on this page.&lt;br /&gt;
&lt;br /&gt;
== Javascript minimization (after July 2020) ==&lt;br /&gt;
&lt;br /&gt;
For performance reasons, when deploying a game the javascript code is minimized using &#039;&#039;&#039;terser&#039;&#039;&#039; (https://github.com/terser/terser). This minifier works with modern javascript syntax. From your project &amp;quot;Manage game&amp;quot; page, you can now test a minified version of your javascript on the studio (and revert to the original).&lt;br /&gt;
&lt;br /&gt;
NB: it has been reported that there is an issue with this minifier and percentage values for opacity.&lt;br /&gt;
&lt;br /&gt;
== Accessing Players Information ==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.player_id: number&#039;&#039;&#039;&lt;br /&gt;
id of the player who is looking at the game. The player may not be part of the game (i.e. spectator)&lt;br /&gt;
  if (notif.args.player_id == this.player_id) {&lt;br /&gt;
    ...&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.isSpectator: boolean&#039;&#039;&#039;&lt;br /&gt;
Flag set to true if the user at the table is a spectator (not a player).&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    if (this.isSpectator) {&lt;br /&gt;
        this.player_color = &#039;ffffff&#039;;&lt;br /&gt;
    } else {&lt;br /&gt;
        this.player_color = gamedatas.players[this.player_id].color;&lt;br /&gt;
    }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note: If you want to hide an element from spectators, you should use [[Game_interface_stylesheet:_yourgamename.css#spectatorMode|CSS &#039;spectatorMode&#039; class]].&lt;br /&gt;
&lt;br /&gt;
You may consider making a function like this, to detect if the game is in a read-only state (i.e. non-interactive):&lt;br /&gt;
  // Returns true for spectators, instant replay (during game), archive mode (after game end)&lt;br /&gt;
  isReadOnly: function () {&lt;br /&gt;
    return this.isSpectator || typeof g_replayFrom != &#039;undefined&#039; || g_archive_mode;&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.gamedatas: object&#039;&#039;&#039;&lt;br /&gt;
Contains the initial set of data to init the game, created at game start or by game refresh (F5).&lt;br /&gt;
You can update it as needed to keep an up-to-date reference of the game on the client side if you need it, however most of the time this is unnecessary.&lt;br /&gt;
&lt;br /&gt;
Note: In hotseat mode, the framework does not keep this.gamedatas of hotseat players and shares the same set as the main player to store data.&lt;br /&gt;
&lt;br /&gt;
Note: be careful when you update this data structurally, many framework functions expect data to be certain way and they will break if they see something else.&lt;br /&gt;
&lt;br /&gt;
Typical example of accessing player&#039;s info&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
for (var player_id in this.gamedatas.players) { &lt;br /&gt;
    var playerInfo = this.gamedatas.players [player_id];&lt;br /&gt;
    var c = playerInfo.color;&lt;br /&gt;
    var name = playerInfo.name;&lt;br /&gt;
    // do something &lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.isCurrentPlayerActive(): boolean&#039;&#039;&#039;&lt;br /&gt;
Returns true if the player on whose browser the code is running is currently active (it&#039;s his turn to play). Note: see remarks above about usage of this function inside onEnteringState method.&lt;br /&gt;
  if (this.isCurrentPlayerActive()) ...&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.getActivePlayerId(): number&#039;&#039;&#039;&lt;br /&gt;
Return the ID of the active player, or null if we are not in an &amp;quot;activeplayer&amp;quot; type state.&lt;br /&gt;
  if (this.player_id == this.getActivePlayerId()) ...&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.getActivePlayers(): number[]&#039;&#039;&#039;&lt;br /&gt;
Return an array with the IDs of players who are currently active (or an empty array if there are none).&lt;br /&gt;
&lt;br /&gt;
== Accessing and manipulating the DOM ==&lt;br /&gt;
&lt;br /&gt;
=== Element by Id ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;$(elementId: ElementOrId)&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
The $ function is used to get an HTML element using its &amp;quot;id&amp;quot; attribute.&lt;br /&gt;
&lt;br /&gt;
Example: modify the content of a &amp;quot;span&amp;quot; element:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
In your HTML code:&lt;br /&gt;
   &amp;lt;span id=&amp;quot;a_value_in_the_game_interface&amp;quot;&amp;gt;1234&amp;lt;/span&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In your Javascript code:&lt;br /&gt;
   $(&#039;a_value_in_the_game_interface&#039;).innerHTML = &amp;quot;9999&amp;quot;;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Note: It is safe to use if you don&#039;t know if variable is string (id of element) or element itself, i.e. &lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  foo: function(card) {&lt;br /&gt;
       card = $(card); // now its node, no need to write if (typeof card === &#039;string&#039;) ...&lt;br /&gt;
       // but its good idea to check for null here&lt;br /&gt;
       ...&lt;br /&gt;
  }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;getElementById(elementId: string)&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Note: $() is the standard method to access some HTML element with the BGA Framework. You can use &#039;&#039;&#039;getElementById&#039;&#039;&#039; but it is longer to type and less handy as it does not do some checks.&lt;br /&gt;
&lt;br /&gt;
=== Style ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;dojo.style(node: ElementOrId, styleName: string, styleValue: any): void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
With dojo.style you can modify the CSS property of any HTML element in your interface.&lt;br /&gt;
&lt;br /&gt;
Examples:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
     // Make an element disappear&lt;br /&gt;
     dojo.style( &#039;my_element&#039;, &#039;display&#039;, &#039;none&#039; );&lt;br /&gt;
&lt;br /&gt;
     // Give an element a 2px border&lt;br /&gt;
     dojo.style( &#039;my_element&#039;, &#039;borderWidth&#039;, &#039;2px&#039; );&lt;br /&gt;
&lt;br /&gt;
     // Change the background position of an element&lt;br /&gt;
     // (very practical when you are using CSS sprites to transform an element to another)&lt;br /&gt;
     dojo.style( &#039;my_element&#039;, &#039;backgroundPosition&#039;, &#039;-20px -50px&#039; );&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note: if you have to modify several CSS properties of an element, or if you have a complex CSS transformation to do, you should consider using dojo.addClass/dojo.removeClass (see below).&lt;br /&gt;
&lt;br /&gt;
You can also use object to set multiple values&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
dojo.setStyle(&amp;quot;thinger&amp;quot;, {&lt;br /&gt;
  &amp;quot;opacity&amp;quot;: 0.5,&lt;br /&gt;
  &amp;quot;border&amp;quot;: &amp;quot;3px solid black&amp;quot;,&lt;br /&gt;
  &amp;quot;height&amp;quot;: &amp;quot;300px&amp;quot;&lt;br /&gt;
});&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.addStyleToClass(cssClassName: string, styleName: string, styleValue: any):&#039;&#039;&#039; &#039;&#039;&#039;void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Same as dojo.style(), but for all the nodes set with the specified cssClassName&lt;br /&gt;
Equivalent of &lt;br /&gt;
  &lt;br /&gt;
  dojo.query(`.${aclass}`).style(styleName, styleValue)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
dojo.query(&amp;quot;#baz &amp;gt; div&amp;quot;).style({&lt;br /&gt;
  opacity:0.75,&lt;br /&gt;
  fontSize:&amp;quot;13pt&amp;quot;&lt;br /&gt;
});&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Vanilla JS style&#039;&#039;&#039;&lt;br /&gt;
  $(&#039;my_element&#039;).style.display=&#039;none&#039;; // set&lt;br /&gt;
  var display = $(&#039;my_element&#039;).style.display; // get&lt;br /&gt;
  $(&#039;my_element&#039;).style.removeProperty(&#039;display&#039;); // remove&lt;br /&gt;
&lt;br /&gt;
=== Classes ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;dojo.addClass(node: ElementOrId, classes: string): void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;dojo.removeClass(node: ElementOrId, classes: string): void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;dojo.hasClass(node: ElementOrId, aclass: string): void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;dojo.toggleClass(node: ElementOrId, aclass: string): void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
In many situations, many small CSS property updates can be replaced by a CSS class change (i.e., you add a CSS class to your element instead of applying all modifications manually).&lt;br /&gt;
&lt;br /&gt;
Advantages are:&lt;br /&gt;
* All your CSS stuff remains in your CSS file.&lt;br /&gt;
* You can add/remove a list of CSS modifications with a simple function and without error.&lt;br /&gt;
* You can test whether you applied the CSS to an element with the &#039;&#039;&#039;dojo.hasClass&#039;&#039;&#039; method.&lt;br /&gt;
&lt;br /&gt;
Example from &#039;&#039;Reversi&#039;&#039;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    // We add &amp;quot;possibleMove&amp;quot; to an element&lt;br /&gt;
    dojo.addClass( &#039;square_&#039;+x+&#039;_&#039;+y, &#039;possibleMove&#039; );&lt;br /&gt;
&lt;br /&gt;
    // In our CSS file, the class is defined as:&lt;br /&gt;
    .possibleMove {&lt;br /&gt;
      background-color: white;&lt;br /&gt;
      opacity: 0.2;&lt;br /&gt;
      filter:alpha(opacity=20); /* For IE8 and earlier */  &lt;br /&gt;
      cursor: pointer;  &lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
     // So we&#039;ve applied 4 CSS property changes in one line of code.&lt;br /&gt;
&lt;br /&gt;
     // ... and when we need to check if a square is a possible move on the client side:&lt;br /&gt;
     if( dojo.hasClass( &#039;square_&#039;+x+&#039;_&#039;+y, &#039;possibleMove&#039; ) )&lt;br /&gt;
     { ... }&lt;br /&gt;
&lt;br /&gt;
     // ... and if we want to remove all possible moves in one line of code (see &amp;quot;dojo.query&amp;quot; method):&lt;br /&gt;
     dojo.query( &#039;.possibleMove&#039; ).removeClass( &#039;possibleMove&#039; );&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Vanilla JS classList&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
This is the only exception where dojo versions are better&lt;br /&gt;
  // add class&lt;br /&gt;
  $(token_id).classList.addClass(&#039;possibleMove&#039;);&lt;br /&gt;
  // remove class&lt;br /&gt;
  $(token_id).classList.removeClass(&#039;possibleMove&#039;);&lt;br /&gt;
  // add 2 classes&lt;br /&gt;
  const myclasses = [&#039;a&#039;,&#039;b&#039;];&lt;br /&gt;
  $(token_id).classList.addClass(...myclasses);&lt;br /&gt;
  // add classes to query result&lt;br /&gt;
  document.querySelectorAll(&amp;quot;.hand .card&amp;quot;).forEach((node)=&amp;gt;node.classList.addClass(&#039;possibleMove&#039;));&lt;br /&gt;
&lt;br /&gt;
=== Attributes ===&lt;br /&gt;
&lt;br /&gt;
;dojo.attr&lt;br /&gt;
&lt;br /&gt;
With dojo.attr you can access or change the value of an attribute or property of any HTML element in your interface.&lt;br /&gt;
&lt;br /&gt;
Exemple:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
     // Get the title of a node&lt;br /&gt;
     var title = dojo.attr( id, &#039;title&#039; );&lt;br /&gt;
     // Change the height of a node&lt;br /&gt;
     dojo.attr( &#039;img_growing_tree&#039;, &#039;height&#039;, 100 );&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Vanilla JS attr&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
   $(token).id=new_id; // set attr for &amp;quot;id&amp;quot;&lt;br /&gt;
   var id = $(token).id; // get&lt;br /&gt;
&lt;br /&gt;
=== Queries ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;dojo.query(cssSelector: string): Element[]&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
With dojo.query, you can query a bunch of HTML elements with a single function, with a &amp;quot;CSS selector&amp;quot; style.&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
     // All elements with class &amp;quot;possibleMove&amp;quot;:&lt;br /&gt;
     var elements = dojo.query( &#039;.possibleMove&#039; );&lt;br /&gt;
&lt;br /&gt;
     // Count number of tokens (i.e., elements of class &amp;quot;token&amp;quot;) on the board (i.e., the element with id &amp;quot;board&amp;quot;):&lt;br /&gt;
     dojo.query( &#039;#board .token&#039; ).length;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
But what is really cool with dojo.query is that you can combine it with almost all methods above.&lt;br /&gt;
&lt;br /&gt;
Examples:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
     // Trigger a method when the mouse enter in any element with class &amp;quot;meeple&amp;quot;:&lt;br /&gt;
     dojo.query( &#039;.meeple&#039; ).connect( &#039;onmouseenter&#039;, this, &#039;myMethodToTrigger&#039; );&lt;br /&gt;
&lt;br /&gt;
     // Hide all meeples who are on the board&lt;br /&gt;
     dojo.query( &#039;#board .meeple&#039; ).style( &#039;display&#039;, &#039;none&#039; );&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Vanilla JS query&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
  var cards=document.querySelectorAll(&amp;quot;.hand .card&amp;quot;);// all cards in all hands&lt;br /&gt;
  var cards=$(&#039;hand&#039;).querySelectorAll(&amp;quot;.card&amp;quot;);// all cards in specific hand&lt;br /&gt;
  var card=document.querySelector(&amp;quot;.hand .card&amp;quot;);// first card or null if none (super handy)&lt;br /&gt;
&lt;br /&gt;
=== Creating and Destroying elements ===&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;dojo.empty(node: ElementOrId)&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Remove all children of the node element&lt;br /&gt;
   dojo.empty(&#039;my_hand&#039;);&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;dojo.destroy(node: ElementOrId)&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Remove the element&lt;br /&gt;
   dojo.destroy(&#039;my_token&#039;);&lt;br /&gt;
&lt;br /&gt;
   dojo.query(&amp;quot;.green&amp;quot;, mynode).forEach(dojo.destroy); // this remove all subnode of class green from mynode&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;dojo.create(tag: string, attributes?: obj, parent?: ElementOrId): Element&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Create element&lt;br /&gt;
&lt;br /&gt;
    dojo.create(&amp;quot;div&amp;quot;, { class: &amp;quot;yellow_arrow&amp;quot; }, parent); // this creates div with class yellow_array and places it in &amp;quot;parent&amp;quot;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.format_block(name: string, args: object): string&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
This bga function that takes global var from template file and substitute variables, typical use would be&lt;br /&gt;
&lt;br /&gt;
                var player = gamedatas.players[player_id];&lt;br /&gt;
                var div = this.format_block(&#039;jstpl_player_board&#039;, player ); // var jstpl_player_board = ... is defined in .tpl file &lt;br /&gt;
Note: result is trimmed&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.format_string(name: string, args: object): string&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
This bga function just substitute variables in a string, i.e.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
     var div = this.format_string(&#039;&amp;lt;div color=&amp;quot;${player_color}&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&#039;, {player_color: &#039;#ff0000&#039;} );&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Note: result is trimmed&lt;br /&gt;
&lt;br /&gt;
Note: this can be replaced by using backquoted string now: &lt;br /&gt;
     const player_color =  &#039;#ff0000&#039;;&lt;br /&gt;
&lt;br /&gt;
    const div = ``;&lt;br /&gt;
&#039;&#039;&#039;this.format_string_recursive&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
This bga function is similar to this.format_string but is capable of processing recursive argument structures and translations. It is used to format server notifications.&lt;br /&gt;
&lt;br /&gt;
TODO: find better place for these function docs&lt;br /&gt;
&lt;br /&gt;
=== Moving elements ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;dojo.place(node: string | Element, refNode: ElementOrId, pos?: string | number): Element&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
dojo.place is the best function to insert HTML code somewhere in your game interface without breaking something. It is much better to use than the &#039;&#039;&#039;innerHTML=&#039;&#039;&#039; method if you must insert HTML tags and not only values.&lt;br /&gt;
&lt;br /&gt;
node: can be a string or a DOM node. If it is a string starting with “&amp;lt;”, it is assumed to be an HTML fragment, which will be created. Otherwise it is assumed to be an id of a DOM node. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
     // Insert your HTML code as a child of a container element&lt;br /&gt;
     dojo.place( &amp;quot;&amp;lt;div class=&#039;foo&#039;&amp;gt;&amp;lt;/div&amp;gt;&amp;quot;, &amp;quot;your_container_element_id&amp;quot; );&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
pos: optional argument. Can be a number or one of the following strings: “before”, “after”, “replace”, “only”, “first”, or “last”. If omitted, “last” is assumed.&lt;br /&gt;
&lt;br /&gt;
* &amp;quot;replace&amp;quot;: replace the container element with my_node element&lt;br /&gt;
* &amp;quot;first&amp;quot;: places the node as a child of the reference node. The node is placed as the first child.&lt;br /&gt;
* &amp;quot;last&amp;quot; (default): places the node as a child of the reference node. The node is placed as the last child.&lt;br /&gt;
* &amp;quot;before&amp;quot;: places the node right before the reference node.&lt;br /&gt;
* &amp;quot;after&amp;quot;: places the node right after the reference node.&lt;br /&gt;
* &amp;quot;only&amp;quot;: replaces all children of the reference node with the node.&lt;br /&gt;
&lt;br /&gt;
this parameter can be a positive integer. In this case, the node will be placed as a child of the reference node with this number (counting from 0). If the number is more than number of children, the node will be appended to the reference node making it the last child. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
     // Replace all children of container with my_node &lt;br /&gt;
     dojo.place( $(&#039;my_node&#039;), &amp;quot;your_container_element_id&amp;quot;, &amp;quot;only&amp;quot; );&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
See also full doc on dojo.place: [https://dojotoolkit.org/reference-guide/1.7/dojo/place.html]&lt;br /&gt;
&lt;br /&gt;
Usually, when you want to insert some piece of HTML in your game interface, you should use &amp;quot;[[Game_layout:_view_and_template:_yourgamename.view.php_and_yourgamename_yourgamename.tpl#Javascript_templates|Javascript templates]]&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
But you can also relocate elements like that. Note: it won&#039;t animate if you do that.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.placeOnObject(mobile_obj: ElementOrId, target_obj: ElementOrId): void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
places mobile_obj on target_obj, set the absolute positions and centers the mobile_obj on target_obj,&lt;br /&gt;
effect is immediate&lt;br /&gt;
&lt;br /&gt;
This is not really an animation, but placeOnObject is frequently used before starting an animation.&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  // (We just created an object &amp;quot;my_new_token&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
  // Place the new token on current player board&lt;br /&gt;
  this.placeOnObject( &amp;quot;my_new_token&amp;quot;, &amp;quot;overall_player_board_&amp;quot;+this.player_id );&lt;br /&gt;
  &lt;br /&gt;
  // Then slide it to its position on the board&lt;br /&gt;
  this.slideToObject( &amp;quot;my_new_token&amp;quot;, &amp;quot;a_place_on_board&amp;quot; ).play();&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.placeOnObjectPos(mobile_obj: ElementOrId, target_obj: ElementOrId, target_x: number, target_y: number): void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
This method works exactly like placeOnObject, except than you can specify some (x,y) coordinates (in px). This way, the center of &amp;quot;mobile_obj&amp;quot; will be placed to the specified x,y position relatively to the center of &amp;quot;target_obj&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Note: the placement works differently from this.slideToObjectPos&#039;&#039;, since coordinates are calculated based on the center of objects.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.attachToNewParent(mobile_obj: ElementOrId, target_obj: ElementOrId): void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
With this method, you change the HTML parent of &amp;quot;mobile_obj&amp;quot; element without moving it. &lt;br /&gt;
&amp;quot;target_obj&amp;quot; is the new parent of this element. The beauty of &lt;br /&gt;
attachToNewParent is that the mobile_obj element DOES NOT MOVE during this process.&lt;br /&gt;
&lt;br /&gt;
What happens is that the method calculate a relative position of mobile_obj to make sure it does not move after the HTML parent changes.&lt;br /&gt;
&lt;br /&gt;
Why using this method?&lt;br /&gt;
&lt;br /&gt;
Changing the HTML parent of an element can be useful for the following reasons:&lt;br /&gt;
* When the HTML parent moves, all its child are moving with them. If some game elements is no more linked with a parent HTML object, you may want to attach it to another place.&lt;br /&gt;
* The z_order (vertical order of display) depends on the position in the DOM, so you may need to change the parent of some game elements when they are moving in your game area.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;CAREFUL&#039;&#039;&#039;: this function destroys original object and places a clone onto a new parent, this will break all references to this HTML element (ex: dojo.connect).&lt;br /&gt;
If you need version that does not destroy the object but the same otherwise see [[BGA_Studio_Cookbook#Attach_to_new_parent_without_destroying_the_object]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Animations ==&lt;br /&gt;
&lt;br /&gt;
===Dojo Animations===&lt;br /&gt;
&lt;br /&gt;
BGA animations is based on Dojo Animation ([http://dojotoolkit.org/documentation/tutorials/1.8/animation/ see tutorial here]).&lt;br /&gt;
&lt;br /&gt;
However, most of the time, you can just use methods below, which are built on top of Dojo Animation.&lt;br /&gt;
&lt;br /&gt;
Note: one interesting method from Dojo that could be useful from time to time is &amp;quot;Dojo.Animation&amp;quot;. It allows you to make any CSS property &amp;quot;slide&amp;quot; from one value to another.&lt;br /&gt;
&lt;br /&gt;
Note 2: the slideTo methods are not compatible with CSS transform (scale, zoom, rotate...). If possible, avoid using CSS transform on nodes that are being slided. Eventually, the only possible solution to make these 2 compatible is to disable all CSS transform properties, use slideToObjectPos/placeOnObjectPos, and then apply them again.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Sliding===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.slideToObject(mobile_obj: ElementOrId, target_obj: ElementOrId, duration?: number, delay?: number): Animation&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
You can use slideToObject to &amp;quot;slide&amp;quot; an element to a target position.&lt;br /&gt;
&lt;br /&gt;
Sliding element on the game area is the recommended and the most used way to animate your game interface. Using slides allow players to figure out what is happening on the game, as if they were playing with the real boardgame.&lt;br /&gt;
&lt;br /&gt;
The parameters are:&lt;br /&gt;
* mobile_obj: the ID of the object to move. This object must be &amp;quot;relative&amp;quot; or &amp;quot;absolute&amp;quot; positioned.&lt;br /&gt;
* target_obj: the ID of the target object. This object must be &amp;quot;relative&amp;quot; or &amp;quot;absolute&amp;quot; positioned. Note that it is not mandatory that mobile_obj and target_obj have the same size. If their size are different, the system slides the center of mobile_obj to the center of target_obj.&lt;br /&gt;
* duration: (optional) defines the duration in millisecond of the slide. The default is 500 milliseconds.&lt;br /&gt;
* delay: (optional). If you defines a delay, the slide will start only after this delay. This is particularly useful when you want to slide several object from the same position to the same position: you can give a 0ms delay to the first object, a 100ms delay to the second one, a 200ms delay to the third one, ... this way they won&#039;t be superposed during the slide.&lt;br /&gt;
&lt;br /&gt;
BE CAREFUL: The method returns an dojo.fx animation, so you can combine it with other animation if you want to. It means that you have to call the &amp;quot;play()&amp;quot; method, otherwise the animation WON&#039;T START.&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
   this.slideToObject( &amp;quot;some_token&amp;quot;, &amp;quot;some_place_on_board&amp;quot; ).play();&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.slideToObjectPos(mobile_obj: ElementOrId, target_obj: ElementOrId, target_x: number, target_y: number, duration?: number, delay?: number): Animation&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
This method does exactly the same as &amp;quot;slideToObject&amp;quot;, except than you can specify some (x,y) coordinates. This way, &amp;quot;mobile_obj&amp;quot; will slide to the specified x,y position relatively to &amp;quot;target_obj&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
Example: slide a token to some place on the board, 10 pixels from the top:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
   this.slideToObjectPos( &amp;quot;some_token&amp;quot;, &amp;quot;some_place_on_board&amp;quot;, 0, 10 ).play();&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.slideTemporaryObject(mobile_obj_html: string, parent: ElementOrId, from: ElementOrId, to: ElementOrId, duration?: number, delay?: number): Animation&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
This method is useful when you want to slide a temporary HTML object from one place to another. As this object does not exists before the animation and won&#039;t remain after, it could be complex to create this object (with dojo.place), to place it at its origin (with placeOnObject) to slide it (with slideToObject) and to make it disappear at the end.&lt;br /&gt;
&lt;br /&gt;
slideTemporaryObject does all of this for you:&lt;br /&gt;
* mobile_obj_html is a piece of HTML code that represent the object to slide.&lt;br /&gt;
* parent is the ID of an HTML element of your interface that will be the parent of this temporary HTML object.&lt;br /&gt;
* from is the ID of the origin of the slide.&lt;br /&gt;
* to is the ID of the target of the slide.&lt;br /&gt;
* duration/delay works exactly like in &amp;quot;slideToObject&amp;quot;&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
this.slideTemporaryObject( &#039;&amp;lt;div class=&amp;quot;token_icon&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&#039;, &#039;tokens&#039;, &#039;my_origin_div&#039;, &#039;my_target_div&#039; ).play();&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Destroy===&lt;br /&gt;
&#039;&#039;&#039;this.slideToObjectAndDestroy(mobile_obj: ElementOrId, target_obj: ElementOrId, duration?: number, delay?: number): void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
This method is a handy shortcut to slide an existing HTML object to some place then destroy it upon arrival. It can be used for example to move a victory token or a card from the board to the player panel to show that the player earns it, then destroy it when we don&#039;t need to keep it visible on the player panel.&lt;br /&gt;
&lt;br /&gt;
It works the same as this.slideToObject and takes the same arguments, but it starts the animation. &lt;br /&gt;
&lt;br /&gt;
CAREFUL: Make sure nothing is creating the same object at the same time the animation is running, because this will cause some random disappearing effects&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
this.slideToObjectAndDestroy( &amp;quot;some_token&amp;quot;, &amp;quot;some_place_on_board&amp;quot;, 1000, 0 );&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.fadeOutAndDestroy( node: string | Element, duration?: number, delay?: number):&#039;&#039;&#039; &#039;&#039;&#039;void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
This function fade out the target node, then destroy it. Its starts the animation.&lt;br /&gt;
* duration/delay works exactly like in &amp;quot;slideToObject&amp;quot;&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
   this.fadeOutAndDestroy( &amp;quot;a_card_that_must_disappear&amp;quot; );&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
CAREFUL: the HTML node still exists until during few milliseconds, until the fadeOut has been completed.&lt;br /&gt;
Make sure nothing is creating same object at the same time as animation is running, because you will be some random dissapearing effects&lt;br /&gt;
&lt;br /&gt;
===Rotating elements===&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
This example combines &amp;quot;Dojo.Animation&amp;quot; method and a CSS property transform that allow you to rotate the element.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
// node is Element we rotating&lt;br /&gt;
		    var animation = new dojo.Animation({&lt;br /&gt;
			    curve: [fromDegree, toDegree],&lt;br /&gt;
			    onAnimate: (v) =&amp;gt; {&lt;br /&gt;
				    node.style.transform = &#039;rotate(&#039; + v + &#039;deg)&#039;;&lt;br /&gt;
			    } &lt;br /&gt;
		    });&lt;br /&gt;
		    &lt;br /&gt;
		    animation.play();  &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
BGA has its own interface to rotate&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.rotateTo(node: string | Element, degree: number): void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
It starts the animation, and stored the rotation degree in the class, so next time you rotate object - it is additive.&lt;br /&gt;
There is no animation hooks in this one, if you need to change any parameters use dojo animation above.&lt;br /&gt;
&lt;br /&gt;
There is also &#039;&#039;&#039;rotateInstantTo&#039;&#039;&#039; with same signature which does not animate&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Animation Callbacks===&lt;br /&gt;
&lt;br /&gt;
If you wish to run some code only after an animation has completed you can do this by linking a callback method to &#039;onEnd&#039;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
var animation_id = this.slideToObject( mobile_obj, target_obj, 500 );&lt;br /&gt;
dojo.connect(animation_id, &#039;onEnd&#039;, () =&amp;gt; {&lt;br /&gt;
   // do something here&lt;br /&gt;
});&lt;br /&gt;
animation_id.play();&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If you wish to call a second animation after the first (rather than general code) then you can use a dojo animation chain (see tutorial referenced above).&lt;br /&gt;
&lt;br /&gt;
== Players input ==&lt;br /&gt;
&lt;br /&gt;
=== Connecting ===&lt;br /&gt;
&#039;&#039;&#039;dojo.connect(element: Element, event: string, context: object, method: eventHandler): any&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;dojo.connect(element: Element, event: string, handler: eventHandler): any&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Used to associate a player event with one of your notification methods.&lt;br /&gt;
&lt;br /&gt;
Example: associate a click on an element (&amp;quot;my_element&amp;quot;) with one of our methods (&amp;quot;onClickOnMyElement&amp;quot;):&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
      dojo.connect( $(&#039;my_element&#039;), &#039;onclick&#039;, this, &#039;onClickOnMyElement&#039; );&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Same idea but based on query (i.e. all element of &#039;pet&#039; class)&lt;br /&gt;
      dojo.query(&amp;quot;.pet&amp;quot;).connect(&#039;onclick&#039;, this, &#039;onPet&#039;);&lt;br /&gt;
&lt;br /&gt;
Note: if you need to disconnect the handler you have to store handler returned from this method, i.e.&lt;br /&gt;
   &lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    var handler = dojo.connect(...);&lt;br /&gt;
    ...&lt;br /&gt;
    dojo.disconnect(handler);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If you don&#039;t store the handler - you have to destroy the object to disconnect it&lt;br /&gt;
&lt;br /&gt;
Typical function that implements the input handler will look like this&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
onPet: function(event) {&lt;br /&gt;
    var id = event.currentTarget.id;&lt;br /&gt;
    console.log(&#039;onPet &#039; + id);&lt;br /&gt;
    dojo.stopEvent(event);&lt;br /&gt;
    if (this.gamedatas.gamestate.name == &#039;playerTurnPet&#039;) {&lt;br /&gt;
          this.bgaPerformAction(&#039;actPlayPet&#039;, {card: id});&lt;br /&gt;
    } else {&lt;br /&gt;
          this.showMoveUnauthorized();&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.connect(element: ElementOrId, event: string, method: eventHandler): void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Used to associate a player event with one of your notification methods.&lt;br /&gt;
&lt;br /&gt;
      this.connect( $(&#039;my_element&#039;), &#039;onclick&#039;, &#039;onClickOnMyElement&#039; );&lt;br /&gt;
&lt;br /&gt;
Or you can use an in-place handler&lt;br /&gt;
&lt;br /&gt;
      this.connect( $(&#039;my_element&#039;), &#039;onclick&#039;, (e) =&amp;gt; { console.log(&#039;boo&#039;); } );&lt;br /&gt;
&lt;br /&gt;
Note that this function stores the connection handler. That is the only real difference between &#039;&#039;&#039;this.connect&#039;&#039;&#039; and &#039;&#039;&#039;dojo.connect&#039;&#039;&#039;. If you plan to destroy the element you connected, you &#039;&#039;&#039;must&#039;&#039;&#039; call this.disconnect() to prevent memory leaks.&lt;br /&gt;
This function is mainly for permanent objects - if you just want to connect the temp object you should probably not use this method but use dojo.connect which won&#039;t require any clean-up.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.connectClass(cssClassName: string, event: string, method: eventHandler): void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Same as connect(), but for all the nodes set with the specified cssClassName.&lt;br /&gt;
 this.connectClass(&#039;pet&#039;, &#039;onclick&#039;, &#039;onPet&#039;);&lt;br /&gt;
&#039;&#039;&#039;this.disconnect(element: ElementOrId, event: string): void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Disconnect event handler (previously registered with this.connect or this.connectClass).&lt;br /&gt;
&lt;br /&gt;
   this.disconnect( $(&#039;my_element&#039;), &#039;onclick&#039;);&lt;br /&gt;
&lt;br /&gt;
Note: dynamic connect/disconnect is for advanced cases ONLY, you should always connect elements statically if possible, i.e. in setup() method.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.disconnectAll(): void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Disconnect all previously registed event handlers (registered via this.connect or this.connectClass)&lt;br /&gt;
&lt;br /&gt;
  this.disconnectAll();&lt;br /&gt;
&lt;br /&gt;
=== Actions ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.bgaPerformAction(action: string, args?: object, options: object = { lock: true, checkAction: true }): Promise&amp;lt;void&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Triggers an action on the backend. This is a combination of checkAction and ajaxcall, returning a Promise which resoves when ajaxcall ends.&lt;br /&gt;
&lt;br /&gt;
This method must be used to send a player input to the game server. &#039;&#039;&#039;It should not be triggered programmatically&#039;&#039;&#039;, especially not in loops, in callbacks, in notifications, or in onEnteringState/onUpdateActionButtons/onLeavingState, in order not to create race conditions or break replay game and tutorial features. It should be used only in reaction to a user action in the interface.&lt;br /&gt;
&lt;br /&gt;
* action: name of the action, as it is written in &amp;quot;possibleactions&amp;quot; of the current state.&lt;br /&gt;
* args: an object containing the call parameters to send to the action&lt;br /&gt;
* options: options to tweak the call with some defaults. Default is &amp;lt;code&amp;gt;{ lock: true, checkAction: true }&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Example of a standard call without args:&lt;br /&gt;
  this.bgaPerformAction(&#039;pass&#039;);&lt;br /&gt;
&lt;br /&gt;
Example of a standard call with action args:&lt;br /&gt;
  this.bgaPerformAction(&#039;actPlayCard&#039;, { id: this.selectedCardId });&lt;br /&gt;
&lt;br /&gt;
Example of a call without checking action (because player is inactive in a multiactive state):&lt;br /&gt;
&lt;br /&gt;
 this.bgaPerformAction(&#039;actChangeMind&#039;, {}, { checkAction: false });&lt;br /&gt;
&lt;br /&gt;
Example of a call without lock (because of a special action not directly related to the game flow):&lt;br /&gt;
&lt;br /&gt;
 this.bgaPerformAction(&#039;actSetAutoBid&#039;, { alwaysBidUntil: 500 }, { lock: false, checkAction: false });&lt;br /&gt;
&lt;br /&gt;
Example of call with reaction to exception:&lt;br /&gt;
  this.bgaPerformAction(&#039;actPlayCard&#039;, { id: this.selectedCardId }).catch(()=&amp;gt;{ this.selectedCardId = undefined; });&lt;br /&gt;
&lt;br /&gt;
Example of call with reaction to success:&lt;br /&gt;
  this.bgaPerformAction(&#039;actPlayCard&#039;, { id: this.selectedCardId }).then(()=&amp;gt;{ this.unselectAll(); });&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.ajaxcall(url, parameters, obj_callback, callback, callback_anycase?, ajax_method?: string)&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Note: bgaPerformAction is a simpler way to use ajax calls, ajaxcall stays in the doc for legacy reasons only and should not be used in new projects.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Same warning as &#039;&#039;&#039;this.bgaPerformAction&#039;&#039;&#039; about using on user action only.&lt;br /&gt;
&lt;br /&gt;
* url: the url of the action to perform. For a game, it must be: &amp;quot;/&amp;lt;mygame&amp;gt;/&amp;lt;mygame&amp;gt;/myAction.html&amp;quot;&lt;br /&gt;
* parameters: an array of parameter to send to the game server. &lt;br /&gt;
** Note that &amp;quot;lock: true&amp;quot; must always be specified in this list of parameters in order the interface can be locked during the server call. Cannot use lock: false - to not lock it has to be undefined.&lt;br /&gt;
** Note: Restricted parameter names (please don&#039;t use them):&lt;br /&gt;
*** &amp;quot;action&amp;quot;&lt;br /&gt;
*** &amp;quot;module&amp;quot;&lt;br /&gt;
*** &amp;quot;class&amp;quot;&lt;br /&gt;
* obj_callback: must be set to &amp;quot;this&amp;quot;.&lt;br /&gt;
* callback (non-optional but rarely used): a function to trigger when the server returns result and everything went fine (not used, as all data handling is done via notifications).&lt;br /&gt;
* callback_anycase: (optional) a function to trigger when the server returns ok OR error.  If no error this function is called with parameter value false. If an error occurred, the first parameter will be set to true, the second will contain the error message sent by the PHP back-end, and the third will contain an error code.&lt;br /&gt;
* ajax_method: (optional and rarely used) if you need to send large amounts of data (over 2048 bytes), you can set this parameter to &#039;post&#039; (all lower-case) to send a POST request as opposed to the default GET. This works, but was not officially documented, so only use if you really need to.&lt;br /&gt;
&lt;br /&gt;
Usage:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
this.ajaxcall( &#039;/mygame/mygame/actMyAction.html&#039;, { lock: true, &lt;br /&gt;
   arg1: myarg1, &lt;br /&gt;
   arg2: myarg2&lt;br /&gt;
}, this, (result)=&amp;gt;{} );&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.checkAction(action: string, nomessage?: boolean): boolean &#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Check if player can do the specified action by taking into account:&lt;br /&gt;
* if interface is locked it will return false and show message &amp;quot;An action is already in progress&amp;quot;,  unless nomessage set to true &lt;br /&gt;
* if player is not active it will return false and show message &amp;quot;This is not your turn&amp;quot;, unless nomessage set to true &lt;br /&gt;
* if action is not in list in possible actions (defined by &amp;quot;possibleaction&amp;quot; in current game state) it will return false and show &amp;quot;This move is not authorized now&amp;quot; error (unconditionally).&lt;br /&gt;
* otherwise returns true&lt;br /&gt;
Example:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  function onClickOnGameElement( evt )  {&lt;br /&gt;
     if( this.checkAction( &amp;quot;actMyAction&amp;quot; ) ) {&lt;br /&gt;
        // Do the action&lt;br /&gt;
     }&lt;br /&gt;
  }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.checkPossibleActions(action: string): boolean&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
* this is independent of the player being active, so can be used instead of this.checkAction(). This is particularly useful for multiplayer states when the player is not active in a &#039;player may like to change their mind&#039; scenario. Unlike this.checkAction, this function does NOT take interface locking into account &lt;br /&gt;
&lt;br /&gt;
* if action is not in list in possible actions (defined by &amp;quot;possibleaction&amp;quot; in current game state) it will return false and show &amp;quot;This move is not authorized now&amp;quot; error (unconditionally).&lt;br /&gt;
* otherwise returns true&lt;br /&gt;
&lt;br /&gt;
  function onChangeMyMind( evt )  {&lt;br /&gt;
     if( this.checkPossibleActions( &amp;quot;actMyAction&amp;quot; ) ) {&lt;br /&gt;
        // Do the action&lt;br /&gt;
     }&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.checkLock(nomessage?: boolean): boolean&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
When using &amp;quot;lock: true&amp;quot; in ajax call you can use this function to check if interface is in lock state (it will be locked during server call and notification processing).&lt;br /&gt;
This check can be used to block some other interactions which do not result in ajaxcall or if you want to suppress errors. Note: normally you only need to use this.checkAction(...), this is for advanced cases.&lt;br /&gt;
&lt;br /&gt;
It will also show error unless nomessage is set to true&lt;br /&gt;
&lt;br /&gt;
  function onChangeMyMind( evt )  {&lt;br /&gt;
     if( this.checkLock() ) {&lt;br /&gt;
        // Do the action&lt;br /&gt;
     }&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
== Notifications ==&lt;br /&gt;
&lt;br /&gt;
When something happens on the server side, your game interface Javascript logic received a notification.&lt;br /&gt;
If you have not done so yet check what notification are in [[Main_game_logic:_yourgamename.game.php#Notifications]]&lt;br /&gt;
&lt;br /&gt;
Here&#039;s how you can handle these notifications on the client side.&lt;br /&gt;
&lt;br /&gt;
=== Subscribe to notifications ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;dojo.subscribe(notif_type: string, callback_obj: Object, handler: string|handler)&#039;&#039;&#039;&lt;br /&gt;
* notif_type - notification type/name send by php server&lt;br /&gt;
* callback_obj - usually this&lt;br /&gt;
* handler - if string method of callback_obj with name name is called, when notification is called, with notification object as parameter (see below)&lt;br /&gt;
&lt;br /&gt;
Your Javascript &amp;quot;setupNotifications&amp;quot; method is the place where you can subscribe to notifications from your PHP code.&lt;br /&gt;
&lt;br /&gt;
Here&#039;s how you associate one of your Javascript method to a notification &amp;quot;playDisc&amp;quot; (from Reversi example):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
   setupNotifications: function() {&lt;br /&gt;
      ...&lt;br /&gt;
      dojo.subscribe(&#039;playDisc&#039;, this, &amp;quot;notif_playDisc&amp;quot;);&lt;br /&gt;
   },&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note: the &amp;quot;playDisc&amp;quot; corresponds to the name of the notification you define it in your PHP code, in your &amp;quot;notifyAllPlayers&amp;quot; or &amp;quot;notifyPlayer&amp;quot; method.&lt;br /&gt;
&lt;br /&gt;
Then, you have to define your &amp;quot;notif_playDisc&amp;quot; method:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
   notif_playDisc: function(notif) {&lt;br /&gt;
     // Remove current possible moves (makes the board more clear)&lt;br /&gt;
     dojo.query( &#039;.possibleMove&#039; ).removeClass( &#039;possibleMove&#039; );          &lt;br /&gt;
     this.addDiscOnBoard( notif.args.x, notif.args.y, notif.args.player_id );&lt;br /&gt;
   },&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In a notification handler like our &amp;quot;notif_playDisc&amp;quot; method, you can access all notifications arguments with &amp;quot;notif.args&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&lt;br /&gt;
PHP&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    $this-&amp;gt;notifyAllPlayers( &amp;quot;apples&amp;quot;, clienttranslate(&#039;player takes ${count} apples&#039;), [ &amp;quot;count&amp;quot; =&amp;gt; 3 ] );&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
JavaScript&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    setupNotifications: function() {&lt;br /&gt;
       dojo.subscribe( &#039;apples&#039;, this, &#039;notif_apples&#039; );&lt;br /&gt;
    },&lt;br /&gt;
&lt;br /&gt;
    notif_apples: function(notif) {&lt;br /&gt;
      //You can access the &amp;quot;count&amp;quot; like this:&lt;br /&gt;
       alert(&amp;quot;count = &amp;quot; + notif.args.count);&lt;br /&gt;
    }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== The notification Object received by client ===&lt;br /&gt;
&lt;br /&gt;
When sending a notification on your PHP, the client side will receive an Object with the following attributes:&lt;br /&gt;
&lt;br /&gt;
* type - type of the notification (as passed by php function)&lt;br /&gt;
* log - the log string passed from php notification&lt;br /&gt;
* args - This is the arguments that you passed on your notification method on php&lt;br /&gt;
* bIsTableMsg - is true when you use [[Main_game_logic:_yourgamename.game.php#NotifyAllPlayers|NotifyAllPlayers]] method (false otherwise)&lt;br /&gt;
* channelorig - information about table ID (formatted as : &amp;quot;/table/t[TABLE_NUMBER]&amp;quot;)&lt;br /&gt;
* gamenameorig - name of the game&lt;br /&gt;
* move_id - ID of the move associated with the notification&lt;br /&gt;
* table_id - ID of the table (comes as string)&lt;br /&gt;
* time - UNIX GMT timestamp&lt;br /&gt;
* uid - unique identifier of the notification&lt;br /&gt;
* h - unknown&lt;br /&gt;
&lt;br /&gt;
&#039;&#039; Note that those information were inferred from observation on console log. If an Admin can confirm/correct (and remove this line), you&#039;re welcome :)&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
=== Ignoring notifications ===&lt;br /&gt;
&lt;br /&gt;
Sometimes you need to ignore some notification on client side. You don&#039;t want them to be shown in game log and you don&#039;t want them to be handled.&lt;br /&gt;
&lt;br /&gt;
The most common use case is when a player gets private information. They will receive a specific notification (such as &amp;quot;You received Ace of Heart&amp;quot;), while other players would receive more generic notification (&amp;quot;Player received a card&amp;quot;).&lt;br /&gt;
&lt;br /&gt;
In X.game.php&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        $this-&amp;gt;notifyAllPlayers(&amp;quot;dealCard&amp;quot;, clienttranslate(&#039;${player_name} received a card&#039;), [&lt;br /&gt;
            &#039;player_id&#039; =&amp;gt; $playerId,&lt;br /&gt;
            &#039;player_name&#039; =&amp;gt; $this-&amp;gt;getActivePlayerName()&lt;br /&gt;
        ]);&lt;br /&gt;
&lt;br /&gt;
        $this-&amp;gt;notifyPlayer($playerId, &amp;quot;dealCardPrivate&amp;quot;, clienttranslate(&#039;You received ${cardName}&#039;), [&lt;br /&gt;
            &amp;quot;type&amp;quot; =&amp;gt; $card[&amp;quot;type&amp;quot;],&lt;br /&gt;
            &amp;quot;cardName&amp;quot; =&amp;gt; $this-&amp;gt;getCardName($card[&amp;quot;type&amp;quot;])&lt;br /&gt;
        ]);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The problem with this approach is that the active player will receive two notifications:&lt;br /&gt;
* Player1 received a card&lt;br /&gt;
* You received Ace of Hearts&lt;br /&gt;
&lt;br /&gt;
Hence, notification ignoring.&lt;br /&gt;
&lt;br /&gt;
NOTE: You can think that it would be possible to send such notification to all players except active just by using notifyPlayer and it seems to work. The problem however is that table spectators would miss such notification and their user interface (and game log) wouldn&#039;t be updated. Since there is no way to send notification just to spectators, ignoring the notification (or &amp;quot;filtering&amp;quot;) is the only reasonable solution.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;setIgnoreNotificationCheck(notif_type: string, predicate: ((notif: Notif)=&amp;gt;boolean))&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
This method will set a check whether any of notifications of specific type should be ignored.&lt;br /&gt;
&lt;br /&gt;
The parameters are:&lt;br /&gt;
* notif_type: type of the notification &lt;br /&gt;
* predicate (notif =&amp;gt; boolean): a function that will receive notif object and will return true if this specific notification should be ignored&lt;br /&gt;
&lt;br /&gt;
Before dispatching any notification of this type, the framework will call predicate to check whether notification should be ignored, if it return true - the notification will be dispatched, i.e. logged or handled.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    this.notifqueue.setIgnoreNotificationCheck( &#039;dealCard&#039;, (notif) =&amp;gt; (notif.args.player_id == this.player_id) );&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
IMPORTANT: Remember that this notification is ignored on the client side, but was still received by the client. Therefore it shouldn&#039;t contain any private information as cheaters can get it. In other words this is not a way to hide information.&lt;br /&gt;
&lt;br /&gt;
IMPORTANT: When a game is reloaded with F5 or when opening a turn based game, old notifications are replayed as history notification. They are used just to update the game log and are stripped of all arguments except player_id, i18n and any argument present in message. If you use and other argument in your predicate you should &#039;&#039;&#039;preserve&#039;&#039;&#039; it as explained [[Main_game_logic:_yourgamename.game.php#Notify_players|here]].&lt;br /&gt;
&lt;br /&gt;
=== Synchronous notifications ===&lt;br /&gt;
&lt;br /&gt;
When several notifications are received by your game interface, these notifications are processed immediately, one after the other, in the same exact order they have been generated in your PHP game logic.&lt;br /&gt;
&lt;br /&gt;
However, sometimes, you need to give some time to the players to figure out what happened on the game before jumping to the next notification. Indeed, in many games, there are a lot of automatic actions, and the computer is going to resolve all these actions very fast if you don&#039;t tell it not to do so.&lt;br /&gt;
&lt;br /&gt;
As an example, for Reversi, when someone is playing a disc, we want to wait 500 milliseconds before doing anything else in order the opponent player can figure out what move has been played.&lt;br /&gt;
&lt;br /&gt;
Here&#039;s how we do this, right after our subscription:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    dojo.subscribe( &#039;playDisc&#039;, this, &amp;quot;notif_playDisc&amp;quot; );&lt;br /&gt;
    this.notifqueue.setSynchronous( &#039;playDisc&#039;, 500 );   // Wait 500 milliseconds after executing the playDisc handler&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
-----&lt;br /&gt;
&lt;br /&gt;
It is also possible to control the delay timing dynamically (e.g., using notification args). As an example, maybe your notification &#039;cardPlayed&#039; should pause for a different amount of time depending on the number or type of cards played.&lt;br /&gt;
&lt;br /&gt;
For this case, use &#039;&#039;&#039;setSynchronous&#039;&#039;&#039; without specifying the duration and use &#039;&#039;&#039;setSynchronousDuration&#039;&#039;&#039; within the notification callback.&lt;br /&gt;
&lt;br /&gt;
* NOTE: If you forget to invoke &#039;&#039;&#039;setSynchronousDuration&#039;&#039;&#039;, the game will remain paused forever!&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
setupNotifications: function () {&lt;br /&gt;
    dojo.subscribe( &#039;cardPlayed&#039;, this, &#039;notif_cardPlayed&#039; );&lt;br /&gt;
    this.notifqueue.setSynchronous( &#039;cardPlayed&#039; ); // wait time is dynamic&lt;br /&gt;
    ...&lt;br /&gt;
},&lt;br /&gt;
&lt;br /&gt;
notif_cardPlayed: function (notif) {&lt;br /&gt;
    // MUST call setSynchronousDuration&lt;br /&gt;
&lt;br /&gt;
    // Example 1: From notification args (PHP)&lt;br /&gt;
    this.notifqueue.setSynchronousDuration(notif.args.duration);&lt;br /&gt;
    ...&lt;br /&gt;
&lt;br /&gt;
    // Or, example 2: Match the duration to a Dojo animation&lt;br /&gt;
    var anim = dojo.fx.combine([&lt;br /&gt;
        ...&lt;br /&gt;
    ]);&lt;br /&gt;
    anim.play();&lt;br /&gt;
    this.notifqueue.setSynchronousDuration(anim.duration);&lt;br /&gt;
},&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You can also manually call this.notifqueue.setSynchronousDuration(0) once client operations are finished, but be careful that even fast replay still has a path to call it.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;WARNING: combining synchronous and ignored notifications&#039;&#039;&#039;&lt;br /&gt;
You must be careful when combining dynamic synchronous durations (as described above) with ignored notifications. If you have a conditionally ignored notification like this (see below section):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;this.notifqueue.setIgnoreNotificationCheck( &#039;myNotif&#039;, (notif) =&amp;gt; (notif.args.player_id == this.player_id) /* or any other condition */ )&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
then you CANNOT do&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;this.notifqueue.setSynchronous(&#039;myNotif&#039;);&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
as, when the ignored check passes, the notification handler, in which `this.notifqueue.setSychronousDuration` is called, is never called and so the duration is never set and interface locking results.&lt;br /&gt;
&lt;br /&gt;
The workaround is to set a &amp;quot;dummy&amp;quot; time:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;this.notifqueue.setSynchronous(&#039;myNotif&#039;, 5000);&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
whose value is irrelevant but must be large enough to cover the time before the notification handler is called. The large value never actually comes into play because the notification is either ignored, or the synchronous duration is reset to a sensible value inside the handler.&lt;br /&gt;
&lt;br /&gt;
=== Pre-defined notification types ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;tableWindow&#039;&#039;&#039; - This defines notification to display [[Game_interface_logic:_yourgamename.js#Scoring_dialogs|Scoring Dialogs]], see below.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;message&#039;&#039;&#039; - This defines notification that shows on players log and have no other effect (technically any unhandled notification will do the same but its recommended to use this keyword for consistency)&lt;br /&gt;
&lt;br /&gt;
   // You can call this on php side without doing anything on client side&lt;br /&gt;
    self::notifyAllPlayers( &#039;message&#039;, clienttranslate(&#039;hello&#039;), [] );&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;simplePause&#039;&#039;&#039; - This notification will just delay other notifications, maybe useful if you know you need some extra time for animation or something. Requires a time parameter.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    self::notifyAllPlayers( &#039;simplePause&#039;, &#039;&#039;, [ &#039;time&#039; =&amp;gt; 500] ); // time is in milliseconds&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note: the following types are RESERVED by framework, do not use:&lt;br /&gt;
&lt;br /&gt;
gameStateChange gameStateChangePrivateArg gameStateMultipleActiveUpdate newActivePlayer playerstatus yourturnack clockalert tableInfosChanged playerEliminated tableDecision  archivewaitingdelay end_archivewaitingdelay replaywaitingdelay end_replaywaitingdelay replayinitialwaitingdelay end_replayinitialwaitingdelay aiPlayerWaitingDelay replay_has_ended updateSpectatorList  wouldlikethink updateReflexionTime undoRestorePoint resetInterfaceWithAllDatas zombieModeFail zombieModeFailWarning aiError skipTurnOfPlayer zombieBack allPlayersAreZombie gameResultNeutralized playerConcedeGame showTutorial showCursor showCursorClick skipTurnOfPlayerWarning  banFromTable resultsAvailable switchToTurnbased newPrivateState infomsg&lt;br /&gt;
&lt;br /&gt;
== Tooltips ==&lt;br /&gt;
&lt;br /&gt;
=== Adding static tooltips ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.addTooltip(nodeId: string, helpStringTranslated: string, actionStringTranslated: string, delay?: number): void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Add a simple text tooltip to the DOM node.&lt;br /&gt;
&lt;br /&gt;
Specify &#039;helpStringTranslated&#039; to display some information about &amp;quot;what is this game element?&amp;quot;.&lt;br /&gt;
Specify &#039;actionStringTranslated&#039; to display some information about &amp;quot;what happens when I click on this element?&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
You must specify both of the strings. You can only use one and specify an empty string (&#039;&#039;) for the other one.&lt;br /&gt;
&lt;br /&gt;
When you pass text directly function _() must be used for the text to be marked for translation! Except for empty string.&lt;br /&gt;
&lt;br /&gt;
Parameter &amp;quot;delay&amp;quot; is optional. It is primarily used to specify a zero delay for some game element when the tooltip gives really important information for the game - but remember: no essential information must be placed in tooltips as they won&#039;t be displayed in some browsers (see [[BGA_Studio_Guidelines|Guidelines]]).&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
   this.addTooltip( &#039;cardcount&#039;, _(&#039;Number of cards in hand&#039;), &#039;&#039; );&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note: this generates static tooltip and attaches to existing dom element, if you need to generate tooltip more dynamically you have to call that method every time information about object is updated or use completely different tehnique, see dynamic tooltips below.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.addTooltipHtml(nodeId: string, html: string, delay?: number): void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Add an HTML tooltip to the DOM node (for more elaborate content such as presenting a bigger version of a card).&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.addTooltipToClass(cssClass: string, helpStringTranslated: string, actionStringTranslated: string, delay?: number ): void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Add a simple text tooltip to all the DOM nodes set with this cssClass. See more details above for this.addTooltip.&lt;br /&gt;
     this.addTooltipToClass( &#039;meeple&#039;, _(&#039;This is A Meeple&#039;), _(&#039;Click to tickle&#039;) );&lt;br /&gt;
&lt;br /&gt;
IMPORTANT: all concerned nodes must exist and have IDs to get tooltips.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.addTooltipHtmlToClass(cssClass: string, html: string, delay?: number): void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Add an HTML tooltip to to all the DOM nodes set with this cssClass (for more elaborate content such as presenting a bigger version of a card).&lt;br /&gt;
&lt;br /&gt;
IMPORTANT: all concerned nodes must exist and have IDs to get tooltips.&lt;br /&gt;
&lt;br /&gt;
=== Removing static tooltips ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.removeTooltip(nodeId: string): void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Remove a tooltip from the DOM node with given id.&lt;br /&gt;
&lt;br /&gt;
=== Advanced tooltips ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;force tooltip to open&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
If you want to force tooltip to open in reaction to some other action, i.e. click you can do this&lt;br /&gt;
&lt;br /&gt;
   this.tooltips[id].open(id)&lt;br /&gt;
&lt;br /&gt;
where id is the id of the tooltip node where tooltip was installed.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;dynamic tooltips&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
See [[BGA_Studio_Cookbook#Dynamic_tooltips]]&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;tooltips on mobile&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Tooltips is very unreliable on mobile, it is recommended to implement some other method to obtaining same information,&lt;br /&gt;
such as simple click handler in dedicated &amp;quot;Help&amp;quot; mode or provide dedicated clickable areas such as corner of card.&lt;br /&gt;
&lt;br /&gt;
== Warning messages ==&lt;br /&gt;
&lt;br /&gt;
Sometimes, there is something important that is happening in the game and you have to make sure all players get the message. Most of the time, the evolution of the game situation or the game log is enough, but sometimes you need something more visible.&lt;br /&gt;
&lt;br /&gt;
Ex: someone fulfills one of the end of the game conditions, so this is the last turn.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.showMessage(msg: string, type: string): void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
showMessage shows a message in a big rectangular area on the top of the screen of the current player, and it dissapears after few seconds (also it will be in the log in some cases).&lt;br /&gt;
&lt;br /&gt;
* &amp;quot;msg&amp;quot; is the string to display. It should be translated.&lt;br /&gt;
* &amp;quot;type&amp;quot; can be set to &amp;quot;info&amp;quot;, &amp;quot;error&amp;quot;, &amp;quot;only_to_log&amp;quot; or custom string. If set to &amp;quot;info&amp;quot;, the message will be an informative message on a white background. If set to &amp;quot;error&amp;quot;, the message will be an error message on a red background and it will be added to log. If set to &amp;quot;only_to_log&amp;quot;, the message will be added to the game log but will not popup at the top of the screen.&lt;br /&gt;
If set to custom string, it will be transparent, to use custom type define &amp;quot;head_xxx&amp;quot; in css, where xxx is the type. For example if you want yellow warning, use &amp;quot;warning&amp;quot; as type and add this to css:&lt;br /&gt;
 .head_warning {&lt;br /&gt;
    background-color: #e6c66e;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
Important: the normal way to inform players about the progression of the game is the game log. The &amp;quot;showMessage&amp;quot; is intrusive and should not be used often.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    notif_messageinfo: function(notif) {&lt;br /&gt;
	if (!g_archive_mode) {&lt;br /&gt;
        	var message = this.format_string_recursive(notif.log, notif.args);&lt;br /&gt;
		this.showMessage(_(&#039;Announcement:&#039;) + &amp;quot; &amp;quot; + message, &#039;info&#039;);		&lt;br /&gt;
         }&lt;br /&gt;
    },&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Show message could be used on the client side to prevent user wrong moves before it is send to server.&lt;br /&gt;
Example from &#039;battleship&#039;:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
onGrid: function(event) {&lt;br /&gt;
     if (checkIfPlayerTriesToFireOnThemselves(event)) {&lt;br /&gt;
        this.showMessage(_(&#039;This is your own board silly!&#039;), &#039;error&#039;);&lt;br /&gt;
        return;&lt;br /&gt;
     }&lt;br /&gt;
     ...&lt;br /&gt;
},&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.showMoveUnauthorized(): void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Shows predefined user error that move is unauthorized now&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
onPet: function(event) {&lt;br /&gt;
     if (checkPet(event)==false) {&lt;br /&gt;
        this.showMoveUnauthorized();&lt;br /&gt;
        return;&lt;br /&gt;
     }&lt;br /&gt;
     ...&lt;br /&gt;
},&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Dialogs ==&lt;br /&gt;
&lt;br /&gt;
=== Confirmation dialog ===&lt;br /&gt;
&lt;br /&gt;
When an important action with a lot of consequences is triggered by the player, you may want to propose a confirmation dialog.&lt;br /&gt;
&lt;br /&gt;
CAREFUL: the general guideline of BGA is to AVOID the use of confirmation dialogs. Confirmation dialogs slow down the game and bother players. The players know that they have to pay attention to each move when they are playing online.&lt;br /&gt;
&lt;br /&gt;
The situations where you should use a confirmation dialog are the following:&lt;br /&gt;
* It must not happen very often during a game.&lt;br /&gt;
* It must be linked to an action that can really &amp;quot;kill a game&amp;quot; if the player does not pay attention.&lt;br /&gt;
* It must be something that can be done by mistake (ex: a link on the action status bar).&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.confirmationDialog(message: string, yesHandler: (param: any) =&amp;gt; void, noHandler?: (param: any) =&amp;gt; void, param?: any): void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
* message - message will be shown to user, use _() to translate&lt;br /&gt;
* yesHandler - non-optional handler to be called on yes&lt;br /&gt;
* noHandler - optional handler to called on no&lt;br /&gt;
* param - if specified, it will be passed to both handlers&lt;br /&gt;
NOTE: this is async function, it does not return anything and you should not do anything after, you must do everything in handlers&lt;br /&gt;
&lt;br /&gt;
How to display a confirmation dialog:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    this.confirmationDialog(_(&amp;quot;Are you sure you want to bake a pie?&amp;quot;), () =&amp;gt; {&lt;br /&gt;
      this.bakeThePie();&lt;br /&gt;
    });&lt;br /&gt;
    return; // nothing should be called or done after calling this, all action must be done in the handler&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
With param and both handlers&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    this.confirmationDialog(_(&amp;quot;Are you sure you want to bake a pie?&amp;quot;), &lt;br /&gt;
           (ingredient) =&amp;gt; this.bakeThePie(ingredient), &lt;br /&gt;
           (ingredient) =&amp;gt; console.log(`cancelled baking of ${ingredient}`), &lt;br /&gt;
           &#039;apple&#039;);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Multiple choice dialog ===&lt;br /&gt;
&lt;br /&gt;
You can use this dialog to give user a choice with small amount of options&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.multipleChoiceDialog(message: string, choices: string[], callback: (choice: number) =&amp;gt; void): void&#039;&#039;&#039;&lt;br /&gt;
* message - message will be shown to user, use _() to translate&lt;br /&gt;
* choices - array of choices&lt;br /&gt;
* callback - non-optional handler to be called on choice made, the choice parameter is the INDEX of the choice from the array of choices&lt;br /&gt;
&lt;br /&gt;
NOTE: this is async function, it does not return anything and you should not do anything after, you must do everything in handlers&lt;br /&gt;
NOTE: there is no cancel handler, so make sure you gave user a choice to get out of it&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    const keys = [&amp;quot;0&amp;quot;, &amp;quot;1&amp;quot;, &amp;quot;5&amp;quot;, &amp;quot;10&amp;quot;];&lt;br /&gt;
    this.multipleChoiceDialog(_(&amp;quot;How many bugs to fix?&amp;quot;), keys, (choice) =&amp;gt; {&lt;br /&gt;
      if (choice==0) return; // cancel operation, do not call server action&lt;br /&gt;
      var bugchoice = keys[choice]; // choice will be 0,1,2,3 here&lt;br /&gt;
      this.bgaPerformAction(&amp;quot;fixBugs&amp;quot;, { number: bugchoice });&lt;br /&gt;
    });&lt;br /&gt;
    return; // must return here&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Generic Dialogs ===&lt;br /&gt;
&lt;br /&gt;
As a general rule, you shouldn&#039;t use dialogs windows.&lt;br /&gt;
&lt;br /&gt;
BGA guidelines specify that all game elements should be displayed on the main screen. Players can eventually scroll down to see game elements they don&#039;t need to see anytime, and you may eventually create anchors to move between game area section. Of course dialogs windows are very practical, but the thing is: all players know how to scroll down, and not all players know how to show up your dialog window. In addition, when the dialog shows up, players can&#039;t access the other game components.&lt;br /&gt;
&lt;br /&gt;
Sometimes although, you need to display a dialog window. Here is how you do this:&lt;br /&gt;
&lt;br /&gt;
  // Create the new dialog over the play zone. You should store the handler in a member variable to access it later&lt;br /&gt;
  this.myDlg = new ebg.popindialog();&lt;br /&gt;
  this.myDlg.create( &#039;myDialogUniqueId&#039; );&lt;br /&gt;
  this.myDlg.setTitle( _(&amp;quot;my dialog title to translate&amp;quot;) );&lt;br /&gt;
  this.myDlg.setMaxWidth( 500 ); // Optional&lt;br /&gt;
  &lt;br /&gt;
  // Create the HTML of my dialog. &lt;br /&gt;
  // The best practice here is to use [[Game_layout:_view_and_template:_yourgamename.view.php_and_yourgamename_yourgamename.tpl#Javascript_templates|Javascript templates]]&lt;br /&gt;
  var html = this.format_block( &#039;jstpl_myDialogTemplate&#039;, { &lt;br /&gt;
                arg1: myArg1,&lt;br /&gt;
                arg2: myArg2,&lt;br /&gt;
                ...&lt;br /&gt;
            } );  &lt;br /&gt;
  &lt;br /&gt;
  // Show the dialog&lt;br /&gt;
  this.myDlg.setContent( html ); // Must be set before calling show() so that the size of the content is defined before positioning the dialog&lt;br /&gt;
  this.myDlg.show();&lt;br /&gt;
  &lt;br /&gt;
  // Now that the dialog has been displayed, you can connect your method to some dialog elements&lt;br /&gt;
  // Example, if you have an &amp;quot;OK&amp;quot; button in the HTML of your dialog:&lt;br /&gt;
  dojo.connect($(&#039;my_ok_button&#039;), &#039;onclick&#039;, this, (event) =&amp;gt; {&lt;br /&gt;
                event.preventDefault();&lt;br /&gt;
                this.myDlg.destroy();&lt;br /&gt;
            });&lt;br /&gt;
&lt;br /&gt;
If necessary, you can remove the default top right corner &#039;close&#039; icon, or replace the function called when it is clicked:&lt;br /&gt;
  // Removes the default close icon&lt;br /&gt;
  this.myDlg.hideCloseIcon();&lt;br /&gt;
&lt;br /&gt;
  // Replace the function call when it&#039;s clicked&lt;br /&gt;
  this.myDlg.replaceCloseCallback((event) =&amp;gt; { ... });&lt;br /&gt;
&lt;br /&gt;
=== Scoring dialogs ===&lt;br /&gt;
&lt;br /&gt;
Sometimes at the end of a round you want to display a big table that details the points wins in each section of the game.&lt;br /&gt;
&lt;br /&gt;
Example: in Hearts game, we display at the end of each round the number of &amp;quot;heart&amp;quot; cards collected by each player, the player who collected the Queen of Spades, and the total number of points loose by each player.&lt;br /&gt;
&lt;br /&gt;
Scoring dialogs are managed entirely on &#039;&#039;&#039;PHP side&#039;&#039;&#039;, but they are described here as their effects are visible only on client side.&lt;br /&gt;
&lt;br /&gt;
Displaying a scoring dialog is quite simple and is using a special notification type: &amp;quot;tableWindow&amp;quot;:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  // on PHP side:&lt;br /&gt;
  $this-&amp;gt;notifyAllPlayers( &amp;quot;tableWindow&amp;quot;, &#039;&#039;, array(&lt;br /&gt;
            &amp;quot;id&amp;quot; =&amp;gt; &#039;finalScoring&#039;,&lt;br /&gt;
            &amp;quot;title&amp;quot; =&amp;gt; clienttranslate(&amp;quot;Title of the scoring dialog&amp;quot;),&lt;br /&gt;
            &amp;quot;table&amp;quot; =&amp;gt; $table&lt;br /&gt;
        )); &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The &amp;quot;table&amp;quot; argument is a 2 dimensional PHP array that describes the table you want to display, line by line and column by column.&lt;br /&gt;
&lt;br /&gt;
Example: display an 3x3 array of strings&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
   $table = [&lt;br /&gt;
      [ &amp;quot;one&amp;quot;, &amp;quot;two&amp;quot;, &amp;quot;three&amp;quot; ],    // This is my first line&lt;br /&gt;
      [ &amp;quot;four&amp;quot;, &amp;quot;five&amp;quot;, &amp;quot;six&amp;quot; ],    // This is my second line&lt;br /&gt;
      [ &amp;quot;seven&amp;quot;, &amp;quot;height&amp;quot;, &amp;quot;nine&amp;quot; ]    // This is my third line&lt;br /&gt;
   ];&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
As you can see above, in each &amp;quot;cell&amp;quot; of your array you can display a simple string value. But you can also display a complex value with a template and associated arguments like this:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
   $table = [&lt;br /&gt;
      [ &amp;quot;one&amp;quot;, &amp;quot;two&amp;quot;, [ &amp;quot;str&amp;quot; =&amp;gt; clienttranslate(&amp;quot;a string with an ${argument}&amp;quot;), &amp;quot;args&amp;quot; =&amp;gt; [ &#039;argument&#039; =&amp;gt; &#039;argument_value&#039; ] ] ],&lt;br /&gt;
      [ &amp;quot;four&amp;quot;, &amp;quot;five&amp;quot;, &amp;quot;six&amp;quot; ], &lt;br /&gt;
      [ &amp;quot;seven&amp;quot;, &amp;quot;height&amp;quot;, &amp;quot;nine&amp;quot; ]&lt;br /&gt;
   ];&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This is especially useful when you want to display player names with colors. Example from &amp;quot;Hearts&amp;quot;:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        $firstRow = [ &#039;&#039; ];&lt;br /&gt;
        foreach( $players as $player_id =&amp;gt; $player )    {&lt;br /&gt;
            $cell = [ &#039;str&#039; =&amp;gt; &#039;${player_name}&#039;,&lt;br /&gt;
                      &#039;args&#039; =&amp;gt; [ &#039;player_name&#039; =&amp;gt; $player[&#039;player_name&#039;] ],&lt;br /&gt;
                      &#039;type&#039; =&amp;gt; &#039;header&#039;&lt;br /&gt;
                    ];&lt;br /&gt;
            $firstRow[] = $cell;&lt;br /&gt;
        }&lt;br /&gt;
        $table[] = $firstRow;&lt;br /&gt;
        ...&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You can also use three extra attributes in the parameter array for the notification:&lt;br /&gt;
* &#039;&#039;&#039;header&#039;&#039;&#039;: the content for this parameter displays before the table (also, the html will be parsed and player names will be colored according to the current game colors). &lt;br /&gt;
* &#039;&#039;&#039;footer&#039;&#039;&#039;: the content for this parameter displays after the table (no parsing for coloring the player names)&lt;br /&gt;
* &#039;&#039;&#039;closing&#039;&#039;&#039;: if this parameter is used, a button will be displayed with this label at the bottom of the popup and will allow players to close it (more easily than by clicking the top right &#039;cross&#039; icon).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
   $this-&amp;gt;notifyAllPlayers( &amp;quot;tableWindow&amp;quot;, &#039;&#039;, [&lt;br /&gt;
            &amp;quot;id&amp;quot; =&amp;gt; &#039;finalScoring&#039;,&lt;br /&gt;
            &amp;quot;title&amp;quot; =&amp;gt; clienttranslate(&amp;quot;Title of the scoring dialog&amp;quot;),&lt;br /&gt;
            &amp;quot;table&amp;quot; =&amp;gt; $table,&lt;br /&gt;
            &amp;quot;header&amp;quot; =&amp;gt; [&#039;str&#039; =&amp;gt; clienttranslate(&#039;Table header with parameter ${number}&#039;),&lt;br /&gt;
                                 &#039;args&#039; =&amp;gt; [ &#039;number&#039; =&amp;gt; 3 ],&lt;br /&gt;
                               ],&lt;br /&gt;
            &amp;quot;footer&amp;quot; =&amp;gt; &#039;&amp;lt;div class=&amp;quot;myfoot&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&#039;,&lt;br /&gt;
            &amp;quot;closing&amp;quot; =&amp;gt; clienttranslate( &amp;quot;Closing button label&amp;quot; )&lt;br /&gt;
        ] ); &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note: currently id is not used - so you cannot access resulting div by id on js side&lt;br /&gt;
Note: any traslatable stirng have to be wrapped by clienttranslate() on top level OR it has to be recursive template. &lt;br /&gt;
&lt;br /&gt;
DO NOT DO THIS: &lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
   &amp;quot;footer&amp;quot; =&amp;gt; &#039;&amp;lt;div&amp;gt;&#039;.clienttranslate( &amp;quot;The end&amp;quot; ).&#039;&amp;lt;/div&amp;gt;&#039;, // this will not work for translations!!!&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Scoring animated display ===&lt;br /&gt;
&lt;br /&gt;
Sometimes, you may want to display a score value over an element to make the scoring easier to follow for the players (Terra Mystica final scoring for example).&lt;br /&gt;
You can do it with:&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.displayScoring(anchor_id: string, color: string, score: number | string, duration?: number, offset_x?: number, offset_y?: number): void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;anchor_id&#039;&#039;&#039;: ID of the html element to place the animated score onto (without the &#039;#&#039;) &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;color&#039;&#039;&#039;: hexadecimal RGB representation of the color (should be the color of the scoring player), but without a leading &#039;#&#039;.  For instance, &#039;ff0000&#039; for red.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;score&#039;&#039;&#039;: numeric score to display, prefixed by a &#039;+&#039; or &#039;-&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;duration&#039;&#039;&#039;: animation duration in milliseconds (optional, default is 1000)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;offset_x&#039;&#039;&#039; and &#039;&#039;&#039;offset_y&#039;&#039;&#039;: if both offset_x and offset_y are defined and not null, apply the following offset (in pixels) to the scoring animation. &lt;br /&gt;
Note that the score is centered in the anchor, so the offsets might have to be negative if you calculate the position.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Note: if you want to display successively each score, you can use &#039;&#039;this.notifqueue.setSynchronous()&#039;&#039; function.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    setupNotifications: function()   {&lt;br /&gt;
           dojo.subscribe( &#039;displayScoring&#039;, this, &amp;quot;notif_displayScoring&amp;quot; );&lt;br /&gt;
           ...&lt;br /&gt;
    }&lt;br /&gt;
...&lt;br /&gt;
&lt;br /&gt;
    notif_displayScoring: function(notif) {&lt;br /&gt;
            const duration = notif.args.duration?notif.args.duration:1000;&lt;br /&gt;
            this.notifqueue.setSynchronous(&#039;displayScoring&#039;, duration );&lt;br /&gt;
	    this.displayScoring( notif.args.target, notif.args.color, notif.args.score, duration);&lt;br /&gt;
    },&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Speech bubble ===&lt;br /&gt;
&lt;br /&gt;
For better interactivity in some games (Love Letter for example), you may use comic book style speech bubbles to express the players voices.&lt;br /&gt;
This is done with showBubble:&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.showBubble(anchor_id: string, text: string, delay?: number, duration?: number, custom_class?: string): void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
* anchor_id - where to attach the bubble&lt;br /&gt;
* text - what to put in bubble, can be html&lt;br /&gt;
* delay - delay in milliseconds (optional, default 0)&lt;br /&gt;
* duration -  duration of animation in milliseconds (optional, default 3000)&lt;br /&gt;
* custom_class - extra class to add to bubble (optional), if you need to override the default bubble style&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
   this.showBubble(&#039;meeple_2&#039;, _(&#039;Hello&#039;), 0, 1000, &#039;pink_bubble&#039;);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  notif_speechBubble(notif) {&lt;br /&gt;
    var html = this.format_string_recursive(notif.args.text, notif.args.args);&lt;br /&gt;
    this.showBubble(notif.args.target, html, notif.args.delay ?? 0, notif.args.duration ?? 1000);&lt;br /&gt;
  },&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Warning&#039;&#039;&#039;: if your bubble could overlap other active elements of the interface (buttons in particular), as it stays in place even after disappearing, you should use a custom class to give it the style &amp;quot;pointer-events: none;&amp;quot; in order to intercept click events.&lt;br /&gt;
&lt;br /&gt;
Note: If you want this visually, but want to take complete control over this bubble and its animation (for example to make it permanent) you can just use div with &#039;discussion_bubble&#039; class on it, and content of div is what will be shown.&lt;br /&gt;
&lt;br /&gt;
== Translations ==&lt;br /&gt;
&lt;br /&gt;
See [[Translations]]&lt;br /&gt;
&lt;br /&gt;
== Players panels ==&lt;br /&gt;
&lt;br /&gt;
=== Update players score ===&lt;br /&gt;
&lt;br /&gt;
The column player_score from the player table is automatically loaded into this.scoreCtrl and therefore into the stars location on the player board. This occurs sometime after the game setup() function. However this score must be updated as the game progresses using notifications.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Note: this.scoreCtrl[player_id] is object of class [[Counter]], you can use other counter API.&lt;br /&gt;
&lt;br /&gt;
Increase a player score (with a positive or negative number):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  this.scoreCtrl[ player_id ].incValue( score_delta );&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Set a player score to a specific value:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  this.scoreCtrl[ player_id ].setValue( new_score );&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Set a player score to a specific value with animation:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  this.scoreCtrl[ player_id ].toValue( new_score );&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Typical usage would be (that will process &#039;score&#039; notification):&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        setupNotifications : function() {&lt;br /&gt;
              ...&lt;br /&gt;
             dojo.subscribe(&#039;score&#039;, this, &amp;quot;notif_score&amp;quot;);&lt;br /&gt;
        },&lt;br /&gt;
        notif_score: function(notif) {&lt;br /&gt;
            this.scoreCtrl[notif.args.player_id].setValue(notif.args.player_score);&lt;br /&gt;
        },&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Adding stuff to player&#039;s panel ===&lt;br /&gt;
&lt;br /&gt;
At first, create a new &amp;quot;JS template&amp;quot; string in your template (tpl) file:&lt;br /&gt;
&lt;br /&gt;
(from Gomoku example)&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
var jstpl_player_board = &#039;\&amp;lt;div class=&amp;quot;cp_board&amp;quot;&amp;gt;\&lt;br /&gt;
    &amp;lt;div id=&amp;quot;stoneicon_p${id}&amp;quot; class=&amp;quot;gmk_stoneicon gmk_stoneicon_${color}&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&amp;lt;span id=&amp;quot;stonecount_p${id}&amp;quot;&amp;gt;0&amp;lt;/span&amp;gt;\&lt;br /&gt;
&amp;lt;/div&amp;gt;&#039;;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Then, you add this piece of code in your JS file to add this template to each player panel:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
            // Setting up player boards&lt;br /&gt;
            for( var player_id in gamedatas.players )&lt;br /&gt;
            {&lt;br /&gt;
                var player = gamedatas.players[player_id];&lt;br /&gt;
                         &lt;br /&gt;
                // Setting up players boards if needed&lt;br /&gt;
                var player_board_div = $(&#039;player_board_&#039;+player_id);&lt;br /&gt;
                dojo.place( this.format_block(&#039;jstpl_player_board&#039;, player ), player_board_div );&lt;br /&gt;
            }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
(Note: the code above is of course from your &amp;quot;setup&amp;quot; function in your Javascript).&lt;br /&gt;
&lt;br /&gt;
Very often, you have to distinguish current player and others players. In this case, you just have to create another JS template (ex: jstpl_otherplayer_board) and use it when &amp;quot;player_id&amp;quot; is different than &amp;quot;this.player_id&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Fixing Player Panel heights ===&lt;br /&gt;
&lt;br /&gt;
You may find that the player panels don&#039;t automatically resize when adding something to (or removing something from) a player panel while the display is in portrait mode (i.e. the player summary panels are at the top of the screen rather than down the right side).&lt;br /&gt;
&lt;br /&gt;
When this happens, call &amp;lt;pre&amp;gt;this.adaptPlayersPanels();&amp;lt;/pre&amp;gt; This recalculates the layout and also adjusts the position of the actionbar for you.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Player&#039;s panel disabling/enabling ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.disablePlayerPanel(player_id: number): void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Disable given player panel (the panel background become gray).&lt;br /&gt;
&lt;br /&gt;
Usually, this is used to signal that this played passes, or will be inactive during a while.&lt;br /&gt;
&lt;br /&gt;
Note that the only effect of this is visual. There are no consequences on the behaviour of the panel itself.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.enablePlayerPanel(player_id:number): void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Enable a player panel that has been disabled before.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.enableAllPlayerPanels(): void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Enable all player panels that has been disabled before.&lt;br /&gt;
&lt;br /&gt;
=== Player order ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.updatePlayerOrdering(): void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
This function makes sure that player order in player&#039;s panel matches this.gamedatas.playerorder and its normally called by framework.&lt;br /&gt;
You can call it yoursel if you change this.gamedatas.playerorder from notification.&lt;br /&gt;
Also you can override this function to change defaults  OR insert a non-player panel [[BGA_Studio_Cookbook#Inserting_non-player_panel]].&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Counters ===&lt;br /&gt;
Note: there is bga component called  &amp;quot;ebg/counter&amp;quot; this API is not using it, these methods&lt;br /&gt;
below declared right in core game. If you need animation for counters use ebg/counter&lt;br /&gt;
&lt;br /&gt;
To use this API just create a counter dom element like this (class does not really matter)&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 &amp;lt;div class=&amp;quot;counter&amp;quot; id=&amp;quot;bread&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
 &amp;lt;div class=&amp;quot;counter&amp;quot; id=&amp;quot;coin&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
The &amp;quot;bread&amp;quot; will the counter name.&lt;br /&gt;
&lt;br /&gt;
The php code should send all &amp;quot;counters&amp;quot; data from getAllDatas() method like this&lt;br /&gt;
&lt;br /&gt;
game.php&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  protected function getAllDatas() {&lt;br /&gt;
    // (the key must match counter_name)&lt;br /&gt;
    $result[&#039;counters&#039;]=[&lt;br /&gt;
        &#039;bread&#039; =&amp;gt; [ &lt;br /&gt;
         &#039;counter_name&#039; =&amp;gt; &#039;bread&#039;, &lt;br /&gt;
         &#039;counter_value&#039; =&amp;gt; 3&lt;br /&gt;
         ], &lt;br /&gt;
        &#039;coin&#039; =&amp;gt; [&lt;br /&gt;
          &#039;counter_name&#039; =&amp;gt; &#039;coin&#039;, &lt;br /&gt;
          &#039;counter_value&#039; =&amp;gt; 5&lt;br /&gt;
        ]&lt;br /&gt;
   ];&lt;br /&gt;
   return $result;&lt;br /&gt;
  }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;setCounter(counter_name: stirng, new_value: string | number): void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
updates the global this.gamedatas.counters and value of node $(counter_name)&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  notif_counter: function(notif) { &lt;br /&gt;
    this.setCounter(notif.args.counter_name, notif.args.counter_value);&lt;br /&gt;
  },&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;incCounter(counter_name: string, delta: number): void&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  notif_counter : function(notif) {&lt;br /&gt;
    this.incCounter(notif.args.counter_name, notif.args.inc);&lt;br /&gt;
  },&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;updateCounters(counters: object): void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Useful for updating game counters in the player panel (such as resources). &lt;br /&gt;
&#039;counters&#039; arg is map of counters (the key must match counter_name)&lt;br /&gt;
  {&lt;br /&gt;
    &#039;bread&#039;: { &lt;br /&gt;
         &#039;counter_name&#039; : &#039;bread&#039;, &lt;br /&gt;
         &#039;counter_value&#039; =&amp;gt; 3&lt;br /&gt;
    }, &lt;br /&gt;
    &#039;coin&#039;: { &lt;br /&gt;
         &#039;counter_name&#039; : &#039;coin&#039;, &lt;br /&gt;
         &#039;counter_value&#039; =&amp;gt; 5&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
All counters MUST be referenced in this.gamedatas.counters (means they should be send from php) and will be updated.&lt;br /&gt;
DOM objects referenced by &#039;counter_name&#039; will have their innerHTML updated with &#039;counter_value&#039;.&lt;br /&gt;
&lt;br /&gt;
Usually you call this from notification&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
                        notif_counter : function(notif) {&lt;br /&gt;
                            this.updateCounters(notif.args.counters);&lt;br /&gt;
                        },&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== BGA GUI components ==&lt;br /&gt;
&lt;br /&gt;
BGA framework provides some useful ready-to-use components for the game interface:&lt;br /&gt;
&lt;br /&gt;
[[Studio#BGA_Studio_game_components_reference]]&lt;br /&gt;
&lt;br /&gt;
Note that each time you are using an additional component, you must declare it at the top of your Javascript file in the list of modules used.&lt;br /&gt;
&lt;br /&gt;
Example if you are using &amp;quot;ebg.stock&amp;quot;:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
define([&lt;br /&gt;
    &amp;quot;dojo&amp;quot;,&amp;quot;dojo/_base/declare&amp;quot;,&lt;br /&gt;
    &amp;quot;ebg/core/gamegui&amp;quot;,&lt;br /&gt;
    &amp;quot;ebg/counter&amp;quot;,&lt;br /&gt;
    &amp;quot;ebg/stock&amp;quot;  /// &amp;lt;=== we are using ebg.stock module&lt;br /&gt;
],&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== BGA Buttons ==&lt;br /&gt;
&lt;br /&gt;
=== Basic Button ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.addActionButton(id: string, label: string, method: string | eventhandler, destination?: string, blinking?: boolean, color?: string): void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
You can use this method to add an action button in the main action status bar (or other places).&lt;br /&gt;
&lt;br /&gt;
Arguments:&lt;br /&gt;
* id: an element ID that should be unique in your HTML DOM document.&lt;br /&gt;
* label: the text of the button. Should be translatable (use _() function). Note: this can also be any html, such as &amp;quot;&amp;lt;div class=&#039;brick&#039;&amp;gt;&amp;lt;/div&amp;gt;&amp;quot;, see example below on how to make image action buttons.&lt;br /&gt;
* method: the name of your method that must be triggered when the player clicks on this button (can be name of the method on game class or handler).&lt;br /&gt;
* destination (optional): id of parent on where to add button, ONLY use in rare cases if location is not action bar. Use &#039;&#039;&#039;null&#039;&#039;&#039; as value if you need to specify other arguments.&lt;br /&gt;
* blinking (optional): if set to &#039;&#039;&#039;true&#039;&#039;&#039;, the button is going blink to catch player&#039;s attention. Please DO NOT abuse blinking button. If you need button to blink after some time passed add class &#039;blinking&#039; to the button later.&lt;br /&gt;
* color: could be &#039;&#039;&#039;blue&#039;&#039;&#039; (default), &#039;&#039;&#039;red&#039;&#039;&#039;,&#039;&#039;&#039;gray&#039;&#039;&#039; or &#039;&#039;&#039;none&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
You should only use this method in your &amp;quot;onUpdateActionButtons&amp;quot; method. Usually, you use it like this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        onUpdateActionButtons: function( stateName, args ) {                      &lt;br /&gt;
            if (this.isCurrentPlayerActive()) {            &lt;br /&gt;
                switch( stateName ) {&lt;br /&gt;
                case &#039;giveCards&#039;:&lt;br /&gt;
                    this.addActionButton( &#039;giveCards_button&#039;, _(&#039;Give selected cards&#039;), &#039;onGiveCards&#039; ); &lt;br /&gt;
                    this.addActionButton( &#039;pass_button&#039;, _(&#039;Pass&#039;), () =&amp;gt; this.bgaPerformAction(&#039;actPass&#039;) ); &lt;br /&gt;
                    break;&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        },   &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In the example above, we are adding a &amp;quot;Give selected cards&amp;quot; button in the case we are on game state &amp;quot;giveCards&amp;quot;. When player clicks on this button, it triggers our &amp;quot;onGiveCards&amp;quot; method.&lt;br /&gt;
&lt;br /&gt;
Example using blinking red button:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    this.addActionButton( &#039;button_confirm&#039;, _(&#039;Confirm?&#039;), &#039;onConfirm&#039;, null, true, &#039;red&#039;); &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If you want to call the handler with arguments, you can use arrow functions, like this:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
     this.addActionButton( &#039;commit_button&#039;, _(&#039;Confirm&#039;), () =&amp;gt; this.onConfirm(this.selectedCardId), null, false, &#039;red&#039;); &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Image Button ===&lt;br /&gt;
&lt;br /&gt;
You can use the same method, but add extra class to a button to disable the padding and style it, i.e.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
this.addActionButton( &#039;button_brick&#039;, &#039;&amp;lt;div class=&amp;quot;brick&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&#039;, ()=&amp;gt;{... on brick ...}, null, null, &#039;gray&#039;); &lt;br /&gt;
dojo.addClass(&#039;button_brick&#039;,&#039;bgaimagebutton&#039;);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
where&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
.bgaimagebutton {&lt;br /&gt;
  padding: 0px 12px;&lt;br /&gt;
  min-height: 28px;&lt;br /&gt;
  border: none;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If you use this a lot, you can define a helper function, i.e.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
 * This method can be used instead of addActionButton, to add a button which is an image (i.e. resource). Can be useful when player&lt;br /&gt;
 * need to make a choice of resources or tokens.&lt;br /&gt;
 */&lt;br /&gt;
addImageActionButton: function(id, div, handler, bcolor, tooltip) {&lt;br /&gt;
	if (typeof bcolor == &amp;quot;undefined&amp;quot;) {&lt;br /&gt;
		bcolor = &amp;quot;gray&amp;quot;;&lt;br /&gt;
	}&lt;br /&gt;
	// this will actually make a transparent button id color = gray&lt;br /&gt;
	this.addActionButton(id, div, handler, null, false, bcolor);&lt;br /&gt;
	// remove border, for images it better without&lt;br /&gt;
	dojo.style(id, &amp;quot;border&amp;quot;, &amp;quot;none&amp;quot;);&lt;br /&gt;
	// but add shadow style (box-shadow, see css)&lt;br /&gt;
	dojo.addClass(id, &amp;quot;shadow bgaimagebutton&amp;quot;);&lt;br /&gt;
	// you can also add additional styles, such as background&lt;br /&gt;
	if (tooltip) {&lt;br /&gt;
		dojo.attr(id, &amp;quot;title&amp;quot;, tooltip);&lt;br /&gt;
	}&lt;br /&gt;
	return $(id);&lt;br /&gt;
},&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Disabling Button ===&lt;br /&gt;
&lt;br /&gt;
You can disable the &#039;&#039;&#039;bgabutton&#039;&#039;&#039; by adding the css class &#039;&#039;&#039;disabled&#039;&#039;&#039; in you js. The disabled button is still visible but is grey and not clickable.&lt;br /&gt;
For example in the &#039;&#039;&#039;onUpdateActionButtons&#039;&#039;&#039; : &lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
this.addActionButton(&#039;play_button_id&#039;, _(&#039;Play 1 to 3 cards&#039;), &#039;playFunctionButton&#039;); &lt;br /&gt;
if (condition) {&lt;br /&gt;
  dojo.addClass(&#039;play_button_id&#039;, &#039;disabled&#039;);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Custom Buttons ===&lt;br /&gt;
&lt;br /&gt;
You can create a custom button, but the BGA framework provides a standard button that requires only .css classes: &#039;&#039;&#039;bgabutton&#039;&#039;&#039; and &#039;&#039;&#039;bgabutton_${color}&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Examples:&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;a href=&amp;quot;#&amp;quot; id=&amp;quot;my_button_id&amp;quot; class=&amp;quot;bgabutton bgabutton_blue&amp;quot;&amp;gt;&amp;lt;span&amp;gt;My blue button&amp;lt;/span&amp;gt;&amp;lt;/a&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;a href=&amp;quot;#&amp;quot; id=&amp;quot;my_button_id&amp;quot; class=&amp;quot;bgabutton bgabutton_red bgabutton_big&amp;quot;&amp;gt;&amp;lt;span&amp;gt;My big red button&amp;lt;/span&amp;gt;&amp;lt;/a&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note&#039;&#039;&#039;: To see it in action, check out &#039;&#039;Coloretto&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
=== Button outside of action bar ===&lt;br /&gt;
&lt;br /&gt;
Use addActionButton() method with destination argument set&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
this.addActionButton( &#039;commit_button&#039;, _(&#039;Confirm&#039;), &#039;onConfirm&#039;, &#039;player_board&#039;, true, &#039;red&#039;); &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
in example above the button will be place on object with id &#039;player_board&#039;&lt;br /&gt;
&lt;br /&gt;
== Image loading ==&lt;br /&gt;
&lt;br /&gt;
See also [[Game_art:_img_directory]].&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Be careful&#039;&#039;&#039;: by default, ALL images of your img directory are loaded on a player&#039;s browser when he loads the game. For this reason, don&#039;t let in your img directory images that are not useful, otherwise it&#039;s going to slowdown the game load.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.dontPreloadImage(image_file_name: string)&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Using dontPreloadImage, you tell the interface to not preload a specific image in your img directory.&lt;br /&gt;
&lt;br /&gt;
Example of use:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
this.dontPreloadImage( &#039;cards.png&#039; );&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This is particularly useful if for example you have 2 different themes for a game. To accelerate the loading of the game, you can specify to not preload images corresponding to the other theme.&lt;br /&gt;
&lt;br /&gt;
Another example of use: in &amp;quot;Gosu&amp;quot; game with Kamakor extension, you play with 5 sets of cards among 10 available. Cards images are organized by sets, and we only preload the images corresponding to the 5 current sets with &#039;&#039;&#039;ensureSpecificGameImageLoading( image_file_names_array )&#039;&#039;&#039;.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
// By default, do not preload anything&lt;br /&gt;
this.dontPreloadImage( &#039;cards.png&#039; );&lt;br /&gt;
this.dontPreloadImage( &#039;clan1.png&#039; );&lt;br /&gt;
this.dontPreloadImage( &#039;clan2.png&#039; );&lt;br /&gt;
this.dontPreloadImage( &#039;clan3.png&#039; );&lt;br /&gt;
this.dontPreloadImage( &#039;clan4.png&#039; );&lt;br /&gt;
this.dontPreloadImage( &#039;clan5.png&#039; );&lt;br /&gt;
this.dontPreloadImage( &#039;clan6.png&#039; );&lt;br /&gt;
this.dontPreloadImage( &#039;clan7.png&#039; );&lt;br /&gt;
this.dontPreloadImage( &#039;clan8.png&#039; );&lt;br /&gt;
this.dontPreloadImage( &#039;clan9.png&#039; );&lt;br /&gt;
this.dontPreloadImage( &#039;clan10.png&#039; );&lt;br /&gt;
var to_preload = [];&lt;br /&gt;
for( i in this.gamedatas.clans )&lt;br /&gt;
{&lt;br /&gt;
	var clan_id = this.gamedatas.clans[i];&lt;br /&gt;
	to_preload.push( &#039;clan&#039;+clan_id+&#039;.png&#039; );&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
this.ensureSpecificGameImageLoading( to_preload );&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note:&#039;&#039;&#039; You don&#039;t need to specify to not preload game box images (game_box.png, game_box75.png...) since they are not preloaded by default.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.ensureSpecificGameImageLoading(list: string[])&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
This is oppostive of dontPreloadImage - its ensure specific images is loaded. Note: only makes sense if preload list is empty, otherwise everything is loaded anyway&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;load specific images&#039;&#039;&#039;&lt;br /&gt;
All images that will be preloaded stored in g_img_preload. If you want to override it directly - there is no API, but you can do this in GAME constructor&lt;br /&gt;
&lt;br /&gt;
          g_img_preload = [&#039;tokens.png&#039;, &#039;trains.png&#039;, &#039;loc_plan.png&#039;, &#039;eng.png&#039;, &#039;eng-back.png&#039;];&lt;br /&gt;
&lt;br /&gt;
You can also set it to empty array and call ensureSpecificGameImageLoading() on specific images&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Sounds ==&lt;br /&gt;
&lt;br /&gt;
Add a custom sound and make it load with your interface:&lt;br /&gt;
&lt;br /&gt;
Add this in your template (.tpl) file:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;audio id=&amp;quot;audiosrc_&amp;lt;gamename&amp;gt;_&amp;lt;yoursoundname&amp;gt;&amp;quot; src=&amp;quot;{GAMETHEMEURL}img/&amp;lt;gamename&amp;gt;_&amp;lt;yoursoundname&amp;gt;.mp3&amp;quot; preload=&amp;quot;none&amp;quot; autobuffer&amp;gt;&amp;lt;/audio&amp;gt;&lt;br /&gt;
&amp;lt;audio id=&amp;quot;audiosrc_o_&amp;lt;gamename&amp;gt;_&amp;lt;yoursoundname&amp;gt;&amp;quot; src=&amp;quot;{GAMETHEMEURL}img/&amp;lt;gamename&amp;gt;_&amp;lt;yoursoundname&amp;gt;.ogg&amp;quot; preload=&amp;quot;none&amp;quot; autobuffer&amp;gt;&amp;lt;/audio&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note: this is a requirement to provide both a mp3 and a ogg file with the names &amp;lt;code&amp;gt;&amp;lt;gamename&amp;gt;_&amp;lt;yoursoundname&amp;gt;[.ogg][.mp3]&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Play the sound (from your .js file):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
playSound(&#039;&amp;lt;gamename&amp;gt;_&amp;lt;yoursoundname&amp;gt;&#039;);   // do not add &#039;this.&#039; - its a global function&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Disable the standard &amp;quot;move&amp;quot; sound for this move (to replace it with your custom sound):&lt;br /&gt;
&lt;br /&gt;
Add this to your notification handler:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
this.disableNextMoveSound();&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note: it only disable the sound for the next move.&lt;br /&gt;
&lt;br /&gt;
== Title bar and states ==&lt;br /&gt;
&lt;br /&gt;
=== Client states ===&lt;br /&gt;
&lt;br /&gt;
Client states is a way to simulate the state transition but without actually going&lt;br /&gt;
to server. It is usefull when you need to ask user multiple questions before you&lt;br /&gt;
send things to server&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.setClientState(newState: string, args: object)&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
     this.setClientState(&amp;quot;client_playerPicksLocation&amp;quot;, {&lt;br /&gt;
                               descriptionmyturn : _(&amp;quot;${you} must select location&amp;quot;),&lt;br /&gt;
                           });&lt;br /&gt;
&lt;br /&gt;
For more information see [[BGA_Studio_Cookbook#Multi_Step_Interactions:_Select_Worker.2FPlace_Worker_-_Using_Client_States]]&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.restoreServerGameState()&#039;&#039;&#039;&lt;br /&gt;
If you are in client state it will restore the current server state (cheap undo)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.on_client_state&#039;&#039;&#039;&lt;br /&gt;
Boolean indicating that we are in client state&lt;br /&gt;
&lt;br /&gt;
=== Title bar ===&lt;br /&gt;
If you simply want to show something in title bar you can do it directly &lt;br /&gt;
     $(&#039;pagemaintitletext&#039;).innerHTML = text;&lt;br /&gt;
&lt;br /&gt;
This however will not work with parameters and will not draw You in color,&lt;br /&gt;
if you want to do proper args rendering use method below&lt;br /&gt;
&lt;br /&gt;
;&#039;&#039;&#039;this.removeActionButtons()&#039;&#039;&#039;&lt;br /&gt;
Removes all buttons from title bar&lt;br /&gt;
&lt;br /&gt;
;&#039;&#039;&#039;this.updatePageTitle()&#039;&#039;&#039;&lt;br /&gt;
:This function allows to update the current page title and turn description according to the game state arguments. If the current game state description this.gamedatas.gamestate.descriptionmyturn is modified before calling this function it allows to update the turn description without changing state. This will handle arguments substitutions properly.&lt;br /&gt;
&lt;br /&gt;
Note: this functional also will calls this.onUpdateActionButtons, if you want different buttons then state defaults, use method in example to replace them, if it becomes too clumsy use client states (see above)&lt;br /&gt;
&lt;br /&gt;
Example from Terra Mystica:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
onClickFavorTile: function( evt ) {&lt;br /&gt;
    ...&lt;br /&gt;
    if ( ... ) {&lt;br /&gt;
        this.gamedatas.gamestate.descriptionmyturn = _(&#039;Special action: &#039;) + _(&#039;Advance 1 space	on a Cult track&#039;);&lt;br /&gt;
        this.updatePageTitle();&lt;br /&gt;
        this.removeActionButtons();&lt;br /&gt;
        this.addActionButton( ... );&lt;br /&gt;
         ...&lt;br /&gt;
        return;&lt;br /&gt;
    }&lt;br /&gt;
    ...&lt;br /&gt;
&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== User preferences ==&lt;br /&gt;
&#039;&#039;&#039;this.getGameUserPreference(pref_id)&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Return the value of a user preference. It will return the value currently selected in the select combo box, in the top-right menu.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.setGameUserPreference(pref_id, value)&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Programmatically change a user preference. It will have the same effect as if the player changed the value in the select combo box, in the top-right menu.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.onGameUserPreferenceChanged&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
A callback you can define if you want to be notified when a user changes a user preference.&lt;br /&gt;
&lt;br /&gt;
Example:&amp;lt;pre&amp;gt;&lt;br /&gt;
onGameUserPreferenceChanged: function(pref_id, pref_value) {&lt;br /&gt;
  switch (pref_id) {&lt;br /&gt;
    case 201: &lt;br /&gt;
      document.getElementsByTagName(&#039;html&#039;)[0].classList.toggle(&#039;dark-background&#039;, pref_value == 2);&lt;br /&gt;
      break;&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Other useful stuff ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;dojo.hitch&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
With dojo.hitch, you can create a callback function that will run with your game object context whatever happen.&lt;br /&gt;
&lt;br /&gt;
Typical example: display a BGA confirmation dialog with a callback function created with dojo.hitch:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        this.confirmationDialog( _(&#039;Are you sure you want to make this?&#039;), dojo.hitch( this, function() {&lt;br /&gt;
            this.bgaPerformAction(&#039;makeThis&#039;);&lt;br /&gt;
        } ) );   &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In the example above, using dojo.hitch, we ensure that the &amp;quot;this&amp;quot; object will be set when the callback is called.&lt;br /&gt;
&lt;br /&gt;
NOTE: In modern JS there are lambdas that eliminate need for that, the example above will look like this&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        this.confirmationDialog( _(&#039;Are you sure you want to make this?&#039;), () =&amp;gt; this.bgaPerformAction( &#039;makeThis&#039;) );   &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
;&#039;&#039;&#039;onScreenWidthChange()&#039;&#039;&#039;&lt;br /&gt;
:This function can be overridden in your game to manage some resizing on the client side when the browser window is resized. This function is also triggered at load time, so it can be used to adapt to the :viewport size at the start of the game too.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
; this.bRealtime&lt;br /&gt;
: Return true if the game is in realtime. Note that having a distinct behavior in realtime and turn-based should be exceptional.&lt;br /&gt;
&lt;br /&gt;
; g_replayFrom&lt;br /&gt;
: Global contains replay number in live game, it is set to undefined (i.e. not set) when it is not a replay mode, so consequentially the good check is &#039;&#039;&#039;typeof g_replayFrom != &#039;undefined&#039;&#039;&#039;&#039; which returns true if the game is in replay mode &amp;lt;i&amp;gt;during the game&amp;lt;/i&amp;gt; (the game is ongoing but the user clicked &amp;quot;replay from this move&amp;quot; in the log)&lt;br /&gt;
&lt;br /&gt;
; g_archive_mode&lt;br /&gt;
: Returns true if the game is in archive mode &amp;lt;i&amp;gt;after the game&amp;lt;/i&amp;gt; (the game has ended)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
; this.instantaneousMode&lt;br /&gt;
: Returns true during replay/archive mode if animations should be skipped. Only needed if you are doing custom animations. (The BGA-provided animation functions like &amp;lt;i&amp;gt;this.slideToObject()&amp;lt;/i&amp;gt; automatically handle instantaneous mode.)&lt;br /&gt;
: Technically, when you click &amp;quot;replay from move #20&amp;quot;, the system replays the game from the very beginning with moves 0 - 19 happening in instantaneous mode and moves 20+ happening in normal mode.&lt;br /&gt;
&lt;br /&gt;
; g_tutorialwritten&lt;br /&gt;
: Returns an object like the below if the game is in tutorial mode, or undefined otherwise. Tutorial mode is a special case of archive mode where comments have been added to a previous game to teach new players the rules.&lt;br /&gt;
    {&lt;br /&gt;
        author: &amp;quot;91577332&amp;quot;,&lt;br /&gt;
        id: &amp;quot;576&amp;quot;,&lt;br /&gt;
        mode: &amp;quot;view&amp;quot;&lt;br /&gt;
        status: &amp;quot;alpha&amp;quot;&lt;br /&gt;
        version_override: null&lt;br /&gt;
        viewer_id: &amp;quot;84554161&amp;quot;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;getBgaEnvironment(): string&#039;&#039;&#039;&lt;br /&gt;
: Returns &amp;quot;studio&amp;quot; for studio and &amp;quot;prod&amp;quot; for production environment (i.e. where games current runs). Only useful for debbugging hooks.&lt;br /&gt;
Note: alpha server is also &amp;quot;prod&amp;quot;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Category:Studio]]&lt;/div&gt;</summary>
		<author><name>Sguzzer Gunayer</name></author>
	</entry>
	<entry>
		<id>https://en.doc.boardgamearena.com/index.php?title=Game_interface_logic:_Game.js&amp;diff=22736</id>
		<title>Game interface logic: Game.js</title>
		<link rel="alternate" type="text/html" href="https://en.doc.boardgamearena.com/index.php?title=Game_interface_logic:_Game.js&amp;diff=22736"/>
		<updated>2024-09-25T17:56:46Z</updated>

		<summary type="html">&lt;p&gt;Sguzzer Gunayer: /* Connecting */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Studio_Framework_Navigation}}&lt;br /&gt;
&lt;br /&gt;
__TOC__&lt;br /&gt;
&lt;br /&gt;
This is the main file for your game interface. Here you will define:&lt;br /&gt;
&lt;br /&gt;
* Which actions on the page will generate calls to the server.&lt;br /&gt;
* What happens when you get a notification for a change from the server and how it will show in the browser. &lt;br /&gt;
* Setup user interface&lt;br /&gt;
&lt;br /&gt;
== File structure ==&lt;br /&gt;
&lt;br /&gt;
The details of how the file is structured are described below with comments in the code skeleton provided to you.&lt;br /&gt;
&lt;br /&gt;
Here is the basic structure:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;constructor&#039;&#039;&#039;: here you can define global variables for your whole interface.&lt;br /&gt;
* &#039;&#039;&#039;setup&#039;&#039;&#039;: this method is called when the page is refreshed, and sets up the game interface.&lt;br /&gt;
* &#039;&#039;&#039;onEnteringState&#039;&#039;&#039;: this method is called when entering a new game state. You can use it to customize the view for each game state.&lt;br /&gt;
* &#039;&#039;&#039;onLeavingState&#039;&#039;&#039;: this method is called when leaving a game state.&lt;br /&gt;
* &#039;&#039;&#039;onUpdateActionButtons&#039;&#039;&#039;: called on state changes, in order to add action buttons to the status bar. Note: in a multipleactiveplayer state, it will be called when another player has become inactive.&lt;br /&gt;
* &#039;&#039;(utility methods)&#039;&#039;: this is where you can define your utility methods.&lt;br /&gt;
* &#039;&#039;(player&#039;s actions)&#039;&#039;: this is where you can write your handlers for player actions on the interface (example: click on an item).&lt;br /&gt;
* &#039;&#039;&#039;setupNotifications&#039;&#039;&#039;: this method associates notifications with notification handlers. For each game notification, you can trigger a javascript method to handle it and update the game interface.&lt;br /&gt;
* &#039;&#039;(notification handlers)&#039;&#039;: this is where you define the notifications handlers associated with notifications in &#039;&#039;&#039;setupNotifications&#039;&#039;&#039;, above.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
More details:&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;setup(gamedatas: object)            &#039;&#039;&#039;&lt;br /&gt;
This method must set up the game user interface according to current game situation specified in parameters.&lt;br /&gt;
The method is called each time the game interface is displayed to a player, ie:&lt;br /&gt;
&lt;br /&gt;
* when the game starts&lt;br /&gt;
* when a player opens a game in the browser later &lt;br /&gt;
* when a player refreshes the game page (F5)&lt;br /&gt;
* when player does a server side Undo&lt;br /&gt;
&lt;br /&gt;
&amp;quot;gamedatas&amp;quot; argument contains all data retrieved by your &amp;quot;getAllDatas&amp;quot; PHP method and some more.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;onEnteringState(stateName: string, args: { args: any } | null): void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
This method is called each time we enter a new game state.&lt;br /&gt;
You can use this method to perform some user interface changes at this moment.&lt;br /&gt;
To access state arguments passed via calling php arg* method use args?.args.&lt;br /&gt;
Typically you would do something only for active player, using this.isCurrentPlayerActive() check.&lt;br /&gt;
It is also called (for the current game state only) when doing a browser refresh (after the setup method is called).&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Warning&#039;&#039;&#039;: for multipleactiveplayer states:&lt;br /&gt;
the active players are NOT active yet so you must use onUpdateActionButtons to perform the client side operation which depends on a player active/inactive status.&lt;br /&gt;
If you are doing initialization of some structures which do not depend on the active player, you can just replace (this.isCurrentPlayerActive()) with (!this.isSpectator) &lt;br /&gt;
for the main switch in that method.&lt;br /&gt;
&lt;br /&gt;
See more details in [[Your_game_state_machine:_states.inc.php#Difference_between_Single_active_and_Multi_active_states]]&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;onLeavingState(stateName: string): void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
This method is called each time we leave a game state.&lt;br /&gt;
You can use this method to perform some user interface changes at this point (i.e. cleanup).&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;onUpdateActionButtons(stateName: string, args: object | null): void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
In this method you can manage &amp;quot;action buttons&amp;quot; that are displayed in the action status bar and highlight active UI elements.&lt;br /&gt;
To access state arguments passed via calling php arg* method use &#039;&#039;&#039;args&#039;&#039;&#039; parameter. Note: args can be null! For &#039;&#039;&#039;game&#039;&#039;&#039; states and when you don&#039;t supply state args function - it is null.&lt;br /&gt;
This method is called when the active or multiactive player changes. In a classic &amp;quot;activePlayer&amp;quot; state this method is called before the onEnteringState state.&lt;br /&gt;
In multipleactiveplayer state it is a mess. The sequencing of calls depends on whether you get into that state from transitions OR from reloading the whole game (i.e. F5).&lt;br /&gt;
&lt;br /&gt;
See more details in [[Your_game_state_machine:_states.inc.php#Difference_between_Single_active_and_Multi_active_states]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Dojo framework ==&lt;br /&gt;
&lt;br /&gt;
BGA uses the [http://dojotoolkit.org/ Dojo Javascript framework].&lt;br /&gt;
&lt;br /&gt;
The Dojo framework allows us to do complex things more easily. The BGA framework uses Dojo extensively.&lt;br /&gt;
&lt;br /&gt;
To implement a game, you only need to use a few parts of the Dojo framework. All the Dojo methods you need are described on this page.&lt;br /&gt;
&lt;br /&gt;
== Javascript minimization (after July 2020) ==&lt;br /&gt;
&lt;br /&gt;
For performance reasons, when deploying a game the javascript code is minimized using &#039;&#039;&#039;terser&#039;&#039;&#039; (https://github.com/terser/terser). This minifier works with modern javascript syntax. From your project &amp;quot;Manage game&amp;quot; page, you can now test a minified version of your javascript on the studio (and revert to the original).&lt;br /&gt;
&lt;br /&gt;
NB: it has been reported that there is an issue with this minifier and percentage values for opacity.&lt;br /&gt;
&lt;br /&gt;
== Accessing Players Information ==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.player_id: number&#039;&#039;&#039;&lt;br /&gt;
id of the player who is looking at the game. The player may not be part of the game (i.e. spectator)&lt;br /&gt;
  if (notif.args.player_id == this.player_id) {&lt;br /&gt;
    ...&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.isSpectator: boolean&#039;&#039;&#039;&lt;br /&gt;
Flag set to true if the user at the table is a spectator (not a player).&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    if (this.isSpectator) {&lt;br /&gt;
        this.player_color = &#039;ffffff&#039;;&lt;br /&gt;
    } else {&lt;br /&gt;
        this.player_color = gamedatas.players[this.player_id].color;&lt;br /&gt;
    }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note: If you want to hide an element from spectators, you should use [[Game_interface_stylesheet:_yourgamename.css#spectatorMode|CSS &#039;spectatorMode&#039; class]].&lt;br /&gt;
&lt;br /&gt;
You may consider making a function like this, to detect if the game is in a read-only state (i.e. non-interactive):&lt;br /&gt;
  // Returns true for spectators, instant replay (during game), archive mode (after game end)&lt;br /&gt;
  isReadOnly: function () {&lt;br /&gt;
    return this.isSpectator || typeof g_replayFrom != &#039;undefined&#039; || g_archive_mode;&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.gamedatas: object&#039;&#039;&#039;&lt;br /&gt;
Contains the initial set of data to init the game, created at game start or by game refresh (F5).&lt;br /&gt;
You can update it as needed to keep an up-to-date reference of the game on the client side if you need it, however most of the time this is unnecessary.&lt;br /&gt;
&lt;br /&gt;
Note: In hotseat mode, the framework does not keep this.gamedatas of hotseat players and shares the same set as the main player to store data.&lt;br /&gt;
&lt;br /&gt;
Note: be careful when you update this data structurally, many framework functions expect data to be certain way and they will break if they see something else.&lt;br /&gt;
&lt;br /&gt;
Typical example of accessing player&#039;s info&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
for (var player_id in this.gamedatas.players) { &lt;br /&gt;
    var playerInfo = this.gamedatas.players [player_id];&lt;br /&gt;
    var c = playerInfo.color;&lt;br /&gt;
    var name = playerInfo.name;&lt;br /&gt;
    // do something &lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.isCurrentPlayerActive(): boolean&#039;&#039;&#039;&lt;br /&gt;
Returns true if the player on whose browser the code is running is currently active (it&#039;s his turn to play). Note: see remarks above about usage of this function inside onEnteringState method.&lt;br /&gt;
  if (this.isCurrentPlayerActive()) ...&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.getActivePlayerId(): number&#039;&#039;&#039;&lt;br /&gt;
Return the ID of the active player, or null if we are not in an &amp;quot;activeplayer&amp;quot; type state.&lt;br /&gt;
  if (this.player_id == this.getActivePlayerId()) ...&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.getActivePlayers(): number[]&#039;&#039;&#039;&lt;br /&gt;
Return an array with the IDs of players who are currently active (or an empty array if there are none).&lt;br /&gt;
&lt;br /&gt;
== Accessing and manipulating the DOM ==&lt;br /&gt;
&lt;br /&gt;
=== Element by Id ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;$(elementId: ElementOrId)&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
The $ function is used to get an HTML element using its &amp;quot;id&amp;quot; attribute.&lt;br /&gt;
&lt;br /&gt;
Example: modify the content of a &amp;quot;span&amp;quot; element:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
In your HTML code:&lt;br /&gt;
   &amp;lt;span id=&amp;quot;a_value_in_the_game_interface&amp;quot;&amp;gt;1234&amp;lt;/span&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In your Javascript code:&lt;br /&gt;
   $(&#039;a_value_in_the_game_interface&#039;).innerHTML = &amp;quot;9999&amp;quot;;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Note: It is safe to use if you don&#039;t know if variable is string (id of element) or element itself, i.e. &lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  foo: function(card) {&lt;br /&gt;
       card = $(card); // now its node, no need to write if (typeof card === &#039;string&#039;) ...&lt;br /&gt;
       // but its good idea to check for null here&lt;br /&gt;
       ...&lt;br /&gt;
  }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;getElementById(elementId: string)&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Note: $() is the standard method to access some HTML element with the BGA Framework. You can use &#039;&#039;&#039;getElementById&#039;&#039;&#039; but it is longer to type and less handy as it does not do some checks.&lt;br /&gt;
&lt;br /&gt;
=== Style ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;dojo.style(node: ElementOrId, styleName: string, styleValue: any): void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
With dojo.style you can modify the CSS property of any HTML element in your interface.&lt;br /&gt;
&lt;br /&gt;
Examples:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
     // Make an element disappear&lt;br /&gt;
     dojo.style( &#039;my_element&#039;, &#039;display&#039;, &#039;none&#039; );&lt;br /&gt;
&lt;br /&gt;
     // Give an element a 2px border&lt;br /&gt;
     dojo.style( &#039;my_element&#039;, &#039;borderWidth&#039;, &#039;2px&#039; );&lt;br /&gt;
&lt;br /&gt;
     // Change the background position of an element&lt;br /&gt;
     // (very practical when you are using CSS sprites to transform an element to another)&lt;br /&gt;
     dojo.style( &#039;my_element&#039;, &#039;backgroundPosition&#039;, &#039;-20px -50px&#039; );&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note: if you have to modify several CSS properties of an element, or if you have a complex CSS transformation to do, you should consider using dojo.addClass/dojo.removeClass (see below).&lt;br /&gt;
&lt;br /&gt;
You can also use object to set multiple values&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
dojo.setStyle(&amp;quot;thinger&amp;quot;, {&lt;br /&gt;
  &amp;quot;opacity&amp;quot;: 0.5,&lt;br /&gt;
  &amp;quot;border&amp;quot;: &amp;quot;3px solid black&amp;quot;,&lt;br /&gt;
  &amp;quot;height&amp;quot;: &amp;quot;300px&amp;quot;&lt;br /&gt;
});&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.addStyleToClass(cssClassName: string, styleName: string, styleValue: any):&#039;&#039;&#039; &#039;&#039;&#039;void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Same as dojo.style(), but for all the nodes set with the specified cssClassName&lt;br /&gt;
Equivalent of &lt;br /&gt;
  &lt;br /&gt;
  dojo.query(`.${aclass}`).style(styleName, styleValue)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
dojo.query(&amp;quot;#baz &amp;gt; div&amp;quot;).style({&lt;br /&gt;
  opacity:0.75,&lt;br /&gt;
  fontSize:&amp;quot;13pt&amp;quot;&lt;br /&gt;
});&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Vanilla JS style&#039;&#039;&#039;&lt;br /&gt;
  $(&#039;my_element&#039;).style.display=&#039;none&#039;; // set&lt;br /&gt;
  var display = $(&#039;my_element&#039;).style.display; // get&lt;br /&gt;
  $(&#039;my_element&#039;).style.removeProperty(&#039;display&#039;); // remove&lt;br /&gt;
&lt;br /&gt;
=== Classes ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;dojo.addClass(node: ElementOrId, classes: string): void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;dojo.removeClass(node: ElementOrId, classes: string): void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;dojo.hasClass(node: ElementOrId, aclass: string): void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;dojo.toggleClass(node: ElementOrId, aclass: string): void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
In many situations, many small CSS property updates can be replaced by a CSS class change (i.e., you add a CSS class to your element instead of applying all modifications manually).&lt;br /&gt;
&lt;br /&gt;
Advantages are:&lt;br /&gt;
* All your CSS stuff remains in your CSS file.&lt;br /&gt;
* You can add/remove a list of CSS modifications with a simple function and without error.&lt;br /&gt;
* You can test whether you applied the CSS to an element with the &#039;&#039;&#039;dojo.hasClass&#039;&#039;&#039; method.&lt;br /&gt;
&lt;br /&gt;
Example from &#039;&#039;Reversi&#039;&#039;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    // We add &amp;quot;possibleMove&amp;quot; to an element&lt;br /&gt;
    dojo.addClass( &#039;square_&#039;+x+&#039;_&#039;+y, &#039;possibleMove&#039; );&lt;br /&gt;
&lt;br /&gt;
    // In our CSS file, the class is defined as:&lt;br /&gt;
    .possibleMove {&lt;br /&gt;
      background-color: white;&lt;br /&gt;
      opacity: 0.2;&lt;br /&gt;
      filter:alpha(opacity=20); /* For IE8 and earlier */  &lt;br /&gt;
      cursor: pointer;  &lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
     // So we&#039;ve applied 4 CSS property changes in one line of code.&lt;br /&gt;
&lt;br /&gt;
     // ... and when we need to check if a square is a possible move on the client side:&lt;br /&gt;
     if( dojo.hasClass( &#039;square_&#039;+x+&#039;_&#039;+y, &#039;possibleMove&#039; ) )&lt;br /&gt;
     { ... }&lt;br /&gt;
&lt;br /&gt;
     // ... and if we want to remove all possible moves in one line of code (see &amp;quot;dojo.query&amp;quot; method):&lt;br /&gt;
     dojo.query( &#039;.possibleMove&#039; ).removeClass( &#039;possibleMove&#039; );&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Vanilla JS classList&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
This is the only exception where dojo versions are better&lt;br /&gt;
  // add class&lt;br /&gt;
  $(token_id).classList.addClass(&#039;possibleMove&#039;);&lt;br /&gt;
  // remove class&lt;br /&gt;
  $(token_id).classList.removeClass(&#039;possibleMove&#039;);&lt;br /&gt;
  // add 2 classes&lt;br /&gt;
  const myclasses = [&#039;a&#039;,&#039;b&#039;];&lt;br /&gt;
  $(token_id).classList.addClass(...myclasses);&lt;br /&gt;
  // add classes to query result&lt;br /&gt;
  document.querySelectorAll(&amp;quot;.hand .card&amp;quot;).forEach((node)=&amp;gt;node.classList.addClass(&#039;possibleMove&#039;));&lt;br /&gt;
&lt;br /&gt;
=== Attributes ===&lt;br /&gt;
&lt;br /&gt;
;dojo.attr&lt;br /&gt;
&lt;br /&gt;
With dojo.attr you can access or change the value of an attribute or property of any HTML element in your interface.&lt;br /&gt;
&lt;br /&gt;
Exemple:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
     // Get the title of a node&lt;br /&gt;
     var title = dojo.attr( id, &#039;title&#039; );&lt;br /&gt;
     // Change the height of a node&lt;br /&gt;
     dojo.attr( &#039;img_growing_tree&#039;, &#039;height&#039;, 100 );&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Vanilla JS attr&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
   $(token).id=new_id; // set attr for &amp;quot;id&amp;quot;&lt;br /&gt;
   var id = $(token).id; // get&lt;br /&gt;
&lt;br /&gt;
=== Queries ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;dojo.query(cssSelector: string): Element[]&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
With dojo.query, you can query a bunch of HTML elements with a single function, with a &amp;quot;CSS selector&amp;quot; style.&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
     // All elements with class &amp;quot;possibleMove&amp;quot;:&lt;br /&gt;
     var elements = dojo.query( &#039;.possibleMove&#039; );&lt;br /&gt;
&lt;br /&gt;
     // Count number of tokens (i.e., elements of class &amp;quot;token&amp;quot;) on the board (i.e., the element with id &amp;quot;board&amp;quot;):&lt;br /&gt;
     dojo.query( &#039;#board .token&#039; ).length;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
But what is really cool with dojo.query is that you can combine it with almost all methods above.&lt;br /&gt;
&lt;br /&gt;
Examples:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
     // Trigger a method when the mouse enter in any element with class &amp;quot;meeple&amp;quot;:&lt;br /&gt;
     dojo.query( &#039;.meeple&#039; ).connect( &#039;onmouseenter&#039;, this, &#039;myMethodToTrigger&#039; );&lt;br /&gt;
&lt;br /&gt;
     // Hide all meeples who are on the board&lt;br /&gt;
     dojo.query( &#039;#board .meeple&#039; ).style( &#039;display&#039;, &#039;none&#039; );&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Vanilla JS query&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
  var cards=document.querySelectorAll(&amp;quot;.hand .card&amp;quot;);// all cards in all hands&lt;br /&gt;
  var cards=$(&#039;hand&#039;).querySelectorAll(&amp;quot;.card&amp;quot;);// all cards in specific hand&lt;br /&gt;
  var card=document.querySelector(&amp;quot;.hand .card&amp;quot;);// first card or null if none (super handy)&lt;br /&gt;
&lt;br /&gt;
=== Creating and Destroying elements ===&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;dojo.empty(node: ElementOrId)&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Remove all children of the node element&lt;br /&gt;
   dojo.empty(&#039;my_hand&#039;);&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;dojo.destroy(node: ElementOrId)&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Remove the element&lt;br /&gt;
   dojo.destroy(&#039;my_token&#039;);&lt;br /&gt;
&lt;br /&gt;
   dojo.query(&amp;quot;.green&amp;quot;, mynode).forEach(dojo.destroy); // this remove all subnode of class green from mynode&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;dojo.create(tag: string, attributes?: obj, parent?: ElementOrId): Element&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Create element&lt;br /&gt;
&lt;br /&gt;
    dojo.create(&amp;quot;div&amp;quot;, { class: &amp;quot;yellow_arrow&amp;quot; }, parent); // this creates div with class yellow_array and places it in &amp;quot;parent&amp;quot;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.format_block(name: string, args: object): string&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
This bga function that takes global var from template file and substitute variables, typical use would be&lt;br /&gt;
&lt;br /&gt;
                var player = gamedatas.players[player_id];&lt;br /&gt;
                var div = this.format_block(&#039;jstpl_player_board&#039;, player ); // var jstpl_player_board = ... is defined in .tpl file &lt;br /&gt;
Note: result is trimmed&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.format_string(name: string, args: object): string&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
This bga function just substitute variables in a string, i.e.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
     var div = this.format_string(&#039;&amp;lt;div color=&amp;quot;${player_color}&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&#039;, {player_color: &#039;#ff0000&#039;} );&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Note: result is trimmed&lt;br /&gt;
&lt;br /&gt;
Note: this can be replaced by using backquoted string now: &lt;br /&gt;
     const player_color =  &#039;#ff0000&#039;;&lt;br /&gt;
&lt;br /&gt;
    const div = ``;&lt;br /&gt;
&#039;&#039;&#039;this.format_string_recursive&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
This bga function is similar to this.format_string but is capable of processing recursive argument structures and translations. It is used to format server notifications.&lt;br /&gt;
&lt;br /&gt;
TODO: find better place for these function docs&lt;br /&gt;
&lt;br /&gt;
=== Moving elements ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;dojo.place(node: string | Element, refNode: ElementOrId, pos?: string | number): Element&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
dojo.place is the best function to insert HTML code somewhere in your game interface without breaking something. It is much better to use than the &#039;&#039;&#039;innerHTML=&#039;&#039;&#039; method if you must insert HTML tags and not only values.&lt;br /&gt;
&lt;br /&gt;
node: can be a string or a DOM node. If it is a string starting with “&amp;lt;”, it is assumed to be an HTML fragment, which will be created. Otherwise it is assumed to be an id of a DOM node. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
     // Insert your HTML code as a child of a container element&lt;br /&gt;
     dojo.place( &amp;quot;&amp;lt;div class=&#039;foo&#039;&amp;gt;&amp;lt;/div&amp;gt;&amp;quot;, &amp;quot;your_container_element_id&amp;quot; );&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
pos: optional argument. Can be a number or one of the following strings: “before”, “after”, “replace”, “only”, “first”, or “last”. If omitted, “last” is assumed.&lt;br /&gt;
&lt;br /&gt;
* &amp;quot;replace&amp;quot;: replace the container element with my_node element&lt;br /&gt;
* &amp;quot;first&amp;quot;: places the node as a child of the reference node. The node is placed as the first child.&lt;br /&gt;
* &amp;quot;last&amp;quot; (default): places the node as a child of the reference node. The node is placed as the last child.&lt;br /&gt;
* &amp;quot;before&amp;quot;: places the node right before the reference node.&lt;br /&gt;
* &amp;quot;after&amp;quot;: places the node right after the reference node.&lt;br /&gt;
* &amp;quot;only&amp;quot;: replaces all children of the reference node with the node.&lt;br /&gt;
&lt;br /&gt;
this parameter can be a positive integer. In this case, the node will be placed as a child of the reference node with this number (counting from 0). If the number is more than number of children, the node will be appended to the reference node making it the last child. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
     // Replace all children of container with my_node &lt;br /&gt;
     dojo.place( $(&#039;my_node&#039;), &amp;quot;your_container_element_id&amp;quot;, &amp;quot;only&amp;quot; );&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
See also full doc on dojo.place: [https://dojotoolkit.org/reference-guide/1.7/dojo/place.html]&lt;br /&gt;
&lt;br /&gt;
Usually, when you want to insert some piece of HTML in your game interface, you should use &amp;quot;[[Game_layout:_view_and_template:_yourgamename.view.php_and_yourgamename_yourgamename.tpl#Javascript_templates|Javascript templates]]&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
But you can also relocate elements like that. Note: it won&#039;t animate if you do that.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.placeOnObject(mobile_obj: ElementOrId, target_obj: ElementOrId): void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
places mobile_obj on target_obj, set the absolute positions and centers the mobile_obj on target_obj,&lt;br /&gt;
effect is immediate&lt;br /&gt;
&lt;br /&gt;
This is not really an animation, but placeOnObject is frequently used before starting an animation.&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  // (We just created an object &amp;quot;my_new_token&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
  // Place the new token on current player board&lt;br /&gt;
  this.placeOnObject( &amp;quot;my_new_token&amp;quot;, &amp;quot;overall_player_board_&amp;quot;+this.player_id );&lt;br /&gt;
  &lt;br /&gt;
  // Then slide it to its position on the board&lt;br /&gt;
  this.slideToObject( &amp;quot;my_new_token&amp;quot;, &amp;quot;a_place_on_board&amp;quot; ).play();&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.placeOnObjectPos(mobile_obj: ElementOrId, target_obj: ElementOrId, target_x: number, target_y: number): void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
This method works exactly like placeOnObject, except than you can specify some (x,y) coordinates (in px). This way, the center of &amp;quot;mobile_obj&amp;quot; will be placed to the specified x,y position relatively to the center of &amp;quot;target_obj&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Note: the placement works differently from this.slideToObjectPos&#039;&#039;, since coordinates are calculated based on the center of objects.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.attachToNewParent(mobile_obj: ElementOrId, target_obj: ElementOrId): void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
With this method, you change the HTML parent of &amp;quot;mobile_obj&amp;quot; element without moving it. &lt;br /&gt;
&amp;quot;target_obj&amp;quot; is the new parent of this element. The beauty of &lt;br /&gt;
attachToNewParent is that the mobile_obj element DOES NOT MOVE during this process.&lt;br /&gt;
&lt;br /&gt;
What happens is that the method calculate a relative position of mobile_obj to make sure it does not move after the HTML parent changes.&lt;br /&gt;
&lt;br /&gt;
Why using this method?&lt;br /&gt;
&lt;br /&gt;
Changing the HTML parent of an element can be useful for the following reasons:&lt;br /&gt;
* When the HTML parent moves, all its child are moving with them. If some game elements is no more linked with a parent HTML object, you may want to attach it to another place.&lt;br /&gt;
* The z_order (vertical order of display) depends on the position in the DOM, so you may need to change the parent of some game elements when they are moving in your game area.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;CAREFUL&#039;&#039;&#039;: this function destroys original object and places a clone onto a new parent, this will break all references to this HTML element (ex: dojo.connect).&lt;br /&gt;
If you need version that does not destroy the object but the same otherwise see [[BGA_Studio_Cookbook#Attach_to_new_parent_without_destroying_the_object]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Animations ==&lt;br /&gt;
&lt;br /&gt;
===Dojo Animations===&lt;br /&gt;
&lt;br /&gt;
BGA animations is based on Dojo Animation ([http://dojotoolkit.org/documentation/tutorials/1.8/animation/ see tutorial here]).&lt;br /&gt;
&lt;br /&gt;
However, most of the time, you can just use methods below, which are built on top of Dojo Animation.&lt;br /&gt;
&lt;br /&gt;
Note: one interesting method from Dojo that could be useful from time to time is &amp;quot;Dojo.Animation&amp;quot;. It allows you to make any CSS property &amp;quot;slide&amp;quot; from one value to another.&lt;br /&gt;
&lt;br /&gt;
Note 2: the slideTo methods are not compatible with CSS transform (scale, zoom, rotate...). If possible, avoid using CSS transform on nodes that are being slided. Eventually, the only possible solution to make these 2 compatible is to disable all CSS transform properties, use slideToObjectPos/placeOnObjectPos, and then apply them again.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Sliding===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.slideToObject(mobile_obj: ElementOrId, target_obj: ElementOrId, duration?: number, delay?: number): Animation&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
You can use slideToObject to &amp;quot;slide&amp;quot; an element to a target position.&lt;br /&gt;
&lt;br /&gt;
Sliding element on the game area is the recommended and the most used way to animate your game interface. Using slides allow players to figure out what is happening on the game, as if they were playing with the real boardgame.&lt;br /&gt;
&lt;br /&gt;
The parameters are:&lt;br /&gt;
* mobile_obj: the ID of the object to move. This object must be &amp;quot;relative&amp;quot; or &amp;quot;absolute&amp;quot; positioned.&lt;br /&gt;
* target_obj: the ID of the target object. This object must be &amp;quot;relative&amp;quot; or &amp;quot;absolute&amp;quot; positioned. Note that it is not mandatory that mobile_obj and target_obj have the same size. If their size are different, the system slides the center of mobile_obj to the center of target_obj.&lt;br /&gt;
* duration: (optional) defines the duration in millisecond of the slide. The default is 500 milliseconds.&lt;br /&gt;
* delay: (optional). If you defines a delay, the slide will start only after this delay. This is particularly useful when you want to slide several object from the same position to the same position: you can give a 0ms delay to the first object, a 100ms delay to the second one, a 200ms delay to the third one, ... this way they won&#039;t be superposed during the slide.&lt;br /&gt;
&lt;br /&gt;
BE CAREFUL: The method returns an dojo.fx animation, so you can combine it with other animation if you want to. It means that you have to call the &amp;quot;play()&amp;quot; method, otherwise the animation WON&#039;T START.&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
   this.slideToObject( &amp;quot;some_token&amp;quot;, &amp;quot;some_place_on_board&amp;quot; ).play();&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.slideToObjectPos(mobile_obj: ElementOrId, target_obj: ElementOrId, target_x: number, target_y: number, duration?: number, delay?: number): Animation&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
This method does exactly the same as &amp;quot;slideToObject&amp;quot;, except than you can specify some (x,y) coordinates. This way, &amp;quot;mobile_obj&amp;quot; will slide to the specified x,y position relatively to &amp;quot;target_obj&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
Example: slide a token to some place on the board, 10 pixels from the top:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
   this.slideToObjectPos( &amp;quot;some_token&amp;quot;, &amp;quot;some_place_on_board&amp;quot;, 0, 10 ).play();&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.slideTemporaryObject(mobile_obj_html: string, parent: ElementOrId, from: ElementOrId, to: ElementOrId, duration?: number, delay?: number): Animation&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
This method is useful when you want to slide a temporary HTML object from one place to another. As this object does not exists before the animation and won&#039;t remain after, it could be complex to create this object (with dojo.place), to place it at its origin (with placeOnObject) to slide it (with slideToObject) and to make it disappear at the end.&lt;br /&gt;
&lt;br /&gt;
slideTemporaryObject does all of this for you:&lt;br /&gt;
* mobile_obj_html is a piece of HTML code that represent the object to slide.&lt;br /&gt;
* parent is the ID of an HTML element of your interface that will be the parent of this temporary HTML object.&lt;br /&gt;
* from is the ID of the origin of the slide.&lt;br /&gt;
* to is the ID of the target of the slide.&lt;br /&gt;
* duration/delay works exactly like in &amp;quot;slideToObject&amp;quot;&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
this.slideTemporaryObject( &#039;&amp;lt;div class=&amp;quot;token_icon&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&#039;, &#039;tokens&#039;, &#039;my_origin_div&#039;, &#039;my_target_div&#039; ).play();&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Destroy===&lt;br /&gt;
&#039;&#039;&#039;this.slideToObjectAndDestroy(mobile_obj: ElementOrId, target_obj: ElementOrId, duration?: number, delay?: number): void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
This method is a handy shortcut to slide an existing HTML object to some place then destroy it upon arrival. It can be used for example to move a victory token or a card from the board to the player panel to show that the player earns it, then destroy it when we don&#039;t need to keep it visible on the player panel.&lt;br /&gt;
&lt;br /&gt;
It works the same as this.slideToObject and takes the same arguments, but it starts the animation. &lt;br /&gt;
&lt;br /&gt;
CAREFUL: Make sure nothing is creating the same object at the same time the animation is running, because this will cause some random disappearing effects&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
this.slideToObjectAndDestroy( &amp;quot;some_token&amp;quot;, &amp;quot;some_place_on_board&amp;quot;, 1000, 0 );&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.fadeOutAndDestroy( node: string | Element, duration?: number, delay?: number):&#039;&#039;&#039; &#039;&#039;&#039;void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
This function fade out the target node, then destroy it. Its starts the animation.&lt;br /&gt;
* duration/delay works exactly like in &amp;quot;slideToObject&amp;quot;&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
   this.fadeOutAndDestroy( &amp;quot;a_card_that_must_disappear&amp;quot; );&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
CAREFUL: the HTML node still exists until during few milliseconds, until the fadeOut has been completed.&lt;br /&gt;
Make sure nothing is creating same object at the same time as animation is running, because you will be some random dissapearing effects&lt;br /&gt;
&lt;br /&gt;
===Rotating elements===&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
This example combines &amp;quot;Dojo.Animation&amp;quot; method and a CSS property transform that allow you to rotate the element.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
// node is Element we rotating&lt;br /&gt;
		    var animation = new dojo.Animation({&lt;br /&gt;
			    curve: [fromDegree, toDegree],&lt;br /&gt;
			    onAnimate: (v) =&amp;gt; {&lt;br /&gt;
				    node.style.transform = &#039;rotate(&#039; + v + &#039;deg)&#039;;&lt;br /&gt;
			    } &lt;br /&gt;
		    });&lt;br /&gt;
		    &lt;br /&gt;
		    animation.play();  &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
BGA has its own interface to rotate&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.rotateTo(node: string | Element, degree: number): void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
It starts the animation, and stored the rotation degree in the class, so next time you rotate object - it is additive.&lt;br /&gt;
There is no animation hooks in this one, if you need to change any parameters use dojo animation above.&lt;br /&gt;
&lt;br /&gt;
There is also &#039;&#039;&#039;rotateInstantTo&#039;&#039;&#039; with same signature which does not animate&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Animation Callbacks===&lt;br /&gt;
&lt;br /&gt;
If you wish to run some code only after an animation has completed you can do this by linking a callback method to &#039;onEnd&#039;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
var animation_id = this.slideToObject( mobile_obj, target_obj, 500 );&lt;br /&gt;
dojo.connect(animation_id, &#039;onEnd&#039;, () =&amp;gt; {&lt;br /&gt;
   // do something here&lt;br /&gt;
});&lt;br /&gt;
animation_id.play();&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If you wish to call a second animation after the first (rather than general code) then you can use a dojo animation chain (see tutorial referenced above).&lt;br /&gt;
&lt;br /&gt;
== Players input ==&lt;br /&gt;
&lt;br /&gt;
=== Connecting ===&lt;br /&gt;
&#039;&#039;&#039;dojo.connect(element: Element, event: string, context: object, method: eventHandler): any&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;dojo.connect(element: Element, event: string, handler: eventHandler): any&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Used to associate a player event with one of your notification methods.&lt;br /&gt;
&lt;br /&gt;
Example: associate a click on an element (&amp;quot;my_element&amp;quot;) with one of our methods (&amp;quot;onClickOnMyElement&amp;quot;):&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
      dojo.connect( $(&#039;my_element&#039;), &#039;onclick&#039;, this, &#039;onClickOnMyElement&#039; );&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Same idea but based on query (i.e. all element of &#039;pet&#039; class)&lt;br /&gt;
      dojo.query(&amp;quot;.pet&amp;quot;).connect(&#039;onclick&#039;, this, &#039;onPet&#039;);&lt;br /&gt;
&lt;br /&gt;
Note: if you need to disconnect the handler you have to store handler returned from this method, i.e.&lt;br /&gt;
   &lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    var handler = dojo.connect(...);&lt;br /&gt;
    ...&lt;br /&gt;
    dojo.disconnect(handler);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If you don&#039;t store the handler - you have to destroy the object to disconnect it&lt;br /&gt;
&lt;br /&gt;
Typical function that implements the input handler will look like this&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
onPet: function(event) {&lt;br /&gt;
    var id = event.currentTarget.id;&lt;br /&gt;
    console.log(&#039;onPet &#039; + id);&lt;br /&gt;
    dojo.stopEvent(event);&lt;br /&gt;
    if (this.gamedatas.gamestate.name == &#039;playerTurnPet&#039;) {&lt;br /&gt;
          this.bgaPerformAction(&#039;actPlayPet&#039;, {card: id});&lt;br /&gt;
    } else {&lt;br /&gt;
          this.showMoveUnauthorized();&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.connect(element: ElementOrId, event: string, method: eventHandler): void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Used to associate a player event with one of your notification methods.&lt;br /&gt;
&lt;br /&gt;
      this.connect( $(&#039;my_element&#039;), &#039;onclick&#039;, &#039;onClickOnMyElement&#039; );&lt;br /&gt;
&lt;br /&gt;
Or you can use an in-place handler&lt;br /&gt;
&lt;br /&gt;
      this.connect( $(&#039;my_element&#039;), &#039;onclick&#039;, (e) =&amp;gt; { console.log(&#039;boo&#039;); } );&lt;br /&gt;
&lt;br /&gt;
Note that this function stores the connection handler. That is the only real difference between &#039;&#039;&#039;this.connect&#039;&#039;&#039; and &#039;&#039;&#039;dojo.connect&#039;&#039;&#039;. If you plan to destroy the element you connected, you &#039;&#039;&#039;must&#039;&#039;&#039; call this.disconnect() to prevent memory leaks.&lt;br /&gt;
This function is mainly for permanent objects - if you just want to connect the temp object you should probably not use this method but use dojo.connect which won&#039;t require any clean-up.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.connectClass(cssClassName: string, event: string, method: eventHandler): void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Same as connect(), but for all the nodes set with the specified cssClassName.&lt;br /&gt;
 this.connectClass(&#039;pet&#039;, &#039;onclick&#039;, &#039;onPet&#039;);&lt;br /&gt;
&#039;&#039;&#039;this.disconnect(element: ElementOrId, event: string): void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Disconnect event handler (previously registered with this.connect or this.connectClass).&lt;br /&gt;
&lt;br /&gt;
   this.disconnect( $(&#039;my_element&#039;), &#039;onclick&#039;);&lt;br /&gt;
&lt;br /&gt;
Note: dynamic connect/disconnect is for advanced cases ONLY, you should always connect elements statically if possible, i.e. in setup() method.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.disconnectAll(): void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Disconnect all previously registed event handlers (registered via this.connect or this.connectClass)&lt;br /&gt;
&lt;br /&gt;
  this.disconnectAll();&lt;br /&gt;
&lt;br /&gt;
=== Actions ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.bgaPerformAction(action: string, args?: object, options: object = { lock: true, checkAction: true }): Promise&amp;lt;void&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Triggers an action on the backend. This is a combination of checkAction and ajaxcall, returning a Promise which resoves when ajaxcall ends.&lt;br /&gt;
&lt;br /&gt;
This method must be used to send a player input to the game server. &#039;&#039;&#039;It should not be triggered programmatically&#039;&#039;&#039;, especially not in loops, in callbacks, in notifications, or in onEnteringState/onUpdateActionButtons/onLeavingState, in order not to create race conditions or break replay game and tutorial features. It should be used only in reaction to a user action in the interface.&lt;br /&gt;
&lt;br /&gt;
* action: name of the action, as it is written in &amp;quot;possibleactions&amp;quot; of the current state.&lt;br /&gt;
* args: an object containing the call parameters to send to the action&lt;br /&gt;
* options: options to tweak the call with some defaults. Default is &amp;lt;code&amp;gt;{ lock: true, checkAction: true }&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Example of a standard call without args:&lt;br /&gt;
  this.bgaPerformAction(&#039;pass&#039;);&lt;br /&gt;
&lt;br /&gt;
Example of a standard call with action args:&lt;br /&gt;
  this.bgaPerformAction(&#039;actPlayCard&#039;, { id: this.selectedCardId });&lt;br /&gt;
&lt;br /&gt;
Example of a call without checking action (because player is inactive in a multiactive state):&lt;br /&gt;
&lt;br /&gt;
 this.bgaPerformAction(&#039;actChangeMind&#039;, {}, { checkAction: false });&lt;br /&gt;
&lt;br /&gt;
Example of a call without lock (because of a special action not directly related to the game flow):&lt;br /&gt;
&lt;br /&gt;
 this.bgaPerformAction(&#039;actSetAutoBid&#039;, { alwaysBidUntil: 500 }, { lock: false, checkAction: false });&lt;br /&gt;
&lt;br /&gt;
Example of call with reaction to exception:&lt;br /&gt;
  this.bgaPerformAction(&#039;actPlayCard&#039;, { id: this.selectedCardId }).catch(()=&amp;gt;{ this.selectedCardId = undefined; });&lt;br /&gt;
&lt;br /&gt;
Example of call with reaction to success:&lt;br /&gt;
  this.bgaPerformAction(&#039;actPlayCard&#039;, { id: this.selectedCardId }).then(()=&amp;gt;{ this.unselectAll(); });&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.ajaxcall(url, parameters, obj_callback, callback, callback_anycase?, ajax_method?: string)&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Note: bgaPerformAction is a simpler way to use ajax calls, ajaxcall stays in the doc for legacy reasons only and should not be used in new projects.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Same warning as &#039;&#039;&#039;this.bgaPerformAction&#039;&#039;&#039; about using on user action only.&lt;br /&gt;
&lt;br /&gt;
* url: the url of the action to perform. For a game, it must be: &amp;quot;/&amp;lt;mygame&amp;gt;/&amp;lt;mygame&amp;gt;/myAction.html&amp;quot;&lt;br /&gt;
* parameters: an array of parameter to send to the game server. &lt;br /&gt;
** Note that &amp;quot;lock: true&amp;quot; must always be specified in this list of parameters in order the interface can be locked during the server call. Cannot use lock: false - to not lock it has to be undefined.&lt;br /&gt;
** Note: Restricted parameter names (please don&#039;t use them):&lt;br /&gt;
*** &amp;quot;action&amp;quot;&lt;br /&gt;
*** &amp;quot;module&amp;quot;&lt;br /&gt;
*** &amp;quot;class&amp;quot;&lt;br /&gt;
* obj_callback: must be set to &amp;quot;this&amp;quot;.&lt;br /&gt;
* callback (non-optional but rarely used): a function to trigger when the server returns result and everything went fine (not used, as all data handling is done via notifications).&lt;br /&gt;
* callback_anycase: (optional) a function to trigger when the server returns ok OR error.  If no error this function is called with parameter value false. If an error occurred, the first parameter will be set to true, the second will contain the error message sent by the PHP back-end, and the third will contain an error code.&lt;br /&gt;
* ajax_method: (optional and rarely used) if you need to send large amounts of data (over 2048 bytes), you can set this parameter to &#039;post&#039; (all lower-case) to send a POST request as opposed to the default GET. This works, but was not officially documented, so only use if you really need to.&lt;br /&gt;
&lt;br /&gt;
Usage:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
this.ajaxcall( &#039;/mygame/mygame/actMyAction.html&#039;, { lock: true, &lt;br /&gt;
   arg1: myarg1, &lt;br /&gt;
   arg2: myarg2&lt;br /&gt;
}, this, (result)=&amp;gt;{} );&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.checkAction(action: string, nomessage?: boolean): boolean &#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Check if player can do the specified action by taking into account:&lt;br /&gt;
* if interface is locked it will return false and show message &amp;quot;An action is already in progress&amp;quot;,  unless nomessage set to true &lt;br /&gt;
* if player is not active it will return false and show message &amp;quot;This is not your turn&amp;quot;, unless nomessage set to true &lt;br /&gt;
* if action is not in list in possible actions (defined by &amp;quot;possibleaction&amp;quot; in current game state) it will return false and show &amp;quot;This move is not authorized now&amp;quot; error (unconditionally).&lt;br /&gt;
* otherwise returns true&lt;br /&gt;
Example:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  function onClickOnGameElement( evt )  {&lt;br /&gt;
     if( this.checkAction( &amp;quot;actMyAction&amp;quot; ) ) {&lt;br /&gt;
        // Do the action&lt;br /&gt;
     }&lt;br /&gt;
  }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.checkPossibleActions(action: string): boolean&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
* this is independent of the player being active, so can be used instead of this.checkAction(). This is particularly useful for multiplayer states when the player is not active in a &#039;player may like to change their mind&#039; scenario. Unlike this.checkAction, this function does NOT take interface locking into account &lt;br /&gt;
&lt;br /&gt;
* if action is not in list in possible actions (defined by &amp;quot;possibleaction&amp;quot; in current game state) it will return false and show &amp;quot;This move is not authorized now&amp;quot; error (unconditionally).&lt;br /&gt;
* otherwise returns true&lt;br /&gt;
&lt;br /&gt;
  function onChangeMyMind( evt )  {&lt;br /&gt;
     if( this.checkPossibleActions( &amp;quot;actMyAction&amp;quot; ) ) {&lt;br /&gt;
        // Do the action&lt;br /&gt;
     }&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.checkLock(nomessage?: boolean): boolean&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
When using &amp;quot;lock: true&amp;quot; in ajax call you can use this function to check if interface is in lock state (it will be locked during server call and notification processing).&lt;br /&gt;
This check can be used to block some other interactions which do not result in ajaxcall or if you want to suppress errors. Note: normally you only need to use this.checkAction(...), this is for advanced cases.&lt;br /&gt;
&lt;br /&gt;
It will also show error unless nomessage is set to true&lt;br /&gt;
&lt;br /&gt;
  function onChangeMyMind( evt )  {&lt;br /&gt;
     if( this.checkLock() ) {&lt;br /&gt;
        // Do the action&lt;br /&gt;
     }&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
== Notifications ==&lt;br /&gt;
&lt;br /&gt;
When something happens on the server side, your game interface Javascript logic received a notification.&lt;br /&gt;
If you have not done so yet check what notification are in [[Main_game_logic:_yourgamename.game.php#Notifications]]&lt;br /&gt;
&lt;br /&gt;
Here&#039;s how you can handle these notifications on the client side.&lt;br /&gt;
&lt;br /&gt;
=== Subscribe to notifications ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;dojo.subscribe(notif_type: string, callback_obj: Object, handler: string|handler)&#039;&#039;&#039;&lt;br /&gt;
* notif_type - notification type/name send by php server&lt;br /&gt;
* callback_obj - usually this&lt;br /&gt;
* handler - if string method of callback_obj with name name is called, when notification is called, with notification object as parameter (see below)&lt;br /&gt;
&lt;br /&gt;
Your Javascript &amp;quot;setupNotifications&amp;quot; method is the place where you can subscribe to notifications from your PHP code.&lt;br /&gt;
&lt;br /&gt;
Here&#039;s how you associate one of your Javascript method to a notification &amp;quot;playDisc&amp;quot; (from Reversi example):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
   setupNotifications: function() {&lt;br /&gt;
      ...&lt;br /&gt;
      dojo.subscribe(&#039;playDisc&#039;, this, &amp;quot;notif_playDisc&amp;quot;);&lt;br /&gt;
   },&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note: the &amp;quot;playDisc&amp;quot; corresponds to the name of the notification you define it in your PHP code, in your &amp;quot;notifyAllPlayers&amp;quot; or &amp;quot;notifyPlayer&amp;quot; method.&lt;br /&gt;
&lt;br /&gt;
Then, you have to define your &amp;quot;notif_playDisc&amp;quot; method:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
   notif_playDisc: function(notif) {&lt;br /&gt;
     // Remove current possible moves (makes the board more clear)&lt;br /&gt;
     dojo.query( &#039;.possibleMove&#039; ).removeClass( &#039;possibleMove&#039; );          &lt;br /&gt;
     this.addDiscOnBoard( notif.args.x, notif.args.y, notif.args.player_id );&lt;br /&gt;
   },&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In a notification handler like our &amp;quot;notif_playDisc&amp;quot; method, you can access all notifications arguments with &amp;quot;notif.args&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&lt;br /&gt;
PHP&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    $this-&amp;gt;notifyAllPlayers( &amp;quot;apples&amp;quot;, clienttranslate(&#039;player takes ${count} apples&#039;), [ &amp;quot;count&amp;quot; =&amp;gt; 3 ] );&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
JavaScript&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    setupNotifications: function() {&lt;br /&gt;
       dojo.subscribe( &#039;apples&#039;, this, &#039;notif_apples&#039; );&lt;br /&gt;
    },&lt;br /&gt;
&lt;br /&gt;
    notif_apples: function(notif) {&lt;br /&gt;
      //You can access the &amp;quot;count&amp;quot; like this:&lt;br /&gt;
       alert(&amp;quot;count = &amp;quot; + notif.args.count);&lt;br /&gt;
    }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== The notification Object received by client ===&lt;br /&gt;
&lt;br /&gt;
When sending a notification on your PHP, the client side will receive an Object with the following attributes:&lt;br /&gt;
&lt;br /&gt;
* type - type of the notification (as passed by php function)&lt;br /&gt;
* log - the log string passed from php notification&lt;br /&gt;
* args - This is the arguments that you passed on your notification method on php&lt;br /&gt;
* bIsTableMsg - is true when you use [[Main_game_logic:_yourgamename.game.php#NotifyAllPlayers|NotifyAllPlayers]] method (false otherwise)&lt;br /&gt;
* channelorig - information about table ID (formatted as : &amp;quot;/table/t[TABLE_NUMBER]&amp;quot;)&lt;br /&gt;
* gamenameorig - name of the game&lt;br /&gt;
* move_id - ID of the move associated with the notification&lt;br /&gt;
* table_id - ID of the table (comes as string)&lt;br /&gt;
* time - UNIX GMT timestamp&lt;br /&gt;
* uid - unique identifier of the notification&lt;br /&gt;
* h - unknown&lt;br /&gt;
&lt;br /&gt;
&#039;&#039; Note that those information were inferred from observation on console log. If an Admin can confirm/correct (and remove this line), you&#039;re welcome :)&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
=== Ignoring notifications ===&lt;br /&gt;
&lt;br /&gt;
Sometimes you need to ignore some notification on client side. You don&#039;t want them to be shown in game log and you don&#039;t want them to be handled.&lt;br /&gt;
&lt;br /&gt;
The most common use case is when a player gets private information. They will receive a specific notification (such as &amp;quot;You received Ace of Heart&amp;quot;), while other players would receive more generic notification (&amp;quot;Player received a card&amp;quot;).&lt;br /&gt;
&lt;br /&gt;
In X.game.php&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        $this-&amp;gt;notifyAllPlayers(&amp;quot;dealCard&amp;quot;, clienttranslate(&#039;${player_name} received a card&#039;), [&lt;br /&gt;
            &#039;player_id&#039; =&amp;gt; $playerId,&lt;br /&gt;
            &#039;player_name&#039; =&amp;gt; $this-&amp;gt;getActivePlayerName()&lt;br /&gt;
        ]);&lt;br /&gt;
&lt;br /&gt;
        $this-&amp;gt;notifyPlayer($playerId, &amp;quot;dealCardPrivate&amp;quot;, clienttranslate(&#039;You received ${cardName}&#039;), [&lt;br /&gt;
            &amp;quot;type&amp;quot; =&amp;gt; $card[&amp;quot;type&amp;quot;],&lt;br /&gt;
            &amp;quot;cardName&amp;quot; =&amp;gt; $this-&amp;gt;getCardName($card[&amp;quot;type&amp;quot;])&lt;br /&gt;
        ]);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The problem with this approach is that the active player will receive two notifications:&lt;br /&gt;
* Player1 received a card&lt;br /&gt;
* You received Ace of Hearts&lt;br /&gt;
&lt;br /&gt;
Hence, notification ignoring.&lt;br /&gt;
&lt;br /&gt;
NOTE: You can think that it would be possible to send such notification to all players except active just by using notifyPlayer and it seems to work. The problem however is that table spectators would miss such notification and their user interface (and game log) wouldn&#039;t be updated. Since there is no way to send notification just to spectators, ignoring the notification (or &amp;quot;filtering&amp;quot;) is the only reasonable solution.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;setIgnoreNotificationCheck(notif_type: string, predicate: ((notif: Notif)=&amp;gt;boolean))&#039;&#039;&#039;&lt;br /&gt;
This method will set a check whether any of notifications of specific type should be ignored.&lt;br /&gt;
&lt;br /&gt;
The parameters are:&lt;br /&gt;
* notif_type: type of the notification &lt;br /&gt;
* predicate (notif =&amp;gt; boolean): a function that will receive notif object and will return true if this specific notification should be ignored&lt;br /&gt;
&lt;br /&gt;
Before dispatching any notification of this type, the framework will call predicate to check whether notification should be ignored, if it return true - the notification will be dispatched, i.e. logged or handled.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    this.notifqueue.setIgnoreNotificationCheck( &#039;dealCard&#039;, (notif) =&amp;gt; (notif.args.player_id == this.player_id) );&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
IMPORTANT: Remember that this notification is ignored on the client side, but was still received by the client. Therefore it shouldn&#039;t contain any private information as cheaters can get it. In other words this is not a way to hide information.&lt;br /&gt;
&lt;br /&gt;
IMPORTANT: When a game is reloaded with F5 or when opening a turn based game, old notifications are replayed as history notification. They are used just to update the game log and are stripped of all arguments except player_id, i18n and any argument present in message. If you use and other argument in your predicate you should &#039;&#039;&#039;preserve&#039;&#039;&#039; it as explained [[Main_game_logic:_yourgamename.game.php#Notify_players|here]].&lt;br /&gt;
&lt;br /&gt;
=== Synchronous notifications ===&lt;br /&gt;
&lt;br /&gt;
When several notifications are received by your game interface, these notifications are processed immediately, one after the other, in the same exact order they have been generated in your PHP game logic.&lt;br /&gt;
&lt;br /&gt;
However, sometimes, you need to give some time to the players to figure out what happened on the game before jumping to the next notification. Indeed, in many games, there are a lot of automatic actions, and the computer is going to resolve all these actions very fast if you don&#039;t tell it not to do so.&lt;br /&gt;
&lt;br /&gt;
As an example, for Reversi, when someone is playing a disc, we want to wait 500 milliseconds before doing anything else in order the opponent player can figure out what move has been played.&lt;br /&gt;
&lt;br /&gt;
Here&#039;s how we do this, right after our subscription:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    dojo.subscribe( &#039;playDisc&#039;, this, &amp;quot;notif_playDisc&amp;quot; );&lt;br /&gt;
    this.notifqueue.setSynchronous( &#039;playDisc&#039;, 500 );   // Wait 500 milliseconds after executing the playDisc handler&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
-----&lt;br /&gt;
&lt;br /&gt;
It is also possible to control the delay timing dynamically (e.g., using notification args). As an example, maybe your notification &#039;cardPlayed&#039; should pause for a different amount of time depending on the number or type of cards played.&lt;br /&gt;
&lt;br /&gt;
For this case, use &#039;&#039;&#039;setSynchronous&#039;&#039;&#039; without specifying the duration and use &#039;&#039;&#039;setSynchronousDuration&#039;&#039;&#039; within the notification callback.&lt;br /&gt;
&lt;br /&gt;
* NOTE: If you forget to invoke &#039;&#039;&#039;setSynchronousDuration&#039;&#039;&#039;, the game will remain paused forever!&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
setupNotifications: function () {&lt;br /&gt;
    dojo.subscribe( &#039;cardPlayed&#039;, this, &#039;notif_cardPlayed&#039; );&lt;br /&gt;
    this.notifqueue.setSynchronous( &#039;cardPlayed&#039; ); // wait time is dynamic&lt;br /&gt;
    ...&lt;br /&gt;
},&lt;br /&gt;
&lt;br /&gt;
notif_cardPlayed: function (notif) {&lt;br /&gt;
    // MUST call setSynchronousDuration&lt;br /&gt;
&lt;br /&gt;
    // Example 1: From notification args (PHP)&lt;br /&gt;
    this.notifqueue.setSynchronousDuration(notif.args.duration);&lt;br /&gt;
    ...&lt;br /&gt;
&lt;br /&gt;
    // Or, example 2: Match the duration to a Dojo animation&lt;br /&gt;
    var anim = dojo.fx.combine([&lt;br /&gt;
        ...&lt;br /&gt;
    ]);&lt;br /&gt;
    anim.play();&lt;br /&gt;
    this.notifqueue.setSynchronousDuration(anim.duration);&lt;br /&gt;
},&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You can also manually call this.notifqueue.setSynchronousDuration(0) once client operations are finished, but be careful that even fast replay still has a path to call it.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;WARNING: combining synchronous and ignored notifications&#039;&#039;&#039;&lt;br /&gt;
You must be careful when combining dynamic synchronous durations (as described above) with ignored notifications. If you have a conditionally ignored notification like this (see below section):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;this.notifqueue.setIgnoreNotificationCheck( &#039;myNotif&#039;, (notif) =&amp;gt; (notif.args.player_id == this.player_id) /* or any other condition */ )&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
then you CANNOT do&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;this.notifqueue.setSynchronous(&#039;myNotif&#039;);&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
as, when the ignored check passes, the notification handler, in which `this.notifqueue.setSychronousDuration` is called, is never called and so the duration is never set and interface locking results.&lt;br /&gt;
&lt;br /&gt;
The workaround is to set a &amp;quot;dummy&amp;quot; time:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;this.notifqueue.setSynchronous(&#039;myNotif&#039;, 5000);&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
whose value is irrelevant but must be large enough to cover the time before the notification handler is called. The large value never actually comes into play because the notification is either ignored, or the synchronous duration is reset to a sensible value inside the handler.&lt;br /&gt;
&lt;br /&gt;
=== Pre-defined notification types ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;tableWindow&#039;&#039;&#039; - This defines notification to display [[Game_interface_logic:_yourgamename.js#Scoring_dialogs|Scoring Dialogs]], see below.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;message&#039;&#039;&#039; - This defines notification that shows on players log and have no other effect (technically any unhandled notification will do the same but its recommended to use this keyword for consistency)&lt;br /&gt;
&lt;br /&gt;
   // You can call this on php side without doing anything on client side&lt;br /&gt;
    self::notifyAllPlayers( &#039;message&#039;, clienttranslate(&#039;hello&#039;), [] );&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;simplePause&#039;&#039;&#039; - This notification will just delay other notifications, maybe useful if you know you need some extra time for animation or something. Requires a time parameter.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    self::notifyAllPlayers( &#039;simplePause&#039;, &#039;&#039;, [ &#039;time&#039; =&amp;gt; 500] ); // time is in milliseconds&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note: the following types are RESERVED by framework, do not use:&lt;br /&gt;
&lt;br /&gt;
gameStateChange gameStateChangePrivateArg gameStateMultipleActiveUpdate newActivePlayer playerstatus yourturnack clockalert tableInfosChanged playerEliminated tableDecision  archivewaitingdelay end_archivewaitingdelay replaywaitingdelay end_replaywaitingdelay replayinitialwaitingdelay end_replayinitialwaitingdelay aiPlayerWaitingDelay replay_has_ended updateSpectatorList  wouldlikethink updateReflexionTime undoRestorePoint resetInterfaceWithAllDatas zombieModeFail zombieModeFailWarning aiError skipTurnOfPlayer zombieBack allPlayersAreZombie gameResultNeutralized playerConcedeGame showTutorial showCursor showCursorClick skipTurnOfPlayerWarning  banFromTable resultsAvailable switchToTurnbased newPrivateState infomsg&lt;br /&gt;
&lt;br /&gt;
== Tooltips ==&lt;br /&gt;
&lt;br /&gt;
=== Adding static tooltips ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.addTooltip(nodeId: string, helpStringTranslated: string, actionStringTranslated: string, delay?: number): void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Add a simple text tooltip to the DOM node.&lt;br /&gt;
&lt;br /&gt;
Specify &#039;helpStringTranslated&#039; to display some information about &amp;quot;what is this game element?&amp;quot;.&lt;br /&gt;
Specify &#039;actionStringTranslated&#039; to display some information about &amp;quot;what happens when I click on this element?&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
You must specify both of the strings. You can only use one and specify an empty string (&#039;&#039;) for the other one.&lt;br /&gt;
&lt;br /&gt;
When you pass text directly function _() must be used for the text to be marked for translation! Except for empty string.&lt;br /&gt;
&lt;br /&gt;
Parameter &amp;quot;delay&amp;quot; is optional. It is primarily used to specify a zero delay for some game element when the tooltip gives really important information for the game - but remember: no essential information must be placed in tooltips as they won&#039;t be displayed in some browsers (see [[BGA_Studio_Guidelines|Guidelines]]).&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
   this.addTooltip( &#039;cardcount&#039;, _(&#039;Number of cards in hand&#039;), &#039;&#039; );&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note: this generates static tooltip and attaches to existing dom element, if you need to generate tooltip more dynamically you have to call that method every time information about object is updated or use completely different tehnique, see dynamic tooltips below.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.addTooltipHtml(nodeId: string, html: string, delay?: number): void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Add an HTML tooltip to the DOM node (for more elaborate content such as presenting a bigger version of a card).&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.addTooltipToClass(cssClass: string, helpStringTranslated: string, actionStringTranslated: string, delay?: number ): void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Add a simple text tooltip to all the DOM nodes set with this cssClass. See more details above for this.addTooltip.&lt;br /&gt;
     this.addTooltipToClass( &#039;meeple&#039;, _(&#039;This is A Meeple&#039;), _(&#039;Click to tickle&#039;) );&lt;br /&gt;
&lt;br /&gt;
IMPORTANT: all concerned nodes must exist and have IDs to get tooltips.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.addTooltipHtmlToClass(cssClass: string, html: string, delay?: number): void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Add an HTML tooltip to to all the DOM nodes set with this cssClass (for more elaborate content such as presenting a bigger version of a card).&lt;br /&gt;
&lt;br /&gt;
IMPORTANT: all concerned nodes must exist and have IDs to get tooltips.&lt;br /&gt;
&lt;br /&gt;
=== Removing static tooltips ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.removeTooltip(nodeId: string): void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Remove a tooltip from the DOM node with given id.&lt;br /&gt;
&lt;br /&gt;
=== Advanced tooltips ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;force tooltip to open&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
If you want to force tooltip to open in reaction to some other action, i.e. click you can do this&lt;br /&gt;
&lt;br /&gt;
   this.tooltips[id].open(id)&lt;br /&gt;
&lt;br /&gt;
where id is the id of the tooltip node where tooltip was installed.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;dynamic tooltips&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
See [[BGA_Studio_Cookbook#Dynamic_tooltips]]&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;tooltips on mobile&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Tooltips is very unreliable on mobile, it is recommended to implement some other method to obtaining same information,&lt;br /&gt;
such as simple click handler in dedicated &amp;quot;Help&amp;quot; mode or provide dedicated clickable areas such as corner of card.&lt;br /&gt;
&lt;br /&gt;
== Warning messages ==&lt;br /&gt;
&lt;br /&gt;
Sometimes, there is something important that is happening in the game and you have to make sure all players get the message. Most of the time, the evolution of the game situation or the game log is enough, but sometimes you need something more visible.&lt;br /&gt;
&lt;br /&gt;
Ex: someone fulfills one of the end of the game conditions, so this is the last turn.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.showMessage(msg: string, type: string): void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
showMessage shows a message in a big rectangular area on the top of the screen of the current player, and it dissapears after few seconds (also it will be in the log in some cases).&lt;br /&gt;
&lt;br /&gt;
* &amp;quot;msg&amp;quot; is the string to display. It should be translated.&lt;br /&gt;
* &amp;quot;type&amp;quot; can be set to &amp;quot;info&amp;quot;, &amp;quot;error&amp;quot;, &amp;quot;only_to_log&amp;quot; or custom string. If set to &amp;quot;info&amp;quot;, the message will be an informative message on a white background. If set to &amp;quot;error&amp;quot;, the message will be an error message on a red background and it will be added to log. If set to &amp;quot;only_to_log&amp;quot;, the message will be added to the game log but will not popup at the top of the screen.&lt;br /&gt;
If set to custom string, it will be transparent, to use custom type define &amp;quot;head_xxx&amp;quot; in css, where xxx is the type. For example if you want yellow warning, use &amp;quot;warning&amp;quot; as type and add this to css:&lt;br /&gt;
 .head_warning {&lt;br /&gt;
    background-color: #e6c66e;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
Important: the normal way to inform players about the progression of the game is the game log. The &amp;quot;showMessage&amp;quot; is intrusive and should not be used often.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    notif_messageinfo: function(notif) {&lt;br /&gt;
	if (!g_archive_mode) {&lt;br /&gt;
        	var message = this.format_string_recursive(notif.log, notif.args);&lt;br /&gt;
		this.showMessage(_(&#039;Announcement:&#039;) + &amp;quot; &amp;quot; + message, &#039;info&#039;);		&lt;br /&gt;
         }&lt;br /&gt;
    },&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Show message could be used on the client side to prevent user wrong moves before it is send to server.&lt;br /&gt;
Example from &#039;battleship&#039;:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
onGrid: function(event) {&lt;br /&gt;
     if (checkIfPlayerTriesToFireOnThemselves(event)) {&lt;br /&gt;
        this.showMessage(_(&#039;This is your own board silly!&#039;), &#039;error&#039;);&lt;br /&gt;
        return;&lt;br /&gt;
     }&lt;br /&gt;
     ...&lt;br /&gt;
},&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.showMoveUnauthorized(): void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Shows predefined user error that move is unauthorized now&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
onPet: function(event) {&lt;br /&gt;
     if (checkPet(event)==false) {&lt;br /&gt;
        this.showMoveUnauthorized();&lt;br /&gt;
        return;&lt;br /&gt;
     }&lt;br /&gt;
     ...&lt;br /&gt;
},&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Dialogs ==&lt;br /&gt;
&lt;br /&gt;
=== Confirmation dialog ===&lt;br /&gt;
&lt;br /&gt;
When an important action with a lot of consequences is triggered by the player, you may want to propose a confirmation dialog.&lt;br /&gt;
&lt;br /&gt;
CAREFUL: the general guideline of BGA is to AVOID the use of confirmation dialogs. Confirmation dialogs slow down the game and bother players. The players know that they have to pay attention to each move when they are playing online.&lt;br /&gt;
&lt;br /&gt;
The situations where you should use a confirmation dialog are the following:&lt;br /&gt;
* It must not happen very often during a game.&lt;br /&gt;
* It must be linked to an action that can really &amp;quot;kill a game&amp;quot; if the player does not pay attention.&lt;br /&gt;
* It must be something that can be done by mistake (ex: a link on the action status bar).&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.confirmationDialog(message: string, yesHandler: (param: any) =&amp;gt; void, noHandler?: (param: any) =&amp;gt; void, param?: any): void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
* message - message will be shown to user, use _() to translate&lt;br /&gt;
* yesHandler - non-optional handler to be called on yes&lt;br /&gt;
* noHandler - optional handler to called on no&lt;br /&gt;
* param - if specified, it will be passed to both handlers&lt;br /&gt;
NOTE: this is async function, it does not return anything and you should not do anything after, you must do everything in handlers&lt;br /&gt;
&lt;br /&gt;
How to display a confirmation dialog:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    this.confirmationDialog(_(&amp;quot;Are you sure you want to bake a pie?&amp;quot;), () =&amp;gt; {&lt;br /&gt;
      this.bakeThePie();&lt;br /&gt;
    });&lt;br /&gt;
    return; // nothing should be called or done after calling this, all action must be done in the handler&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
With param and both handlers&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    this.confirmationDialog(_(&amp;quot;Are you sure you want to bake a pie?&amp;quot;), &lt;br /&gt;
           (ingredient) =&amp;gt; this.bakeThePie(ingredient), &lt;br /&gt;
           (ingredient) =&amp;gt; console.log(`cancelled baking of ${ingredient}`), &lt;br /&gt;
           &#039;apple&#039;);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Multiple choice dialog ===&lt;br /&gt;
&lt;br /&gt;
You can use this dialog to give user a choice with small amount of options&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.multipleChoiceDialog(message: string, choices: string[], callback: (choice: number) =&amp;gt; void): void&#039;&#039;&#039;&lt;br /&gt;
* message - message will be shown to user, use _() to translate&lt;br /&gt;
* choices - array of choices&lt;br /&gt;
* callback - non-optional handler to be called on choice made, the choice parameter is the INDEX of the choice from the array of choices&lt;br /&gt;
&lt;br /&gt;
NOTE: this is async function, it does not return anything and you should not do anything after, you must do everything in handlers&lt;br /&gt;
NOTE: there is no cancel handler, so make sure you gave user a choice to get out of it&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    const keys = [&amp;quot;0&amp;quot;, &amp;quot;1&amp;quot;, &amp;quot;5&amp;quot;, &amp;quot;10&amp;quot;];&lt;br /&gt;
    this.multipleChoiceDialog(_(&amp;quot;How many bugs to fix?&amp;quot;), keys, (choice) =&amp;gt; {&lt;br /&gt;
      if (choice==0) return; // cancel operation, do not call server action&lt;br /&gt;
      var bugchoice = keys[choice]; // choice will be 0,1,2,3 here&lt;br /&gt;
      this.bgaPerformAction(&amp;quot;fixBugs&amp;quot;, { number: bugchoice });&lt;br /&gt;
    });&lt;br /&gt;
    return; // must return here&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Generic Dialogs ===&lt;br /&gt;
&lt;br /&gt;
As a general rule, you shouldn&#039;t use dialogs windows.&lt;br /&gt;
&lt;br /&gt;
BGA guidelines specify that all game elements should be displayed on the main screen. Players can eventually scroll down to see game elements they don&#039;t need to see anytime, and you may eventually create anchors to move between game area section. Of course dialogs windows are very practical, but the thing is: all players know how to scroll down, and not all players know how to show up your dialog window. In addition, when the dialog shows up, players can&#039;t access the other game components.&lt;br /&gt;
&lt;br /&gt;
Sometimes although, you need to display a dialog window. Here is how you do this:&lt;br /&gt;
&lt;br /&gt;
  // Create the new dialog over the play zone. You should store the handler in a member variable to access it later&lt;br /&gt;
  this.myDlg = new ebg.popindialog();&lt;br /&gt;
  this.myDlg.create( &#039;myDialogUniqueId&#039; );&lt;br /&gt;
  this.myDlg.setTitle( _(&amp;quot;my dialog title to translate&amp;quot;) );&lt;br /&gt;
  this.myDlg.setMaxWidth( 500 ); // Optional&lt;br /&gt;
  &lt;br /&gt;
  // Create the HTML of my dialog. &lt;br /&gt;
  // The best practice here is to use [[Game_layout:_view_and_template:_yourgamename.view.php_and_yourgamename_yourgamename.tpl#Javascript_templates|Javascript templates]]&lt;br /&gt;
  var html = this.format_block( &#039;jstpl_myDialogTemplate&#039;, { &lt;br /&gt;
                arg1: myArg1,&lt;br /&gt;
                arg2: myArg2,&lt;br /&gt;
                ...&lt;br /&gt;
            } );  &lt;br /&gt;
  &lt;br /&gt;
  // Show the dialog&lt;br /&gt;
  this.myDlg.setContent( html ); // Must be set before calling show() so that the size of the content is defined before positioning the dialog&lt;br /&gt;
  this.myDlg.show();&lt;br /&gt;
  &lt;br /&gt;
  // Now that the dialog has been displayed, you can connect your method to some dialog elements&lt;br /&gt;
  // Example, if you have an &amp;quot;OK&amp;quot; button in the HTML of your dialog:&lt;br /&gt;
  dojo.connect($(&#039;my_ok_button&#039;), &#039;onclick&#039;, this, (event) =&amp;gt; {&lt;br /&gt;
                event.preventDefault();&lt;br /&gt;
                this.myDlg.destroy();&lt;br /&gt;
            });&lt;br /&gt;
&lt;br /&gt;
If necessary, you can remove the default top right corner &#039;close&#039; icon, or replace the function called when it is clicked:&lt;br /&gt;
  // Removes the default close icon&lt;br /&gt;
  this.myDlg.hideCloseIcon();&lt;br /&gt;
&lt;br /&gt;
  // Replace the function call when it&#039;s clicked&lt;br /&gt;
  this.myDlg.replaceCloseCallback((event) =&amp;gt; { ... });&lt;br /&gt;
&lt;br /&gt;
=== Scoring dialogs ===&lt;br /&gt;
&lt;br /&gt;
Sometimes at the end of a round you want to display a big table that details the points wins in each section of the game.&lt;br /&gt;
&lt;br /&gt;
Example: in Hearts game, we display at the end of each round the number of &amp;quot;heart&amp;quot; cards collected by each player, the player who collected the Queen of Spades, and the total number of points loose by each player.&lt;br /&gt;
&lt;br /&gt;
Scoring dialogs are managed entirely on &#039;&#039;&#039;PHP side&#039;&#039;&#039;, but they are described here as their effects are visible only on client side.&lt;br /&gt;
&lt;br /&gt;
Displaying a scoring dialog is quite simple and is using a special notification type: &amp;quot;tableWindow&amp;quot;:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  // on PHP side:&lt;br /&gt;
  $this-&amp;gt;notifyAllPlayers( &amp;quot;tableWindow&amp;quot;, &#039;&#039;, array(&lt;br /&gt;
            &amp;quot;id&amp;quot; =&amp;gt; &#039;finalScoring&#039;,&lt;br /&gt;
            &amp;quot;title&amp;quot; =&amp;gt; clienttranslate(&amp;quot;Title of the scoring dialog&amp;quot;),&lt;br /&gt;
            &amp;quot;table&amp;quot; =&amp;gt; $table&lt;br /&gt;
        )); &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The &amp;quot;table&amp;quot; argument is a 2 dimensional PHP array that describes the table you want to display, line by line and column by column.&lt;br /&gt;
&lt;br /&gt;
Example: display an 3x3 array of strings&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
   $table = [&lt;br /&gt;
      [ &amp;quot;one&amp;quot;, &amp;quot;two&amp;quot;, &amp;quot;three&amp;quot; ],    // This is my first line&lt;br /&gt;
      [ &amp;quot;four&amp;quot;, &amp;quot;five&amp;quot;, &amp;quot;six&amp;quot; ],    // This is my second line&lt;br /&gt;
      [ &amp;quot;seven&amp;quot;, &amp;quot;height&amp;quot;, &amp;quot;nine&amp;quot; ]    // This is my third line&lt;br /&gt;
   ];&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
As you can see above, in each &amp;quot;cell&amp;quot; of your array you can display a simple string value. But you can also display a complex value with a template and associated arguments like this:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
   $table = [&lt;br /&gt;
      [ &amp;quot;one&amp;quot;, &amp;quot;two&amp;quot;, [ &amp;quot;str&amp;quot; =&amp;gt; clienttranslate(&amp;quot;a string with an ${argument}&amp;quot;), &amp;quot;args&amp;quot; =&amp;gt; [ &#039;argument&#039; =&amp;gt; &#039;argument_value&#039; ] ] ],&lt;br /&gt;
      [ &amp;quot;four&amp;quot;, &amp;quot;five&amp;quot;, &amp;quot;six&amp;quot; ], &lt;br /&gt;
      [ &amp;quot;seven&amp;quot;, &amp;quot;height&amp;quot;, &amp;quot;nine&amp;quot; ]&lt;br /&gt;
   ];&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This is especially useful when you want to display player names with colors. Example from &amp;quot;Hearts&amp;quot;:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        $firstRow = [ &#039;&#039; ];&lt;br /&gt;
        foreach( $players as $player_id =&amp;gt; $player )    {&lt;br /&gt;
            $cell = [ &#039;str&#039; =&amp;gt; &#039;${player_name}&#039;,&lt;br /&gt;
                      &#039;args&#039; =&amp;gt; [ &#039;player_name&#039; =&amp;gt; $player[&#039;player_name&#039;] ],&lt;br /&gt;
                      &#039;type&#039; =&amp;gt; &#039;header&#039;&lt;br /&gt;
                    ];&lt;br /&gt;
            $firstRow[] = $cell;&lt;br /&gt;
        }&lt;br /&gt;
        $table[] = $firstRow;&lt;br /&gt;
        ...&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You can also use three extra attributes in the parameter array for the notification:&lt;br /&gt;
* &#039;&#039;&#039;header&#039;&#039;&#039;: the content for this parameter displays before the table (also, the html will be parsed and player names will be colored according to the current game colors). &lt;br /&gt;
* &#039;&#039;&#039;footer&#039;&#039;&#039;: the content for this parameter displays after the table (no parsing for coloring the player names)&lt;br /&gt;
* &#039;&#039;&#039;closing&#039;&#039;&#039;: if this parameter is used, a button will be displayed with this label at the bottom of the popup and will allow players to close it (more easily than by clicking the top right &#039;cross&#039; icon).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
   $this-&amp;gt;notifyAllPlayers( &amp;quot;tableWindow&amp;quot;, &#039;&#039;, [&lt;br /&gt;
            &amp;quot;id&amp;quot; =&amp;gt; &#039;finalScoring&#039;,&lt;br /&gt;
            &amp;quot;title&amp;quot; =&amp;gt; clienttranslate(&amp;quot;Title of the scoring dialog&amp;quot;),&lt;br /&gt;
            &amp;quot;table&amp;quot; =&amp;gt; $table,&lt;br /&gt;
            &amp;quot;header&amp;quot; =&amp;gt; [&#039;str&#039; =&amp;gt; clienttranslate(&#039;Table header with parameter ${number}&#039;),&lt;br /&gt;
                                 &#039;args&#039; =&amp;gt; [ &#039;number&#039; =&amp;gt; 3 ],&lt;br /&gt;
                               ],&lt;br /&gt;
            &amp;quot;footer&amp;quot; =&amp;gt; &#039;&amp;lt;div class=&amp;quot;myfoot&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&#039;,&lt;br /&gt;
            &amp;quot;closing&amp;quot; =&amp;gt; clienttranslate( &amp;quot;Closing button label&amp;quot; )&lt;br /&gt;
        ] ); &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note: currently id is not used - so you cannot access resulting div by id on js side&lt;br /&gt;
Note: any traslatable stirng have to be wrapped by clienttranslate() on top level OR it has to be recursive template. &lt;br /&gt;
&lt;br /&gt;
DO NOT DO THIS: &lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
   &amp;quot;footer&amp;quot; =&amp;gt; &#039;&amp;lt;div&amp;gt;&#039;.clienttranslate( &amp;quot;The end&amp;quot; ).&#039;&amp;lt;/div&amp;gt;&#039;, // this will not work for translations!!!&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Scoring animated display ===&lt;br /&gt;
&lt;br /&gt;
Sometimes, you may want to display a score value over an element to make the scoring easier to follow for the players (Terra Mystica final scoring for example).&lt;br /&gt;
You can do it with:&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.displayScoring(anchor_id: string, color: string, score: number | string, duration?: number, offset_x?: number, offset_y?: number): void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;anchor_id&#039;&#039;&#039;: ID of the html element to place the animated score onto (without the &#039;#&#039;) &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;color&#039;&#039;&#039;: hexadecimal RGB representation of the color (should be the color of the scoring player), but without a leading &#039;#&#039;.  For instance, &#039;ff0000&#039; for red.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;score&#039;&#039;&#039;: numeric score to display, prefixed by a &#039;+&#039; or &#039;-&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;duration&#039;&#039;&#039;: animation duration in milliseconds (optional, default is 1000)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;offset_x&#039;&#039;&#039; and &#039;&#039;&#039;offset_y&#039;&#039;&#039;: if both offset_x and offset_y are defined and not null, apply the following offset (in pixels) to the scoring animation. &lt;br /&gt;
Note that the score is centered in the anchor, so the offsets might have to be negative if you calculate the position.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Note: if you want to display successively each score, you can use &#039;&#039;this.notifqueue.setSynchronous()&#039;&#039; function.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    setupNotifications: function()   {&lt;br /&gt;
           dojo.subscribe( &#039;displayScoring&#039;, this, &amp;quot;notif_displayScoring&amp;quot; );&lt;br /&gt;
           ...&lt;br /&gt;
    }&lt;br /&gt;
...&lt;br /&gt;
&lt;br /&gt;
    notif_displayScoring: function(notif) {&lt;br /&gt;
            const duration = notif.args.duration?notif.args.duration:1000;&lt;br /&gt;
            this.notifqueue.setSynchronous(&#039;displayScoring&#039;, duration );&lt;br /&gt;
	    this.displayScoring( notif.args.target, notif.args.color, notif.args.score, duration);&lt;br /&gt;
    },&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Speech bubble ===&lt;br /&gt;
&lt;br /&gt;
For better interactivity in some games (Love Letter for example), you may use comic book style speech bubbles to express the players voices.&lt;br /&gt;
This is done with showBubble:&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.showBubble(anchor_id: string, text: string, delay?: number, duration?: number, custom_class?: string): void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
* anchor_id - where to attach the bubble&lt;br /&gt;
* text - what to put in bubble, can be html&lt;br /&gt;
* delay - delay in milliseconds (optional, default 0)&lt;br /&gt;
* duration -  duration of animation in milliseconds (optional, default 3000)&lt;br /&gt;
* custom_class - extra class to add to bubble (optional), if you need to override the default bubble style&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
   this.showBubble(&#039;meeple_2&#039;, _(&#039;Hello&#039;), 0, 1000, &#039;pink_bubble&#039;);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  notif_speechBubble(notif) {&lt;br /&gt;
    var html = this.format_string_recursive(notif.args.text, notif.args.args);&lt;br /&gt;
    this.showBubble(notif.args.target, html, notif.args.delay ?? 0, notif.args.duration ?? 1000);&lt;br /&gt;
  },&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Warning&#039;&#039;&#039;: if your bubble could overlap other active elements of the interface (buttons in particular), as it stays in place even after disappearing, you should use a custom class to give it the style &amp;quot;pointer-events: none;&amp;quot; in order to intercept click events.&lt;br /&gt;
&lt;br /&gt;
Note: If you want this visually, but want to take complete control over this bubble and its animation (for example to make it permanent) you can just use div with &#039;discussion_bubble&#039; class on it, and content of div is what will be shown.&lt;br /&gt;
&lt;br /&gt;
== Translations ==&lt;br /&gt;
&lt;br /&gt;
See [[Translations]]&lt;br /&gt;
&lt;br /&gt;
== Players panels ==&lt;br /&gt;
&lt;br /&gt;
=== Update players score ===&lt;br /&gt;
&lt;br /&gt;
The column player_score from the player table is automatically loaded into this.scoreCtrl and therefore into the stars location on the player board. This occurs sometime after the game setup() function. However this score must be updated as the game progresses using notifications.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Note: this.scoreCtrl[player_id] is object of class [[Counter]], you can use other counter API.&lt;br /&gt;
&lt;br /&gt;
Increase a player score (with a positive or negative number):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  this.scoreCtrl[ player_id ].incValue( score_delta );&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Set a player score to a specific value:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  this.scoreCtrl[ player_id ].setValue( new_score );&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Set a player score to a specific value with animation:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  this.scoreCtrl[ player_id ].toValue( new_score );&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Typical usage would be (that will process &#039;score&#039; notification):&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        setupNotifications : function() {&lt;br /&gt;
              ...&lt;br /&gt;
             dojo.subscribe(&#039;score&#039;, this, &amp;quot;notif_score&amp;quot;);&lt;br /&gt;
        },&lt;br /&gt;
        notif_score: function(notif) {&lt;br /&gt;
            this.scoreCtrl[notif.args.player_id].setValue(notif.args.player_score);&lt;br /&gt;
        },&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Adding stuff to player&#039;s panel ===&lt;br /&gt;
&lt;br /&gt;
At first, create a new &amp;quot;JS template&amp;quot; string in your template (tpl) file:&lt;br /&gt;
&lt;br /&gt;
(from Gomoku example)&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
var jstpl_player_board = &#039;\&amp;lt;div class=&amp;quot;cp_board&amp;quot;&amp;gt;\&lt;br /&gt;
    &amp;lt;div id=&amp;quot;stoneicon_p${id}&amp;quot; class=&amp;quot;gmk_stoneicon gmk_stoneicon_${color}&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&amp;lt;span id=&amp;quot;stonecount_p${id}&amp;quot;&amp;gt;0&amp;lt;/span&amp;gt;\&lt;br /&gt;
&amp;lt;/div&amp;gt;&#039;;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Then, you add this piece of code in your JS file to add this template to each player panel:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
            // Setting up player boards&lt;br /&gt;
            for( var player_id in gamedatas.players )&lt;br /&gt;
            {&lt;br /&gt;
                var player = gamedatas.players[player_id];&lt;br /&gt;
                         &lt;br /&gt;
                // Setting up players boards if needed&lt;br /&gt;
                var player_board_div = $(&#039;player_board_&#039;+player_id);&lt;br /&gt;
                dojo.place( this.format_block(&#039;jstpl_player_board&#039;, player ), player_board_div );&lt;br /&gt;
            }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
(Note: the code above is of course from your &amp;quot;setup&amp;quot; function in your Javascript).&lt;br /&gt;
&lt;br /&gt;
Very often, you have to distinguish current player and others players. In this case, you just have to create another JS template (ex: jstpl_otherplayer_board) and use it when &amp;quot;player_id&amp;quot; is different than &amp;quot;this.player_id&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Fixing Player Panel heights ===&lt;br /&gt;
&lt;br /&gt;
You may find that the player panels don&#039;t automatically resize when adding something to (or removing something from) a player panel while the display is in portrait mode (i.e. the player summary panels are at the top of the screen rather than down the right side).&lt;br /&gt;
&lt;br /&gt;
When this happens, call &amp;lt;pre&amp;gt;this.adaptPlayersPanels();&amp;lt;/pre&amp;gt; This recalculates the layout and also adjusts the position of the actionbar for you.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Player&#039;s panel disabling/enabling ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.disablePlayerPanel(player_id: number): void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Disable given player panel (the panel background become gray).&lt;br /&gt;
&lt;br /&gt;
Usually, this is used to signal that this played passes, or will be inactive during a while.&lt;br /&gt;
&lt;br /&gt;
Note that the only effect of this is visual. There are no consequences on the behaviour of the panel itself.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.enablePlayerPanel(player_id:number): void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Enable a player panel that has been disabled before.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.enableAllPlayerPanels(): void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Enable all player panels that has been disabled before.&lt;br /&gt;
&lt;br /&gt;
=== Player order ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.updatePlayerOrdering(): void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
This function makes sure that player order in player&#039;s panel matches this.gamedatas.playerorder and its normally called by framework.&lt;br /&gt;
You can call it yoursel if you change this.gamedatas.playerorder from notification.&lt;br /&gt;
Also you can override this function to change defaults  OR insert a non-player panel [[BGA_Studio_Cookbook#Inserting_non-player_panel]].&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Counters ===&lt;br /&gt;
Note: there is bga component called  &amp;quot;ebg/counter&amp;quot; this API is not using it, these methods&lt;br /&gt;
below declared right in core game. If you need animation for counters use ebg/counter&lt;br /&gt;
&lt;br /&gt;
To use this API just create a counter dom element like this (class does not really matter)&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 &amp;lt;div class=&amp;quot;counter&amp;quot; id=&amp;quot;bread&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
 &amp;lt;div class=&amp;quot;counter&amp;quot; id=&amp;quot;coin&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
The &amp;quot;bread&amp;quot; will the counter name.&lt;br /&gt;
&lt;br /&gt;
The php code should send all &amp;quot;counters&amp;quot; data from getAllDatas() method like this&lt;br /&gt;
&lt;br /&gt;
game.php&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  protected function getAllDatas() {&lt;br /&gt;
    // (the key must match counter_name)&lt;br /&gt;
    $result[&#039;counters&#039;]=[&lt;br /&gt;
        &#039;bread&#039; =&amp;gt; [ &lt;br /&gt;
         &#039;counter_name&#039; =&amp;gt; &#039;bread&#039;, &lt;br /&gt;
         &#039;counter_value&#039; =&amp;gt; 3&lt;br /&gt;
         ], &lt;br /&gt;
        &#039;coin&#039; =&amp;gt; [&lt;br /&gt;
          &#039;counter_name&#039; =&amp;gt; &#039;coin&#039;, &lt;br /&gt;
          &#039;counter_value&#039; =&amp;gt; 5&lt;br /&gt;
        ]&lt;br /&gt;
   ];&lt;br /&gt;
   return $result;&lt;br /&gt;
  }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;setCounter(counter_name: stirng, new_value: string | number): void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
updates the global this.gamedatas.counters and value of node $(counter_name)&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  notif_counter: function(notif) { &lt;br /&gt;
    this.setCounter(notif.args.counter_name, notif.args.counter_value);&lt;br /&gt;
  },&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;incCounter(counter_name: string, delta: number): void&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  notif_counter : function(notif) {&lt;br /&gt;
    this.incCounter(notif.args.counter_name, notif.args.inc);&lt;br /&gt;
  },&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;updateCounters(counters: object): void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Useful for updating game counters in the player panel (such as resources). &lt;br /&gt;
&#039;counters&#039; arg is map of counters (the key must match counter_name)&lt;br /&gt;
  {&lt;br /&gt;
    &#039;bread&#039;: { &lt;br /&gt;
         &#039;counter_name&#039; : &#039;bread&#039;, &lt;br /&gt;
         &#039;counter_value&#039; =&amp;gt; 3&lt;br /&gt;
    }, &lt;br /&gt;
    &#039;coin&#039;: { &lt;br /&gt;
         &#039;counter_name&#039; : &#039;coin&#039;, &lt;br /&gt;
         &#039;counter_value&#039; =&amp;gt; 5&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
All counters MUST be referenced in this.gamedatas.counters (means they should be send from php) and will be updated.&lt;br /&gt;
DOM objects referenced by &#039;counter_name&#039; will have their innerHTML updated with &#039;counter_value&#039;.&lt;br /&gt;
&lt;br /&gt;
Usually you call this from notification&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
                        notif_counter : function(notif) {&lt;br /&gt;
                            this.updateCounters(notif.args.counters);&lt;br /&gt;
                        },&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== BGA GUI components ==&lt;br /&gt;
&lt;br /&gt;
BGA framework provides some useful ready-to-use components for the game interface:&lt;br /&gt;
&lt;br /&gt;
[[Studio#BGA_Studio_game_components_reference]]&lt;br /&gt;
&lt;br /&gt;
Note that each time you are using an additional component, you must declare it at the top of your Javascript file in the list of modules used.&lt;br /&gt;
&lt;br /&gt;
Example if you are using &amp;quot;ebg.stock&amp;quot;:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
define([&lt;br /&gt;
    &amp;quot;dojo&amp;quot;,&amp;quot;dojo/_base/declare&amp;quot;,&lt;br /&gt;
    &amp;quot;ebg/core/gamegui&amp;quot;,&lt;br /&gt;
    &amp;quot;ebg/counter&amp;quot;,&lt;br /&gt;
    &amp;quot;ebg/stock&amp;quot;  /// &amp;lt;=== we are using ebg.stock module&lt;br /&gt;
],&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== BGA Buttons ==&lt;br /&gt;
&lt;br /&gt;
=== Basic Button ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.addActionButton(id: string, label: string, method: string | eventhandler, destination?: string, blinking?: boolean, color?: string): void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
You can use this method to add an action button in the main action status bar (or other places).&lt;br /&gt;
&lt;br /&gt;
Arguments:&lt;br /&gt;
* id: an element ID that should be unique in your HTML DOM document.&lt;br /&gt;
* label: the text of the button. Should be translatable (use _() function). Note: this can also be any html, such as &amp;quot;&amp;lt;div class=&#039;brick&#039;&amp;gt;&amp;lt;/div&amp;gt;&amp;quot;, see example below on how to make image action buttons.&lt;br /&gt;
* method: the name of your method that must be triggered when the player clicks on this button (can be name of the method on game class or handler).&lt;br /&gt;
* destination (optional): id of parent on where to add button, ONLY use in rare cases if location is not action bar. Use &#039;&#039;&#039;null&#039;&#039;&#039; as value if you need to specify other arguments.&lt;br /&gt;
* blinking (optional): if set to &#039;&#039;&#039;true&#039;&#039;&#039;, the button is going blink to catch player&#039;s attention. Please DO NOT abuse blinking button. If you need button to blink after some time passed add class &#039;blinking&#039; to the button later.&lt;br /&gt;
* color: could be &#039;&#039;&#039;blue&#039;&#039;&#039; (default), &#039;&#039;&#039;red&#039;&#039;&#039;,&#039;&#039;&#039;gray&#039;&#039;&#039; or &#039;&#039;&#039;none&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
You should only use this method in your &amp;quot;onUpdateActionButtons&amp;quot; method. Usually, you use it like this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        onUpdateActionButtons: function( stateName, args ) {                      &lt;br /&gt;
            if (this.isCurrentPlayerActive()) {            &lt;br /&gt;
                switch( stateName ) {&lt;br /&gt;
                case &#039;giveCards&#039;:&lt;br /&gt;
                    this.addActionButton( &#039;giveCards_button&#039;, _(&#039;Give selected cards&#039;), &#039;onGiveCards&#039; ); &lt;br /&gt;
                    this.addActionButton( &#039;pass_button&#039;, _(&#039;Pass&#039;), () =&amp;gt; this.bgaPerformAction(&#039;actPass&#039;) ); &lt;br /&gt;
                    break;&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        },   &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In the example above, we are adding a &amp;quot;Give selected cards&amp;quot; button in the case we are on game state &amp;quot;giveCards&amp;quot;. When player clicks on this button, it triggers our &amp;quot;onGiveCards&amp;quot; method.&lt;br /&gt;
&lt;br /&gt;
Example using blinking red button:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    this.addActionButton( &#039;button_confirm&#039;, _(&#039;Confirm?&#039;), &#039;onConfirm&#039;, null, true, &#039;red&#039;); &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If you want to call the handler with arguments, you can use arrow functions, like this:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
     this.addActionButton( &#039;commit_button&#039;, _(&#039;Confirm&#039;), () =&amp;gt; this.onConfirm(this.selectedCardId), null, false, &#039;red&#039;); &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Image Button ===&lt;br /&gt;
&lt;br /&gt;
You can use the same method, but add extra class to a button to disable the padding and style it, i.e.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
this.addActionButton( &#039;button_brick&#039;, &#039;&amp;lt;div class=&amp;quot;brick&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&#039;, ()=&amp;gt;{... on brick ...}, null, null, &#039;gray&#039;); &lt;br /&gt;
dojo.addClass(&#039;button_brick&#039;,&#039;bgaimagebutton&#039;);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
where&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
.bgaimagebutton {&lt;br /&gt;
  padding: 0px 12px;&lt;br /&gt;
  min-height: 28px;&lt;br /&gt;
  border: none;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If you use this a lot, you can define a helper function, i.e.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
 * This method can be used instead of addActionButton, to add a button which is an image (i.e. resource). Can be useful when player&lt;br /&gt;
 * need to make a choice of resources or tokens.&lt;br /&gt;
 */&lt;br /&gt;
addImageActionButton: function(id, div, handler, bcolor, tooltip) {&lt;br /&gt;
	if (typeof bcolor == &amp;quot;undefined&amp;quot;) {&lt;br /&gt;
		bcolor = &amp;quot;gray&amp;quot;;&lt;br /&gt;
	}&lt;br /&gt;
	// this will actually make a transparent button id color = gray&lt;br /&gt;
	this.addActionButton(id, div, handler, null, false, bcolor);&lt;br /&gt;
	// remove border, for images it better without&lt;br /&gt;
	dojo.style(id, &amp;quot;border&amp;quot;, &amp;quot;none&amp;quot;);&lt;br /&gt;
	// but add shadow style (box-shadow, see css)&lt;br /&gt;
	dojo.addClass(id, &amp;quot;shadow bgaimagebutton&amp;quot;);&lt;br /&gt;
	// you can also add additional styles, such as background&lt;br /&gt;
	if (tooltip) {&lt;br /&gt;
		dojo.attr(id, &amp;quot;title&amp;quot;, tooltip);&lt;br /&gt;
	}&lt;br /&gt;
	return $(id);&lt;br /&gt;
},&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Disabling Button ===&lt;br /&gt;
&lt;br /&gt;
You can disable the &#039;&#039;&#039;bgabutton&#039;&#039;&#039; by adding the css class &#039;&#039;&#039;disabled&#039;&#039;&#039; in you js. The disabled button is still visible but is grey and not clickable.&lt;br /&gt;
For example in the &#039;&#039;&#039;onUpdateActionButtons&#039;&#039;&#039; : &lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
this.addActionButton(&#039;play_button_id&#039;, _(&#039;Play 1 to 3 cards&#039;), &#039;playFunctionButton&#039;); &lt;br /&gt;
if (condition) {&lt;br /&gt;
  dojo.addClass(&#039;play_button_id&#039;, &#039;disabled&#039;);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Custom Buttons ===&lt;br /&gt;
&lt;br /&gt;
You can create a custom button, but the BGA framework provides a standard button that requires only .css classes: &#039;&#039;&#039;bgabutton&#039;&#039;&#039; and &#039;&#039;&#039;bgabutton_${color}&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Examples:&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;a href=&amp;quot;#&amp;quot; id=&amp;quot;my_button_id&amp;quot; class=&amp;quot;bgabutton bgabutton_blue&amp;quot;&amp;gt;&amp;lt;span&amp;gt;My blue button&amp;lt;/span&amp;gt;&amp;lt;/a&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;a href=&amp;quot;#&amp;quot; id=&amp;quot;my_button_id&amp;quot; class=&amp;quot;bgabutton bgabutton_red bgabutton_big&amp;quot;&amp;gt;&amp;lt;span&amp;gt;My big red button&amp;lt;/span&amp;gt;&amp;lt;/a&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note&#039;&#039;&#039;: To see it in action, check out &#039;&#039;Coloretto&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
=== Button outside of action bar ===&lt;br /&gt;
&lt;br /&gt;
Use addActionButton() method with destination argument set&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
this.addActionButton( &#039;commit_button&#039;, _(&#039;Confirm&#039;), &#039;onConfirm&#039;, &#039;player_board&#039;, true, &#039;red&#039;); &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
in example above the button will be place on object with id &#039;player_board&#039;&lt;br /&gt;
&lt;br /&gt;
== Image loading ==&lt;br /&gt;
&lt;br /&gt;
See also [[Game_art:_img_directory]].&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Be careful&#039;&#039;&#039;: by default, ALL images of your img directory are loaded on a player&#039;s browser when he loads the game. For this reason, don&#039;t let in your img directory images that are not useful, otherwise it&#039;s going to slowdown the game load.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.dontPreloadImage(image_file_name: string)&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Using dontPreloadImage, you tell the interface to not preload a specific image in your img directory.&lt;br /&gt;
&lt;br /&gt;
Example of use:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
this.dontPreloadImage( &#039;cards.png&#039; );&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This is particularly useful if for example you have 2 different themes for a game. To accelerate the loading of the game, you can specify to not preload images corresponding to the other theme.&lt;br /&gt;
&lt;br /&gt;
Another example of use: in &amp;quot;Gosu&amp;quot; game with Kamakor extension, you play with 5 sets of cards among 10 available. Cards images are organized by sets, and we only preload the images corresponding to the 5 current sets with &#039;&#039;&#039;ensureSpecificGameImageLoading( image_file_names_array )&#039;&#039;&#039;.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
// By default, do not preload anything&lt;br /&gt;
this.dontPreloadImage( &#039;cards.png&#039; );&lt;br /&gt;
this.dontPreloadImage( &#039;clan1.png&#039; );&lt;br /&gt;
this.dontPreloadImage( &#039;clan2.png&#039; );&lt;br /&gt;
this.dontPreloadImage( &#039;clan3.png&#039; );&lt;br /&gt;
this.dontPreloadImage( &#039;clan4.png&#039; );&lt;br /&gt;
this.dontPreloadImage( &#039;clan5.png&#039; );&lt;br /&gt;
this.dontPreloadImage( &#039;clan6.png&#039; );&lt;br /&gt;
this.dontPreloadImage( &#039;clan7.png&#039; );&lt;br /&gt;
this.dontPreloadImage( &#039;clan8.png&#039; );&lt;br /&gt;
this.dontPreloadImage( &#039;clan9.png&#039; );&lt;br /&gt;
this.dontPreloadImage( &#039;clan10.png&#039; );&lt;br /&gt;
var to_preload = [];&lt;br /&gt;
for( i in this.gamedatas.clans )&lt;br /&gt;
{&lt;br /&gt;
	var clan_id = this.gamedatas.clans[i];&lt;br /&gt;
	to_preload.push( &#039;clan&#039;+clan_id+&#039;.png&#039; );&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
this.ensureSpecificGameImageLoading( to_preload );&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note:&#039;&#039;&#039; You don&#039;t need to specify to not preload game box images (game_box.png, game_box75.png...) since they are not preloaded by default.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.ensureSpecificGameImageLoading(list: string[])&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
This is oppostive of dontPreloadImage - its ensure specific images is loaded. Note: only makes sense if preload list is empty, otherwise everything is loaded anyway&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;load specific images&#039;&#039;&#039;&lt;br /&gt;
All images that will be preloaded stored in g_img_preload. If you want to override it directly - there is no API, but you can do this in GAME constructor&lt;br /&gt;
&lt;br /&gt;
          g_img_preload = [&#039;tokens.png&#039;, &#039;trains.png&#039;, &#039;loc_plan.png&#039;, &#039;eng.png&#039;, &#039;eng-back.png&#039;];&lt;br /&gt;
&lt;br /&gt;
You can also set it to empty array and call ensureSpecificGameImageLoading() on specific images&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Sounds ==&lt;br /&gt;
&lt;br /&gt;
Add a custom sound and make it load with your interface:&lt;br /&gt;
&lt;br /&gt;
Add this in your template (.tpl) file:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;audio id=&amp;quot;audiosrc_&amp;lt;gamename&amp;gt;_&amp;lt;yoursoundname&amp;gt;&amp;quot; src=&amp;quot;{GAMETHEMEURL}img/&amp;lt;gamename&amp;gt;_&amp;lt;yoursoundname&amp;gt;.mp3&amp;quot; preload=&amp;quot;none&amp;quot; autobuffer&amp;gt;&amp;lt;/audio&amp;gt;&lt;br /&gt;
&amp;lt;audio id=&amp;quot;audiosrc_o_&amp;lt;gamename&amp;gt;_&amp;lt;yoursoundname&amp;gt;&amp;quot; src=&amp;quot;{GAMETHEMEURL}img/&amp;lt;gamename&amp;gt;_&amp;lt;yoursoundname&amp;gt;.ogg&amp;quot; preload=&amp;quot;none&amp;quot; autobuffer&amp;gt;&amp;lt;/audio&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note: this is a requirement to provide both a mp3 and a ogg file with the names &amp;lt;code&amp;gt;&amp;lt;gamename&amp;gt;_&amp;lt;yoursoundname&amp;gt;[.ogg][.mp3]&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Play the sound (from your .js file):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
playSound(&#039;&amp;lt;gamename&amp;gt;_&amp;lt;yoursoundname&amp;gt;&#039;);   // do not add &#039;this.&#039; - its a global function&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Disable the standard &amp;quot;move&amp;quot; sound for this move (to replace it with your custom sound):&lt;br /&gt;
&lt;br /&gt;
Add this to your notification handler:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
this.disableNextMoveSound();&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note: it only disable the sound for the next move.&lt;br /&gt;
&lt;br /&gt;
== Title bar and states ==&lt;br /&gt;
&lt;br /&gt;
=== Client states ===&lt;br /&gt;
&lt;br /&gt;
Client states is a way to simulate the state transition but without actually going&lt;br /&gt;
to server. It is usefull when you need to ask user multiple questions before you&lt;br /&gt;
send things to server&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.setClientState(newState: string, args: object)&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
     this.setClientState(&amp;quot;client_playerPicksLocation&amp;quot;, {&lt;br /&gt;
                               descriptionmyturn : _(&amp;quot;${you} must select location&amp;quot;),&lt;br /&gt;
                           });&lt;br /&gt;
&lt;br /&gt;
For more information see [[BGA_Studio_Cookbook#Multi_Step_Interactions:_Select_Worker.2FPlace_Worker_-_Using_Client_States]]&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.restoreServerGameState()&#039;&#039;&#039;&lt;br /&gt;
If you are in client state it will restore the current server state (cheap undo)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.on_client_state&#039;&#039;&#039;&lt;br /&gt;
Boolean indicating that we are in client state&lt;br /&gt;
&lt;br /&gt;
=== Title bar ===&lt;br /&gt;
If you simply want to show something in title bar you can do it directly &lt;br /&gt;
     $(&#039;pagemaintitletext&#039;).innerHTML = text;&lt;br /&gt;
&lt;br /&gt;
This however will not work with parameters and will not draw You in color,&lt;br /&gt;
if you want to do proper args rendering use method below&lt;br /&gt;
&lt;br /&gt;
;&#039;&#039;&#039;this.removeActionButtons()&#039;&#039;&#039;&lt;br /&gt;
Removes all buttons from title bar&lt;br /&gt;
&lt;br /&gt;
;&#039;&#039;&#039;this.updatePageTitle()&#039;&#039;&#039;&lt;br /&gt;
:This function allows to update the current page title and turn description according to the game state arguments. If the current game state description this.gamedatas.gamestate.descriptionmyturn is modified before calling this function it allows to update the turn description without changing state. This will handle arguments substitutions properly.&lt;br /&gt;
&lt;br /&gt;
Note: this functional also will calls this.onUpdateActionButtons, if you want different buttons then state defaults, use method in example to replace them, if it becomes too clumsy use client states (see above)&lt;br /&gt;
&lt;br /&gt;
Example from Terra Mystica:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
onClickFavorTile: function( evt ) {&lt;br /&gt;
    ...&lt;br /&gt;
    if ( ... ) {&lt;br /&gt;
        this.gamedatas.gamestate.descriptionmyturn = _(&#039;Special action: &#039;) + _(&#039;Advance 1 space	on a Cult track&#039;);&lt;br /&gt;
        this.updatePageTitle();&lt;br /&gt;
        this.removeActionButtons();&lt;br /&gt;
        this.addActionButton( ... );&lt;br /&gt;
         ...&lt;br /&gt;
        return;&lt;br /&gt;
    }&lt;br /&gt;
    ...&lt;br /&gt;
&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== User preferences ==&lt;br /&gt;
&#039;&#039;&#039;this.getGameUserPreference(pref_id)&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Return the value of a user preference. It will return the value currently selected in the select combo box, in the top-right menu.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.setGameUserPreference(pref_id, value)&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Programmatically change a user preference. It will have the same effect as if the player changed the value in the select combo box, in the top-right menu.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.onGameUserPreferenceChanged&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
A callback you can define if you want to be notified when a user changes a user preference.&lt;br /&gt;
&lt;br /&gt;
Example:&amp;lt;pre&amp;gt;&lt;br /&gt;
onGameUserPreferenceChanged: function(pref_id, pref_value) {&lt;br /&gt;
  switch (pref_id) {&lt;br /&gt;
    case 201: &lt;br /&gt;
      document.getElementsByTagName(&#039;html&#039;)[0].classList.toggle(&#039;dark-background&#039;, pref_value == 2);&lt;br /&gt;
      break;&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Other useful stuff ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;dojo.hitch&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
With dojo.hitch, you can create a callback function that will run with your game object context whatever happen.&lt;br /&gt;
&lt;br /&gt;
Typical example: display a BGA confirmation dialog with a callback function created with dojo.hitch:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        this.confirmationDialog( _(&#039;Are you sure you want to make this?&#039;), dojo.hitch( this, function() {&lt;br /&gt;
            this.bgaPerformAction(&#039;makeThis&#039;);&lt;br /&gt;
        } ) );   &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In the example above, using dojo.hitch, we ensure that the &amp;quot;this&amp;quot; object will be set when the callback is called.&lt;br /&gt;
&lt;br /&gt;
NOTE: In modern JS there are lambdas that eliminate need for that, the example above will look like this&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        this.confirmationDialog( _(&#039;Are you sure you want to make this?&#039;), () =&amp;gt; this.bgaPerformAction( &#039;makeThis&#039;) );   &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
;&#039;&#039;&#039;onScreenWidthChange()&#039;&#039;&#039;&lt;br /&gt;
:This function can be overridden in your game to manage some resizing on the client side when the browser window is resized. This function is also triggered at load time, so it can be used to adapt to the :viewport size at the start of the game too.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
; this.bRealtime&lt;br /&gt;
: Return true if the game is in realtime. Note that having a distinct behavior in realtime and turn-based should be exceptional.&lt;br /&gt;
&lt;br /&gt;
; g_replayFrom&lt;br /&gt;
: Global contains replay number in live game, it is set to undefined (i.e. not set) when it is not a replay mode, so consequentially the good check is &#039;&#039;&#039;typeof g_replayFrom != &#039;undefined&#039;&#039;&#039;&#039; which returns true if the game is in replay mode &amp;lt;i&amp;gt;during the game&amp;lt;/i&amp;gt; (the game is ongoing but the user clicked &amp;quot;replay from this move&amp;quot; in the log)&lt;br /&gt;
&lt;br /&gt;
; g_archive_mode&lt;br /&gt;
: Returns true if the game is in archive mode &amp;lt;i&amp;gt;after the game&amp;lt;/i&amp;gt; (the game has ended)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
; this.instantaneousMode&lt;br /&gt;
: Returns true during replay/archive mode if animations should be skipped. Only needed if you are doing custom animations. (The BGA-provided animation functions like &amp;lt;i&amp;gt;this.slideToObject()&amp;lt;/i&amp;gt; automatically handle instantaneous mode.)&lt;br /&gt;
: Technically, when you click &amp;quot;replay from move #20&amp;quot;, the system replays the game from the very beginning with moves 0 - 19 happening in instantaneous mode and moves 20+ happening in normal mode.&lt;br /&gt;
&lt;br /&gt;
; g_tutorialwritten&lt;br /&gt;
: Returns an object like the below if the game is in tutorial mode, or undefined otherwise. Tutorial mode is a special case of archive mode where comments have been added to a previous game to teach new players the rules.&lt;br /&gt;
    {&lt;br /&gt;
        author: &amp;quot;91577332&amp;quot;,&lt;br /&gt;
        id: &amp;quot;576&amp;quot;,&lt;br /&gt;
        mode: &amp;quot;view&amp;quot;&lt;br /&gt;
        status: &amp;quot;alpha&amp;quot;&lt;br /&gt;
        version_override: null&lt;br /&gt;
        viewer_id: &amp;quot;84554161&amp;quot;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;getBgaEnvironment(): string&#039;&#039;&#039;&lt;br /&gt;
: Returns &amp;quot;studio&amp;quot; for studio and &amp;quot;prod&amp;quot; for production environment (i.e. where games current runs). Only useful for debbugging hooks.&lt;br /&gt;
Note: alpha server is also &amp;quot;prod&amp;quot;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Category:Studio]]&lt;/div&gt;</summary>
		<author><name>Sguzzer Gunayer</name></author>
	</entry>
	<entry>
		<id>https://en.doc.boardgamearena.com/index.php?title=Game_interface_logic:_Game.js&amp;diff=22735</id>
		<title>Game interface logic: Game.js</title>
		<link rel="alternate" type="text/html" href="https://en.doc.boardgamearena.com/index.php?title=Game_interface_logic:_Game.js&amp;diff=22735"/>
		<updated>2024-09-25T17:54:43Z</updated>

		<summary type="html">&lt;p&gt;Sguzzer Gunayer: /* Connecting */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Studio_Framework_Navigation}}&lt;br /&gt;
&lt;br /&gt;
__TOC__&lt;br /&gt;
&lt;br /&gt;
This is the main file for your game interface. Here you will define:&lt;br /&gt;
&lt;br /&gt;
* Which actions on the page will generate calls to the server.&lt;br /&gt;
* What happens when you get a notification for a change from the server and how it will show in the browser. &lt;br /&gt;
* Setup user interface&lt;br /&gt;
&lt;br /&gt;
== File structure ==&lt;br /&gt;
&lt;br /&gt;
The details of how the file is structured are described below with comments in the code skeleton provided to you.&lt;br /&gt;
&lt;br /&gt;
Here is the basic structure:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;constructor&#039;&#039;&#039;: here you can define global variables for your whole interface.&lt;br /&gt;
* &#039;&#039;&#039;setup&#039;&#039;&#039;: this method is called when the page is refreshed, and sets up the game interface.&lt;br /&gt;
* &#039;&#039;&#039;onEnteringState&#039;&#039;&#039;: this method is called when entering a new game state. You can use it to customize the view for each game state.&lt;br /&gt;
* &#039;&#039;&#039;onLeavingState&#039;&#039;&#039;: this method is called when leaving a game state.&lt;br /&gt;
* &#039;&#039;&#039;onUpdateActionButtons&#039;&#039;&#039;: called on state changes, in order to add action buttons to the status bar. Note: in a multipleactiveplayer state, it will be called when another player has become inactive.&lt;br /&gt;
* &#039;&#039;(utility methods)&#039;&#039;: this is where you can define your utility methods.&lt;br /&gt;
* &#039;&#039;(player&#039;s actions)&#039;&#039;: this is where you can write your handlers for player actions on the interface (example: click on an item).&lt;br /&gt;
* &#039;&#039;&#039;setupNotifications&#039;&#039;&#039;: this method associates notifications with notification handlers. For each game notification, you can trigger a javascript method to handle it and update the game interface.&lt;br /&gt;
* &#039;&#039;(notification handlers)&#039;&#039;: this is where you define the notifications handlers associated with notifications in &#039;&#039;&#039;setupNotifications&#039;&#039;&#039;, above.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
More details:&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;setup(gamedatas: object)            &#039;&#039;&#039;&lt;br /&gt;
This method must set up the game user interface according to current game situation specified in parameters.&lt;br /&gt;
The method is called each time the game interface is displayed to a player, ie:&lt;br /&gt;
&lt;br /&gt;
* when the game starts&lt;br /&gt;
* when a player opens a game in the browser later &lt;br /&gt;
* when a player refreshes the game page (F5)&lt;br /&gt;
* when player does a server side Undo&lt;br /&gt;
&lt;br /&gt;
&amp;quot;gamedatas&amp;quot; argument contains all data retrieved by your &amp;quot;getAllDatas&amp;quot; PHP method and some more.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;onEnteringState(stateName: string, args: { args: any } | null): void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
This method is called each time we enter a new game state.&lt;br /&gt;
You can use this method to perform some user interface changes at this moment.&lt;br /&gt;
To access state arguments passed via calling php arg* method use args?.args.&lt;br /&gt;
Typically you would do something only for active player, using this.isCurrentPlayerActive() check.&lt;br /&gt;
It is also called (for the current game state only) when doing a browser refresh (after the setup method is called).&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Warning&#039;&#039;&#039;: for multipleactiveplayer states:&lt;br /&gt;
the active players are NOT active yet so you must use onUpdateActionButtons to perform the client side operation which depends on a player active/inactive status.&lt;br /&gt;
If you are doing initialization of some structures which do not depend on the active player, you can just replace (this.isCurrentPlayerActive()) with (!this.isSpectator) &lt;br /&gt;
for the main switch in that method.&lt;br /&gt;
&lt;br /&gt;
See more details in [[Your_game_state_machine:_states.inc.php#Difference_between_Single_active_and_Multi_active_states]]&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;onLeavingState(stateName: string): void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
This method is called each time we leave a game state.&lt;br /&gt;
You can use this method to perform some user interface changes at this point (i.e. cleanup).&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;onUpdateActionButtons(stateName: string, args: object | null): void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
In this method you can manage &amp;quot;action buttons&amp;quot; that are displayed in the action status bar and highlight active UI elements.&lt;br /&gt;
To access state arguments passed via calling php arg* method use &#039;&#039;&#039;args&#039;&#039;&#039; parameter. Note: args can be null! For &#039;&#039;&#039;game&#039;&#039;&#039; states and when you don&#039;t supply state args function - it is null.&lt;br /&gt;
This method is called when the active or multiactive player changes. In a classic &amp;quot;activePlayer&amp;quot; state this method is called before the onEnteringState state.&lt;br /&gt;
In multipleactiveplayer state it is a mess. The sequencing of calls depends on whether you get into that state from transitions OR from reloading the whole game (i.e. F5).&lt;br /&gt;
&lt;br /&gt;
See more details in [[Your_game_state_machine:_states.inc.php#Difference_between_Single_active_and_Multi_active_states]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Dojo framework ==&lt;br /&gt;
&lt;br /&gt;
BGA uses the [http://dojotoolkit.org/ Dojo Javascript framework].&lt;br /&gt;
&lt;br /&gt;
The Dojo framework allows us to do complex things more easily. The BGA framework uses Dojo extensively.&lt;br /&gt;
&lt;br /&gt;
To implement a game, you only need to use a few parts of the Dojo framework. All the Dojo methods you need are described on this page.&lt;br /&gt;
&lt;br /&gt;
== Javascript minimization (after July 2020) ==&lt;br /&gt;
&lt;br /&gt;
For performance reasons, when deploying a game the javascript code is minimized using &#039;&#039;&#039;terser&#039;&#039;&#039; (https://github.com/terser/terser). This minifier works with modern javascript syntax. From your project &amp;quot;Manage game&amp;quot; page, you can now test a minified version of your javascript on the studio (and revert to the original).&lt;br /&gt;
&lt;br /&gt;
NB: it has been reported that there is an issue with this minifier and percentage values for opacity.&lt;br /&gt;
&lt;br /&gt;
== Accessing Players Information ==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.player_id: number&#039;&#039;&#039;&lt;br /&gt;
id of the player who is looking at the game. The player may not be part of the game (i.e. spectator)&lt;br /&gt;
  if (notif.args.player_id == this.player_id) {&lt;br /&gt;
    ...&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.isSpectator: boolean&#039;&#039;&#039;&lt;br /&gt;
Flag set to true if the user at the table is a spectator (not a player).&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    if (this.isSpectator) {&lt;br /&gt;
        this.player_color = &#039;ffffff&#039;;&lt;br /&gt;
    } else {&lt;br /&gt;
        this.player_color = gamedatas.players[this.player_id].color;&lt;br /&gt;
    }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note: If you want to hide an element from spectators, you should use [[Game_interface_stylesheet:_yourgamename.css#spectatorMode|CSS &#039;spectatorMode&#039; class]].&lt;br /&gt;
&lt;br /&gt;
You may consider making a function like this, to detect if the game is in a read-only state (i.e. non-interactive):&lt;br /&gt;
  // Returns true for spectators, instant replay (during game), archive mode (after game end)&lt;br /&gt;
  isReadOnly: function () {&lt;br /&gt;
    return this.isSpectator || typeof g_replayFrom != &#039;undefined&#039; || g_archive_mode;&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.gamedatas: object&#039;&#039;&#039;&lt;br /&gt;
Contains the initial set of data to init the game, created at game start or by game refresh (F5).&lt;br /&gt;
You can update it as needed to keep an up-to-date reference of the game on the client side if you need it, however most of the time this is unnecessary.&lt;br /&gt;
&lt;br /&gt;
Note: In hotseat mode, the framework does not keep this.gamedatas of hotseat players and shares the same set as the main player to store data.&lt;br /&gt;
&lt;br /&gt;
Note: be careful when you update this data structurally, many framework functions expect data to be certain way and they will break if they see something else.&lt;br /&gt;
&lt;br /&gt;
Typical example of accessing player&#039;s info&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
for (var player_id in this.gamedatas.players) { &lt;br /&gt;
    var playerInfo = this.gamedatas.players [player_id];&lt;br /&gt;
    var c = playerInfo.color;&lt;br /&gt;
    var name = playerInfo.name;&lt;br /&gt;
    // do something &lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.isCurrentPlayerActive(): boolean&#039;&#039;&#039;&lt;br /&gt;
Returns true if the player on whose browser the code is running is currently active (it&#039;s his turn to play). Note: see remarks above about usage of this function inside onEnteringState method.&lt;br /&gt;
  if (this.isCurrentPlayerActive()) ...&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.getActivePlayerId(): number&#039;&#039;&#039;&lt;br /&gt;
Return the ID of the active player, or null if we are not in an &amp;quot;activeplayer&amp;quot; type state.&lt;br /&gt;
  if (this.player_id == this.getActivePlayerId()) ...&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.getActivePlayers(): number[]&#039;&#039;&#039;&lt;br /&gt;
Return an array with the IDs of players who are currently active (or an empty array if there are none).&lt;br /&gt;
&lt;br /&gt;
== Accessing and manipulating the DOM ==&lt;br /&gt;
&lt;br /&gt;
=== Element by Id ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;$(elementId: ElementOrId)&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
The $ function is used to get an HTML element using its &amp;quot;id&amp;quot; attribute.&lt;br /&gt;
&lt;br /&gt;
Example: modify the content of a &amp;quot;span&amp;quot; element:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
In your HTML code:&lt;br /&gt;
   &amp;lt;span id=&amp;quot;a_value_in_the_game_interface&amp;quot;&amp;gt;1234&amp;lt;/span&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In your Javascript code:&lt;br /&gt;
   $(&#039;a_value_in_the_game_interface&#039;).innerHTML = &amp;quot;9999&amp;quot;;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Note: It is safe to use if you don&#039;t know if variable is string (id of element) or element itself, i.e. &lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  foo: function(card) {&lt;br /&gt;
       card = $(card); // now its node, no need to write if (typeof card === &#039;string&#039;) ...&lt;br /&gt;
       // but its good idea to check for null here&lt;br /&gt;
       ...&lt;br /&gt;
  }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;getElementById(elementId: string)&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Note: $() is the standard method to access some HTML element with the BGA Framework. You can use &#039;&#039;&#039;getElementById&#039;&#039;&#039; but it is longer to type and less handy as it does not do some checks.&lt;br /&gt;
&lt;br /&gt;
=== Style ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;dojo.style(node: ElementOrId, styleName: string, styleValue: any): void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
With dojo.style you can modify the CSS property of any HTML element in your interface.&lt;br /&gt;
&lt;br /&gt;
Examples:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
     // Make an element disappear&lt;br /&gt;
     dojo.style( &#039;my_element&#039;, &#039;display&#039;, &#039;none&#039; );&lt;br /&gt;
&lt;br /&gt;
     // Give an element a 2px border&lt;br /&gt;
     dojo.style( &#039;my_element&#039;, &#039;borderWidth&#039;, &#039;2px&#039; );&lt;br /&gt;
&lt;br /&gt;
     // Change the background position of an element&lt;br /&gt;
     // (very practical when you are using CSS sprites to transform an element to another)&lt;br /&gt;
     dojo.style( &#039;my_element&#039;, &#039;backgroundPosition&#039;, &#039;-20px -50px&#039; );&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note: if you have to modify several CSS properties of an element, or if you have a complex CSS transformation to do, you should consider using dojo.addClass/dojo.removeClass (see below).&lt;br /&gt;
&lt;br /&gt;
You can also use object to set multiple values&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
dojo.setStyle(&amp;quot;thinger&amp;quot;, {&lt;br /&gt;
  &amp;quot;opacity&amp;quot;: 0.5,&lt;br /&gt;
  &amp;quot;border&amp;quot;: &amp;quot;3px solid black&amp;quot;,&lt;br /&gt;
  &amp;quot;height&amp;quot;: &amp;quot;300px&amp;quot;&lt;br /&gt;
});&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.addStyleToClass(cssClassName: string, styleName: string, styleValue: any):&#039;&#039;&#039; &#039;&#039;&#039;void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Same as dojo.style(), but for all the nodes set with the specified cssClassName&lt;br /&gt;
Equivalent of &lt;br /&gt;
  &lt;br /&gt;
  dojo.query(`.${aclass}`).style(styleName, styleValue)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
dojo.query(&amp;quot;#baz &amp;gt; div&amp;quot;).style({&lt;br /&gt;
  opacity:0.75,&lt;br /&gt;
  fontSize:&amp;quot;13pt&amp;quot;&lt;br /&gt;
});&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Vanilla JS style&#039;&#039;&#039;&lt;br /&gt;
  $(&#039;my_element&#039;).style.display=&#039;none&#039;; // set&lt;br /&gt;
  var display = $(&#039;my_element&#039;).style.display; // get&lt;br /&gt;
  $(&#039;my_element&#039;).style.removeProperty(&#039;display&#039;); // remove&lt;br /&gt;
&lt;br /&gt;
=== Classes ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;dojo.addClass(node: ElementOrId, classes: string): void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;dojo.removeClass(node: ElementOrId, classes: string): void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;dojo.hasClass(node: ElementOrId, aclass: string): void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;dojo.toggleClass(node: ElementOrId, aclass: string): void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
In many situations, many small CSS property updates can be replaced by a CSS class change (i.e., you add a CSS class to your element instead of applying all modifications manually).&lt;br /&gt;
&lt;br /&gt;
Advantages are:&lt;br /&gt;
* All your CSS stuff remains in your CSS file.&lt;br /&gt;
* You can add/remove a list of CSS modifications with a simple function and without error.&lt;br /&gt;
* You can test whether you applied the CSS to an element with the &#039;&#039;&#039;dojo.hasClass&#039;&#039;&#039; method.&lt;br /&gt;
&lt;br /&gt;
Example from &#039;&#039;Reversi&#039;&#039;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    // We add &amp;quot;possibleMove&amp;quot; to an element&lt;br /&gt;
    dojo.addClass( &#039;square_&#039;+x+&#039;_&#039;+y, &#039;possibleMove&#039; );&lt;br /&gt;
&lt;br /&gt;
    // In our CSS file, the class is defined as:&lt;br /&gt;
    .possibleMove {&lt;br /&gt;
      background-color: white;&lt;br /&gt;
      opacity: 0.2;&lt;br /&gt;
      filter:alpha(opacity=20); /* For IE8 and earlier */  &lt;br /&gt;
      cursor: pointer;  &lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
     // So we&#039;ve applied 4 CSS property changes in one line of code.&lt;br /&gt;
&lt;br /&gt;
     // ... and when we need to check if a square is a possible move on the client side:&lt;br /&gt;
     if( dojo.hasClass( &#039;square_&#039;+x+&#039;_&#039;+y, &#039;possibleMove&#039; ) )&lt;br /&gt;
     { ... }&lt;br /&gt;
&lt;br /&gt;
     // ... and if we want to remove all possible moves in one line of code (see &amp;quot;dojo.query&amp;quot; method):&lt;br /&gt;
     dojo.query( &#039;.possibleMove&#039; ).removeClass( &#039;possibleMove&#039; );&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Vanilla JS classList&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
This is the only exception where dojo versions are better&lt;br /&gt;
  // add class&lt;br /&gt;
  $(token_id).classList.addClass(&#039;possibleMove&#039;);&lt;br /&gt;
  // remove class&lt;br /&gt;
  $(token_id).classList.removeClass(&#039;possibleMove&#039;);&lt;br /&gt;
  // add 2 classes&lt;br /&gt;
  const myclasses = [&#039;a&#039;,&#039;b&#039;];&lt;br /&gt;
  $(token_id).classList.addClass(...myclasses);&lt;br /&gt;
  // add classes to query result&lt;br /&gt;
  document.querySelectorAll(&amp;quot;.hand .card&amp;quot;).forEach((node)=&amp;gt;node.classList.addClass(&#039;possibleMove&#039;));&lt;br /&gt;
&lt;br /&gt;
=== Attributes ===&lt;br /&gt;
&lt;br /&gt;
;dojo.attr&lt;br /&gt;
&lt;br /&gt;
With dojo.attr you can access or change the value of an attribute or property of any HTML element in your interface.&lt;br /&gt;
&lt;br /&gt;
Exemple:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
     // Get the title of a node&lt;br /&gt;
     var title = dojo.attr( id, &#039;title&#039; );&lt;br /&gt;
     // Change the height of a node&lt;br /&gt;
     dojo.attr( &#039;img_growing_tree&#039;, &#039;height&#039;, 100 );&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Vanilla JS attr&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
   $(token).id=new_id; // set attr for &amp;quot;id&amp;quot;&lt;br /&gt;
   var id = $(token).id; // get&lt;br /&gt;
&lt;br /&gt;
=== Queries ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;dojo.query(cssSelector: string): Element[]&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
With dojo.query, you can query a bunch of HTML elements with a single function, with a &amp;quot;CSS selector&amp;quot; style.&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
     // All elements with class &amp;quot;possibleMove&amp;quot;:&lt;br /&gt;
     var elements = dojo.query( &#039;.possibleMove&#039; );&lt;br /&gt;
&lt;br /&gt;
     // Count number of tokens (i.e., elements of class &amp;quot;token&amp;quot;) on the board (i.e., the element with id &amp;quot;board&amp;quot;):&lt;br /&gt;
     dojo.query( &#039;#board .token&#039; ).length;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
But what is really cool with dojo.query is that you can combine it with almost all methods above.&lt;br /&gt;
&lt;br /&gt;
Examples:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
     // Trigger a method when the mouse enter in any element with class &amp;quot;meeple&amp;quot;:&lt;br /&gt;
     dojo.query( &#039;.meeple&#039; ).connect( &#039;onmouseenter&#039;, this, &#039;myMethodToTrigger&#039; );&lt;br /&gt;
&lt;br /&gt;
     // Hide all meeples who are on the board&lt;br /&gt;
     dojo.query( &#039;#board .meeple&#039; ).style( &#039;display&#039;, &#039;none&#039; );&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Vanilla JS query&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
  var cards=document.querySelectorAll(&amp;quot;.hand .card&amp;quot;);// all cards in all hands&lt;br /&gt;
  var cards=$(&#039;hand&#039;).querySelectorAll(&amp;quot;.card&amp;quot;);// all cards in specific hand&lt;br /&gt;
  var card=document.querySelector(&amp;quot;.hand .card&amp;quot;);// first card or null if none (super handy)&lt;br /&gt;
&lt;br /&gt;
=== Creating and Destroying elements ===&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;dojo.empty(node: ElementOrId)&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Remove all children of the node element&lt;br /&gt;
   dojo.empty(&#039;my_hand&#039;);&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;dojo.destroy(node: ElementOrId)&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Remove the element&lt;br /&gt;
   dojo.destroy(&#039;my_token&#039;);&lt;br /&gt;
&lt;br /&gt;
   dojo.query(&amp;quot;.green&amp;quot;, mynode).forEach(dojo.destroy); // this remove all subnode of class green from mynode&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;dojo.create(tag: string, attributes?: obj, parent?: ElementOrId): Element&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Create element&lt;br /&gt;
&lt;br /&gt;
    dojo.create(&amp;quot;div&amp;quot;, { class: &amp;quot;yellow_arrow&amp;quot; }, parent); // this creates div with class yellow_array and places it in &amp;quot;parent&amp;quot;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.format_block(name: string, args: object): string&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
This bga function that takes global var from template file and substitute variables, typical use would be&lt;br /&gt;
&lt;br /&gt;
                var player = gamedatas.players[player_id];&lt;br /&gt;
                var div = this.format_block(&#039;jstpl_player_board&#039;, player ); // var jstpl_player_board = ... is defined in .tpl file &lt;br /&gt;
Note: result is trimmed&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.format_string(name: string, args: object): string&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
This bga function just substitute variables in a string, i.e.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
     var div = this.format_string(&#039;&amp;lt;div color=&amp;quot;${player_color}&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&#039;, {player_color: &#039;#ff0000&#039;} );&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Note: result is trimmed&lt;br /&gt;
&lt;br /&gt;
Note: this can be replaced by using backquoted string now: &lt;br /&gt;
     const player_color =  &#039;#ff0000&#039;;&lt;br /&gt;
&lt;br /&gt;
    const div = ``;&lt;br /&gt;
&#039;&#039;&#039;this.format_string_recursive&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
This bga function is similar to this.format_string but is capable of processing recursive argument structures and translations. It is used to format server notifications.&lt;br /&gt;
&lt;br /&gt;
TODO: find better place for these function docs&lt;br /&gt;
&lt;br /&gt;
=== Moving elements ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;dojo.place(node: string | Element, refNode: ElementOrId, pos?: string | number): Element&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
dojo.place is the best function to insert HTML code somewhere in your game interface without breaking something. It is much better to use than the &#039;&#039;&#039;innerHTML=&#039;&#039;&#039; method if you must insert HTML tags and not only values.&lt;br /&gt;
&lt;br /&gt;
node: can be a string or a DOM node. If it is a string starting with “&amp;lt;”, it is assumed to be an HTML fragment, which will be created. Otherwise it is assumed to be an id of a DOM node. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
     // Insert your HTML code as a child of a container element&lt;br /&gt;
     dojo.place( &amp;quot;&amp;lt;div class=&#039;foo&#039;&amp;gt;&amp;lt;/div&amp;gt;&amp;quot;, &amp;quot;your_container_element_id&amp;quot; );&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
pos: optional argument. Can be a number or one of the following strings: “before”, “after”, “replace”, “only”, “first”, or “last”. If omitted, “last” is assumed.&lt;br /&gt;
&lt;br /&gt;
* &amp;quot;replace&amp;quot;: replace the container element with my_node element&lt;br /&gt;
* &amp;quot;first&amp;quot;: places the node as a child of the reference node. The node is placed as the first child.&lt;br /&gt;
* &amp;quot;last&amp;quot; (default): places the node as a child of the reference node. The node is placed as the last child.&lt;br /&gt;
* &amp;quot;before&amp;quot;: places the node right before the reference node.&lt;br /&gt;
* &amp;quot;after&amp;quot;: places the node right after the reference node.&lt;br /&gt;
* &amp;quot;only&amp;quot;: replaces all children of the reference node with the node.&lt;br /&gt;
&lt;br /&gt;
this parameter can be a positive integer. In this case, the node will be placed as a child of the reference node with this number (counting from 0). If the number is more than number of children, the node will be appended to the reference node making it the last child. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
     // Replace all children of container with my_node &lt;br /&gt;
     dojo.place( $(&#039;my_node&#039;), &amp;quot;your_container_element_id&amp;quot;, &amp;quot;only&amp;quot; );&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
See also full doc on dojo.place: [https://dojotoolkit.org/reference-guide/1.7/dojo/place.html]&lt;br /&gt;
&lt;br /&gt;
Usually, when you want to insert some piece of HTML in your game interface, you should use &amp;quot;[[Game_layout:_view_and_template:_yourgamename.view.php_and_yourgamename_yourgamename.tpl#Javascript_templates|Javascript templates]]&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
But you can also relocate elements like that. Note: it won&#039;t animate if you do that.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.placeOnObject(mobile_obj: ElementOrId, target_obj: ElementOrId): void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
places mobile_obj on target_obj, set the absolute positions and centers the mobile_obj on target_obj,&lt;br /&gt;
effect is immediate&lt;br /&gt;
&lt;br /&gt;
This is not really an animation, but placeOnObject is frequently used before starting an animation.&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  // (We just created an object &amp;quot;my_new_token&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
  // Place the new token on current player board&lt;br /&gt;
  this.placeOnObject( &amp;quot;my_new_token&amp;quot;, &amp;quot;overall_player_board_&amp;quot;+this.player_id );&lt;br /&gt;
  &lt;br /&gt;
  // Then slide it to its position on the board&lt;br /&gt;
  this.slideToObject( &amp;quot;my_new_token&amp;quot;, &amp;quot;a_place_on_board&amp;quot; ).play();&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.placeOnObjectPos(mobile_obj: ElementOrId, target_obj: ElementOrId, target_x: number, target_y: number): void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
This method works exactly like placeOnObject, except than you can specify some (x,y) coordinates (in px). This way, the center of &amp;quot;mobile_obj&amp;quot; will be placed to the specified x,y position relatively to the center of &amp;quot;target_obj&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Note: the placement works differently from this.slideToObjectPos&#039;&#039;, since coordinates are calculated based on the center of objects.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.attachToNewParent(mobile_obj: ElementOrId, target_obj: ElementOrId): void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
With this method, you change the HTML parent of &amp;quot;mobile_obj&amp;quot; element without moving it. &lt;br /&gt;
&amp;quot;target_obj&amp;quot; is the new parent of this element. The beauty of &lt;br /&gt;
attachToNewParent is that the mobile_obj element DOES NOT MOVE during this process.&lt;br /&gt;
&lt;br /&gt;
What happens is that the method calculate a relative position of mobile_obj to make sure it does not move after the HTML parent changes.&lt;br /&gt;
&lt;br /&gt;
Why using this method?&lt;br /&gt;
&lt;br /&gt;
Changing the HTML parent of an element can be useful for the following reasons:&lt;br /&gt;
* When the HTML parent moves, all its child are moving with them. If some game elements is no more linked with a parent HTML object, you may want to attach it to another place.&lt;br /&gt;
* The z_order (vertical order of display) depends on the position in the DOM, so you may need to change the parent of some game elements when they are moving in your game area.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;CAREFUL&#039;&#039;&#039;: this function destroys original object and places a clone onto a new parent, this will break all references to this HTML element (ex: dojo.connect).&lt;br /&gt;
If you need version that does not destroy the object but the same otherwise see [[BGA_Studio_Cookbook#Attach_to_new_parent_without_destroying_the_object]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Animations ==&lt;br /&gt;
&lt;br /&gt;
===Dojo Animations===&lt;br /&gt;
&lt;br /&gt;
BGA animations is based on Dojo Animation ([http://dojotoolkit.org/documentation/tutorials/1.8/animation/ see tutorial here]).&lt;br /&gt;
&lt;br /&gt;
However, most of the time, you can just use methods below, which are built on top of Dojo Animation.&lt;br /&gt;
&lt;br /&gt;
Note: one interesting method from Dojo that could be useful from time to time is &amp;quot;Dojo.Animation&amp;quot;. It allows you to make any CSS property &amp;quot;slide&amp;quot; from one value to another.&lt;br /&gt;
&lt;br /&gt;
Note 2: the slideTo methods are not compatible with CSS transform (scale, zoom, rotate...). If possible, avoid using CSS transform on nodes that are being slided. Eventually, the only possible solution to make these 2 compatible is to disable all CSS transform properties, use slideToObjectPos/placeOnObjectPos, and then apply them again.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Sliding===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.slideToObject(mobile_obj: ElementOrId, target_obj: ElementOrId, duration?: number, delay?: number): Animation&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
You can use slideToObject to &amp;quot;slide&amp;quot; an element to a target position.&lt;br /&gt;
&lt;br /&gt;
Sliding element on the game area is the recommended and the most used way to animate your game interface. Using slides allow players to figure out what is happening on the game, as if they were playing with the real boardgame.&lt;br /&gt;
&lt;br /&gt;
The parameters are:&lt;br /&gt;
* mobile_obj: the ID of the object to move. This object must be &amp;quot;relative&amp;quot; or &amp;quot;absolute&amp;quot; positioned.&lt;br /&gt;
* target_obj: the ID of the target object. This object must be &amp;quot;relative&amp;quot; or &amp;quot;absolute&amp;quot; positioned. Note that it is not mandatory that mobile_obj and target_obj have the same size. If their size are different, the system slides the center of mobile_obj to the center of target_obj.&lt;br /&gt;
* duration: (optional) defines the duration in millisecond of the slide. The default is 500 milliseconds.&lt;br /&gt;
* delay: (optional). If you defines a delay, the slide will start only after this delay. This is particularly useful when you want to slide several object from the same position to the same position: you can give a 0ms delay to the first object, a 100ms delay to the second one, a 200ms delay to the third one, ... this way they won&#039;t be superposed during the slide.&lt;br /&gt;
&lt;br /&gt;
BE CAREFUL: The method returns an dojo.fx animation, so you can combine it with other animation if you want to. It means that you have to call the &amp;quot;play()&amp;quot; method, otherwise the animation WON&#039;T START.&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
   this.slideToObject( &amp;quot;some_token&amp;quot;, &amp;quot;some_place_on_board&amp;quot; ).play();&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.slideToObjectPos(mobile_obj: ElementOrId, target_obj: ElementOrId, target_x: number, target_y: number, duration?: number, delay?: number): Animation&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
This method does exactly the same as &amp;quot;slideToObject&amp;quot;, except than you can specify some (x,y) coordinates. This way, &amp;quot;mobile_obj&amp;quot; will slide to the specified x,y position relatively to &amp;quot;target_obj&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
Example: slide a token to some place on the board, 10 pixels from the top:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
   this.slideToObjectPos( &amp;quot;some_token&amp;quot;, &amp;quot;some_place_on_board&amp;quot;, 0, 10 ).play();&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.slideTemporaryObject(mobile_obj_html: string, parent: ElementOrId, from: ElementOrId, to: ElementOrId, duration?: number, delay?: number): Animation&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
This method is useful when you want to slide a temporary HTML object from one place to another. As this object does not exists before the animation and won&#039;t remain after, it could be complex to create this object (with dojo.place), to place it at its origin (with placeOnObject) to slide it (with slideToObject) and to make it disappear at the end.&lt;br /&gt;
&lt;br /&gt;
slideTemporaryObject does all of this for you:&lt;br /&gt;
* mobile_obj_html is a piece of HTML code that represent the object to slide.&lt;br /&gt;
* parent is the ID of an HTML element of your interface that will be the parent of this temporary HTML object.&lt;br /&gt;
* from is the ID of the origin of the slide.&lt;br /&gt;
* to is the ID of the target of the slide.&lt;br /&gt;
* duration/delay works exactly like in &amp;quot;slideToObject&amp;quot;&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
this.slideTemporaryObject( &#039;&amp;lt;div class=&amp;quot;token_icon&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&#039;, &#039;tokens&#039;, &#039;my_origin_div&#039;, &#039;my_target_div&#039; ).play();&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Destroy===&lt;br /&gt;
&#039;&#039;&#039;this.slideToObjectAndDestroy(mobile_obj: ElementOrId, target_obj: ElementOrId, duration?: number, delay?: number): void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
This method is a handy shortcut to slide an existing HTML object to some place then destroy it upon arrival. It can be used for example to move a victory token or a card from the board to the player panel to show that the player earns it, then destroy it when we don&#039;t need to keep it visible on the player panel.&lt;br /&gt;
&lt;br /&gt;
It works the same as this.slideToObject and takes the same arguments, but it starts the animation. &lt;br /&gt;
&lt;br /&gt;
CAREFUL: Make sure nothing is creating the same object at the same time the animation is running, because this will cause some random disappearing effects&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
this.slideToObjectAndDestroy( &amp;quot;some_token&amp;quot;, &amp;quot;some_place_on_board&amp;quot;, 1000, 0 );&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.fadeOutAndDestroy( node: string | Element, duration?: number, delay?: number):&#039;&#039;&#039; &#039;&#039;&#039;void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
This function fade out the target node, then destroy it. Its starts the animation.&lt;br /&gt;
* duration/delay works exactly like in &amp;quot;slideToObject&amp;quot;&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
   this.fadeOutAndDestroy( &amp;quot;a_card_that_must_disappear&amp;quot; );&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
CAREFUL: the HTML node still exists until during few milliseconds, until the fadeOut has been completed.&lt;br /&gt;
Make sure nothing is creating same object at the same time as animation is running, because you will be some random dissapearing effects&lt;br /&gt;
&lt;br /&gt;
===Rotating elements===&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
This example combines &amp;quot;Dojo.Animation&amp;quot; method and a CSS property transform that allow you to rotate the element.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
// node is Element we rotating&lt;br /&gt;
		    var animation = new dojo.Animation({&lt;br /&gt;
			    curve: [fromDegree, toDegree],&lt;br /&gt;
			    onAnimate: (v) =&amp;gt; {&lt;br /&gt;
				    node.style.transform = &#039;rotate(&#039; + v + &#039;deg)&#039;;&lt;br /&gt;
			    } &lt;br /&gt;
		    });&lt;br /&gt;
		    &lt;br /&gt;
		    animation.play();  &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
BGA has its own interface to rotate&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.rotateTo(node: string | Element, degree: number): void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
It starts the animation, and stored the rotation degree in the class, so next time you rotate object - it is additive.&lt;br /&gt;
There is no animation hooks in this one, if you need to change any parameters use dojo animation above.&lt;br /&gt;
&lt;br /&gt;
There is also &#039;&#039;&#039;rotateInstantTo&#039;&#039;&#039; with same signature which does not animate&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Animation Callbacks===&lt;br /&gt;
&lt;br /&gt;
If you wish to run some code only after an animation has completed you can do this by linking a callback method to &#039;onEnd&#039;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
var animation_id = this.slideToObject( mobile_obj, target_obj, 500 );&lt;br /&gt;
dojo.connect(animation_id, &#039;onEnd&#039;, () =&amp;gt; {&lt;br /&gt;
   // do something here&lt;br /&gt;
});&lt;br /&gt;
animation_id.play();&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If you wish to call a second animation after the first (rather than general code) then you can use a dojo animation chain (see tutorial referenced above).&lt;br /&gt;
&lt;br /&gt;
== Players input ==&lt;br /&gt;
&lt;br /&gt;
=== Connecting ===&lt;br /&gt;
&#039;&#039;&#039;dojo.connect(element: Element, event: string, context: object, method: eventHandler): any&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;dojo.connect(element: Element, event: string, handler: eventHandler): any&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Used to associate a player event with one of your notification methods.&lt;br /&gt;
&lt;br /&gt;
Example: associate a click on an element (&amp;quot;my_element&amp;quot;) with one of our methods (&amp;quot;onClickOnMyElement&amp;quot;):&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
      dojo.connect( $(&#039;my_element&#039;), &#039;onclick&#039;, this, &#039;onClickOnMyElement&#039; );&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Same idea but based on query (i.e. all element of &#039;pet&#039; class)&lt;br /&gt;
      dojo.query(&amp;quot;.pet&amp;quot;).connect(&#039;onclick&#039;, this, &#039;onPet&#039;);&lt;br /&gt;
&lt;br /&gt;
Note: if you need to disconnect the handler you have to store handler returned from this method, i.e.&lt;br /&gt;
   &lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    var handler = dojo.connect(...);&lt;br /&gt;
    ...&lt;br /&gt;
    dojo.disconnect(handler);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If you don&#039;t store the handler - you have to destroy the object to disconnect it&lt;br /&gt;
&lt;br /&gt;
Typical function that implements the input handler will look like this&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
onPet: function(event) {&lt;br /&gt;
    var id = event.currentTarget.id;&lt;br /&gt;
    console.log(&#039;onPet &#039; + id);&lt;br /&gt;
    dojo.stopEvent(event);&lt;br /&gt;
    if (this.gamedatas.gamestate.name == &#039;playerTurnPet&#039;) {&lt;br /&gt;
          this.bgaPerformAction(&#039;actPlayPet&#039;, {card: id});&lt;br /&gt;
    } else {&lt;br /&gt;
          this.showMoveUnauthorized();&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.connect(element: ElementOrId, event: string, method: eventHandler): void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Used to associate a player event with one of your notification methods.&lt;br /&gt;
&lt;br /&gt;
      this.connect( $(&#039;my_element&#039;), &#039;onclick&#039;, &#039;onClickOnMyElement&#039; );&lt;br /&gt;
&lt;br /&gt;
Or you can use an in-place handler&lt;br /&gt;
&lt;br /&gt;
      this.connect( $(&#039;my_element&#039;), &#039;onclick&#039;, (e) =&amp;gt; { console.log(&#039;boo&#039;); } );&lt;br /&gt;
&lt;br /&gt;
Note that this function stores the connection handler. That is the only real difference between &#039;&#039;&#039;this.connect&#039;&#039;&#039; and &#039;&#039;&#039;dojo.connect&#039;&#039;&#039;. If you plan to destroy the element you connected, you &#039;&#039;&#039;must&#039;&#039;&#039; call this.disconnect() to prevent memory leaks.&lt;br /&gt;
This function is mainly for permanent objects - if you just want to connect the temp object you should probably not use this method but use dojo.connect which won&#039;t require any clean-up.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.connectClass(cssClassName: string, event: string, method: eventHandler): void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Same as connect(), but for all the nodes set with the specified cssClassName.&lt;br /&gt;
&lt;br /&gt;
	this.connectClass(&#039;pet&#039;, &#039;onclick&#039;, &#039;onPet&#039;);&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.disconnect(element: ElementOrId, event: string): void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Disconnect event handler (previously registered with this.connect or this.connectClass).&lt;br /&gt;
&lt;br /&gt;
   this.disconnect( $(&#039;my_element&#039;), &#039;onclick&#039;);&lt;br /&gt;
&lt;br /&gt;
Note: dynamic connect/disconnect is for advanced cases ONLY, you should always connect elements statically if possible, i.e. in setup() method.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.disconnectAll(): void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Disconnect all previously registed event handlers (registered via this.connect or this.connectClass)&lt;br /&gt;
&lt;br /&gt;
  this.disconnectAll();&lt;br /&gt;
&lt;br /&gt;
=== Actions ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.bgaPerformAction(action: string, args?: object, options: object = { lock: true, checkAction: true }): Promise&amp;lt;void&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Triggers an action on the backend. This is a combination of checkAction and ajaxcall, returning a Promise which resoves when ajaxcall ends.&lt;br /&gt;
&lt;br /&gt;
This method must be used to send a player input to the game server. &#039;&#039;&#039;It should not be triggered programmatically&#039;&#039;&#039;, especially not in loops, in callbacks, in notifications, or in onEnteringState/onUpdateActionButtons/onLeavingState, in order not to create race conditions or break replay game and tutorial features. It should be used only in reaction to a user action in the interface.&lt;br /&gt;
&lt;br /&gt;
* action: name of the action, as it is written in &amp;quot;possibleactions&amp;quot; of the current state.&lt;br /&gt;
* args: an object containing the call parameters to send to the action&lt;br /&gt;
* options: options to tweak the call with some defaults. Default is &amp;lt;code&amp;gt;{ lock: true, checkAction: true }&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Example of a standard call without args:&lt;br /&gt;
  this.bgaPerformAction(&#039;pass&#039;);&lt;br /&gt;
&lt;br /&gt;
Example of a standard call with action args:&lt;br /&gt;
  this.bgaPerformAction(&#039;actPlayCard&#039;, { id: this.selectedCardId });&lt;br /&gt;
&lt;br /&gt;
Example of a call without checking action (because player is inactive in a multiactive state):&lt;br /&gt;
&lt;br /&gt;
 this.bgaPerformAction(&#039;actChangeMind&#039;, {}, { checkAction: false });&lt;br /&gt;
&lt;br /&gt;
Example of a call without lock (because of a special action not directly related to the game flow):&lt;br /&gt;
&lt;br /&gt;
 this.bgaPerformAction(&#039;actSetAutoBid&#039;, { alwaysBidUntil: 500 }, { lock: false, checkAction: false });&lt;br /&gt;
&lt;br /&gt;
Example of call with reaction to exception:&lt;br /&gt;
  this.bgaPerformAction(&#039;actPlayCard&#039;, { id: this.selectedCardId }).catch(()=&amp;gt;{ this.selectedCardId = undefined; });&lt;br /&gt;
&lt;br /&gt;
Example of call with reaction to success:&lt;br /&gt;
  this.bgaPerformAction(&#039;actPlayCard&#039;, { id: this.selectedCardId }).then(()=&amp;gt;{ this.unselectAll(); });&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.ajaxcall(url, parameters, obj_callback, callback, callback_anycase?, ajax_method?: string)&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Note: bgaPerformAction is a simpler way to use ajax calls, ajaxcall stays in the doc for legacy reasons only and should not be used in new projects.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Same warning as &#039;&#039;&#039;this.bgaPerformAction&#039;&#039;&#039; about using on user action only.&lt;br /&gt;
&lt;br /&gt;
* url: the url of the action to perform. For a game, it must be: &amp;quot;/&amp;lt;mygame&amp;gt;/&amp;lt;mygame&amp;gt;/myAction.html&amp;quot;&lt;br /&gt;
* parameters: an array of parameter to send to the game server. &lt;br /&gt;
** Note that &amp;quot;lock: true&amp;quot; must always be specified in this list of parameters in order the interface can be locked during the server call. Cannot use lock: false - to not lock it has to be undefined.&lt;br /&gt;
** Note: Restricted parameter names (please don&#039;t use them):&lt;br /&gt;
*** &amp;quot;action&amp;quot;&lt;br /&gt;
*** &amp;quot;module&amp;quot;&lt;br /&gt;
*** &amp;quot;class&amp;quot;&lt;br /&gt;
* obj_callback: must be set to &amp;quot;this&amp;quot;.&lt;br /&gt;
* callback (non-optional but rarely used): a function to trigger when the server returns result and everything went fine (not used, as all data handling is done via notifications).&lt;br /&gt;
* callback_anycase: (optional) a function to trigger when the server returns ok OR error.  If no error this function is called with parameter value false. If an error occurred, the first parameter will be set to true, the second will contain the error message sent by the PHP back-end, and the third will contain an error code.&lt;br /&gt;
* ajax_method: (optional and rarely used) if you need to send large amounts of data (over 2048 bytes), you can set this parameter to &#039;post&#039; (all lower-case) to send a POST request as opposed to the default GET. This works, but was not officially documented, so only use if you really need to.&lt;br /&gt;
&lt;br /&gt;
Usage:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
this.ajaxcall( &#039;/mygame/mygame/actMyAction.html&#039;, { lock: true, &lt;br /&gt;
   arg1: myarg1, &lt;br /&gt;
   arg2: myarg2&lt;br /&gt;
}, this, (result)=&amp;gt;{} );&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.checkAction(action: string, nomessage?: boolean): boolean &#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Check if player can do the specified action by taking into account:&lt;br /&gt;
* if interface is locked it will return false and show message &amp;quot;An action is already in progress&amp;quot;,  unless nomessage set to true &lt;br /&gt;
* if player is not active it will return false and show message &amp;quot;This is not your turn&amp;quot;, unless nomessage set to true &lt;br /&gt;
* if action is not in list in possible actions (defined by &amp;quot;possibleaction&amp;quot; in current game state) it will return false and show &amp;quot;This move is not authorized now&amp;quot; error (unconditionally).&lt;br /&gt;
* otherwise returns true&lt;br /&gt;
Example:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  function onClickOnGameElement( evt )  {&lt;br /&gt;
     if( this.checkAction( &amp;quot;actMyAction&amp;quot; ) ) {&lt;br /&gt;
        // Do the action&lt;br /&gt;
     }&lt;br /&gt;
  }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.checkPossibleActions(action: string): boolean&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
* this is independent of the player being active, so can be used instead of this.checkAction(). This is particularly useful for multiplayer states when the player is not active in a &#039;player may like to change their mind&#039; scenario. Unlike this.checkAction, this function does NOT take interface locking into account &lt;br /&gt;
&lt;br /&gt;
* if action is not in list in possible actions (defined by &amp;quot;possibleaction&amp;quot; in current game state) it will return false and show &amp;quot;This move is not authorized now&amp;quot; error (unconditionally).&lt;br /&gt;
* otherwise returns true&lt;br /&gt;
&lt;br /&gt;
  function onChangeMyMind( evt )  {&lt;br /&gt;
     if( this.checkPossibleActions( &amp;quot;actMyAction&amp;quot; ) ) {&lt;br /&gt;
        // Do the action&lt;br /&gt;
     }&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.checkLock(nomessage?: boolean): boolean&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
When using &amp;quot;lock: true&amp;quot; in ajax call you can use this function to check if interface is in lock state (it will be locked during server call and notification processing).&lt;br /&gt;
This check can be used to block some other interactions which do not result in ajaxcall or if you want to suppress errors. Note: normally you only need to use this.checkAction(...), this is for advanced cases.&lt;br /&gt;
&lt;br /&gt;
It will also show error unless nomessage is set to true&lt;br /&gt;
&lt;br /&gt;
  function onChangeMyMind( evt )  {&lt;br /&gt;
     if( this.checkLock() ) {&lt;br /&gt;
        // Do the action&lt;br /&gt;
     }&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
== Notifications ==&lt;br /&gt;
&lt;br /&gt;
When something happens on the server side, your game interface Javascript logic received a notification.&lt;br /&gt;
If you have not done so yet check what notification are in [[Main_game_logic:_yourgamename.game.php#Notifications]]&lt;br /&gt;
&lt;br /&gt;
Here&#039;s how you can handle these notifications on the client side.&lt;br /&gt;
&lt;br /&gt;
=== Subscribe to notifications ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;dojo.subscribe(notif_type: string, callback_obj: Object, handler: string|handler)&#039;&#039;&#039;&lt;br /&gt;
* notif_type - notification type/name send by php server&lt;br /&gt;
* callback_obj - usually this&lt;br /&gt;
* handler - if string method of callback_obj with name name is called, when notification is called, with notification object as parameter (see below)&lt;br /&gt;
&lt;br /&gt;
Your Javascript &amp;quot;setupNotifications&amp;quot; method is the place where you can subscribe to notifications from your PHP code.&lt;br /&gt;
&lt;br /&gt;
Here&#039;s how you associate one of your Javascript method to a notification &amp;quot;playDisc&amp;quot; (from Reversi example):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
   setupNotifications: function() {&lt;br /&gt;
      ...&lt;br /&gt;
      dojo.subscribe(&#039;playDisc&#039;, this, &amp;quot;notif_playDisc&amp;quot;);&lt;br /&gt;
   },&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note: the &amp;quot;playDisc&amp;quot; corresponds to the name of the notification you define it in your PHP code, in your &amp;quot;notifyAllPlayers&amp;quot; or &amp;quot;notifyPlayer&amp;quot; method.&lt;br /&gt;
&lt;br /&gt;
Then, you have to define your &amp;quot;notif_playDisc&amp;quot; method:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
   notif_playDisc: function(notif) {&lt;br /&gt;
     // Remove current possible moves (makes the board more clear)&lt;br /&gt;
     dojo.query( &#039;.possibleMove&#039; ).removeClass( &#039;possibleMove&#039; );          &lt;br /&gt;
     this.addDiscOnBoard( notif.args.x, notif.args.y, notif.args.player_id );&lt;br /&gt;
   },&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In a notification handler like our &amp;quot;notif_playDisc&amp;quot; method, you can access all notifications arguments with &amp;quot;notif.args&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&lt;br /&gt;
PHP&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    $this-&amp;gt;notifyAllPlayers( &amp;quot;apples&amp;quot;, clienttranslate(&#039;player takes ${count} apples&#039;), [ &amp;quot;count&amp;quot; =&amp;gt; 3 ] );&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
JavaScript&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    setupNotifications: function() {&lt;br /&gt;
       dojo.subscribe( &#039;apples&#039;, this, &#039;notif_apples&#039; );&lt;br /&gt;
    },&lt;br /&gt;
&lt;br /&gt;
    notif_apples: function(notif) {&lt;br /&gt;
      //You can access the &amp;quot;count&amp;quot; like this:&lt;br /&gt;
       alert(&amp;quot;count = &amp;quot; + notif.args.count);&lt;br /&gt;
    }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== The notification Object received by client ===&lt;br /&gt;
&lt;br /&gt;
When sending a notification on your PHP, the client side will receive an Object with the following attributes:&lt;br /&gt;
&lt;br /&gt;
* type - type of the notification (as passed by php function)&lt;br /&gt;
* log - the log string passed from php notification&lt;br /&gt;
* args - This is the arguments that you passed on your notification method on php&lt;br /&gt;
* bIsTableMsg - is true when you use [[Main_game_logic:_yourgamename.game.php#NotifyAllPlayers|NotifyAllPlayers]] method (false otherwise)&lt;br /&gt;
* channelorig - information about table ID (formatted as : &amp;quot;/table/t[TABLE_NUMBER]&amp;quot;)&lt;br /&gt;
* gamenameorig - name of the game&lt;br /&gt;
* move_id - ID of the move associated with the notification&lt;br /&gt;
* table_id - ID of the table (comes as string)&lt;br /&gt;
* time - UNIX GMT timestamp&lt;br /&gt;
* uid - unique identifier of the notification&lt;br /&gt;
* h - unknown&lt;br /&gt;
&lt;br /&gt;
&#039;&#039; Note that those information were inferred from observation on console log. If an Admin can confirm/correct (and remove this line), you&#039;re welcome :)&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
=== Ignoring notifications ===&lt;br /&gt;
&lt;br /&gt;
Sometimes you need to ignore some notification on client side. You don&#039;t want them to be shown in game log and you don&#039;t want them to be handled.&lt;br /&gt;
&lt;br /&gt;
The most common use case is when a player gets private information. They will receive a specific notification (such as &amp;quot;You received Ace of Heart&amp;quot;), while other players would receive more generic notification (&amp;quot;Player received a card&amp;quot;).&lt;br /&gt;
&lt;br /&gt;
In X.game.php&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        $this-&amp;gt;notifyAllPlayers(&amp;quot;dealCard&amp;quot;, clienttranslate(&#039;${player_name} received a card&#039;), [&lt;br /&gt;
            &#039;player_id&#039; =&amp;gt; $playerId,&lt;br /&gt;
            &#039;player_name&#039; =&amp;gt; $this-&amp;gt;getActivePlayerName()&lt;br /&gt;
        ]);&lt;br /&gt;
&lt;br /&gt;
        $this-&amp;gt;notifyPlayer($playerId, &amp;quot;dealCardPrivate&amp;quot;, clienttranslate(&#039;You received ${cardName}&#039;), [&lt;br /&gt;
            &amp;quot;type&amp;quot; =&amp;gt; $card[&amp;quot;type&amp;quot;],&lt;br /&gt;
            &amp;quot;cardName&amp;quot; =&amp;gt; $this-&amp;gt;getCardName($card[&amp;quot;type&amp;quot;])&lt;br /&gt;
        ]);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The problem with this approach is that the active player will receive two notifications:&lt;br /&gt;
* Player1 received a card&lt;br /&gt;
* You received Ace of Hearts&lt;br /&gt;
&lt;br /&gt;
Hence, notification ignoring.&lt;br /&gt;
&lt;br /&gt;
NOTE: You can think that it would be possible to send such notification to all players except active just by using notifyPlayer and it seems to work. The problem however is that table spectators would miss such notification and their user interface (and game log) wouldn&#039;t be updated. Since there is no way to send notification just to spectators, ignoring the notification (or &amp;quot;filtering&amp;quot;) is the only reasonable solution.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;setIgnoreNotificationCheck(notif_type: string, predicate: ((notif: Notif)=&amp;gt;boolean))&#039;&#039;&#039;&lt;br /&gt;
This method will set a check whether any of notifications of specific type should be ignored.&lt;br /&gt;
&lt;br /&gt;
The parameters are:&lt;br /&gt;
* notif_type: type of the notification &lt;br /&gt;
* predicate (notif =&amp;gt; boolean): a function that will receive notif object and will return true if this specific notification should be ignored&lt;br /&gt;
&lt;br /&gt;
Before dispatching any notification of this type, the framework will call predicate to check whether notification should be ignored, if it return true - the notification will be dispatched, i.e. logged or handled.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    this.notifqueue.setIgnoreNotificationCheck( &#039;dealCard&#039;, (notif) =&amp;gt; (notif.args.player_id == this.player_id) );&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
IMPORTANT: Remember that this notification is ignored on the client side, but was still received by the client. Therefore it shouldn&#039;t contain any private information as cheaters can get it. In other words this is not a way to hide information.&lt;br /&gt;
&lt;br /&gt;
IMPORTANT: When a game is reloaded with F5 or when opening a turn based game, old notifications are replayed as history notification. They are used just to update the game log and are stripped of all arguments except player_id, i18n and any argument present in message. If you use and other argument in your predicate you should &#039;&#039;&#039;preserve&#039;&#039;&#039; it as explained [[Main_game_logic:_yourgamename.game.php#Notify_players|here]].&lt;br /&gt;
&lt;br /&gt;
=== Synchronous notifications ===&lt;br /&gt;
&lt;br /&gt;
When several notifications are received by your game interface, these notifications are processed immediately, one after the other, in the same exact order they have been generated in your PHP game logic.&lt;br /&gt;
&lt;br /&gt;
However, sometimes, you need to give some time to the players to figure out what happened on the game before jumping to the next notification. Indeed, in many games, there are a lot of automatic actions, and the computer is going to resolve all these actions very fast if you don&#039;t tell it not to do so.&lt;br /&gt;
&lt;br /&gt;
As an example, for Reversi, when someone is playing a disc, we want to wait 500 milliseconds before doing anything else in order the opponent player can figure out what move has been played.&lt;br /&gt;
&lt;br /&gt;
Here&#039;s how we do this, right after our subscription:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    dojo.subscribe( &#039;playDisc&#039;, this, &amp;quot;notif_playDisc&amp;quot; );&lt;br /&gt;
    this.notifqueue.setSynchronous( &#039;playDisc&#039;, 500 );   // Wait 500 milliseconds after executing the playDisc handler&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
-----&lt;br /&gt;
&lt;br /&gt;
It is also possible to control the delay timing dynamically (e.g., using notification args). As an example, maybe your notification &#039;cardPlayed&#039; should pause for a different amount of time depending on the number or type of cards played.&lt;br /&gt;
&lt;br /&gt;
For this case, use &#039;&#039;&#039;setSynchronous&#039;&#039;&#039; without specifying the duration and use &#039;&#039;&#039;setSynchronousDuration&#039;&#039;&#039; within the notification callback.&lt;br /&gt;
&lt;br /&gt;
* NOTE: If you forget to invoke &#039;&#039;&#039;setSynchronousDuration&#039;&#039;&#039;, the game will remain paused forever!&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
setupNotifications: function () {&lt;br /&gt;
    dojo.subscribe( &#039;cardPlayed&#039;, this, &#039;notif_cardPlayed&#039; );&lt;br /&gt;
    this.notifqueue.setSynchronous( &#039;cardPlayed&#039; ); // wait time is dynamic&lt;br /&gt;
    ...&lt;br /&gt;
},&lt;br /&gt;
&lt;br /&gt;
notif_cardPlayed: function (notif) {&lt;br /&gt;
    // MUST call setSynchronousDuration&lt;br /&gt;
&lt;br /&gt;
    // Example 1: From notification args (PHP)&lt;br /&gt;
    this.notifqueue.setSynchronousDuration(notif.args.duration);&lt;br /&gt;
    ...&lt;br /&gt;
&lt;br /&gt;
    // Or, example 2: Match the duration to a Dojo animation&lt;br /&gt;
    var anim = dojo.fx.combine([&lt;br /&gt;
        ...&lt;br /&gt;
    ]);&lt;br /&gt;
    anim.play();&lt;br /&gt;
    this.notifqueue.setSynchronousDuration(anim.duration);&lt;br /&gt;
},&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You can also manually call this.notifqueue.setSynchronousDuration(0) once client operations are finished, but be careful that even fast replay still has a path to call it.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;WARNING: combining synchronous and ignored notifications&#039;&#039;&#039;&lt;br /&gt;
You must be careful when combining dynamic synchronous durations (as described above) with ignored notifications. If you have a conditionally ignored notification like this (see below section):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;this.notifqueue.setIgnoreNotificationCheck( &#039;myNotif&#039;, (notif) =&amp;gt; (notif.args.player_id == this.player_id) /* or any other condition */ )&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
then you CANNOT do&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;this.notifqueue.setSynchronous(&#039;myNotif&#039;);&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
as, when the ignored check passes, the notification handler, in which `this.notifqueue.setSychronousDuration` is called, is never called and so the duration is never set and interface locking results.&lt;br /&gt;
&lt;br /&gt;
The workaround is to set a &amp;quot;dummy&amp;quot; time:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;this.notifqueue.setSynchronous(&#039;myNotif&#039;, 5000);&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
whose value is irrelevant but must be large enough to cover the time before the notification handler is called. The large value never actually comes into play because the notification is either ignored, or the synchronous duration is reset to a sensible value inside the handler.&lt;br /&gt;
&lt;br /&gt;
=== Pre-defined notification types ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;tableWindow&#039;&#039;&#039; - This defines notification to display [[Game_interface_logic:_yourgamename.js#Scoring_dialogs|Scoring Dialogs]], see below.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;message&#039;&#039;&#039; - This defines notification that shows on players log and have no other effect (technically any unhandled notification will do the same but its recommended to use this keyword for consistency)&lt;br /&gt;
&lt;br /&gt;
   // You can call this on php side without doing anything on client side&lt;br /&gt;
    self::notifyAllPlayers( &#039;message&#039;, clienttranslate(&#039;hello&#039;), [] );&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;simplePause&#039;&#039;&#039; - This notification will just delay other notifications, maybe useful if you know you need some extra time for animation or something. Requires a time parameter.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    self::notifyAllPlayers( &#039;simplePause&#039;, &#039;&#039;, [ &#039;time&#039; =&amp;gt; 500] ); // time is in milliseconds&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note: the following types are RESERVED by framework, do not use:&lt;br /&gt;
&lt;br /&gt;
gameStateChange gameStateChangePrivateArg gameStateMultipleActiveUpdate newActivePlayer playerstatus yourturnack clockalert tableInfosChanged playerEliminated tableDecision  archivewaitingdelay end_archivewaitingdelay replaywaitingdelay end_replaywaitingdelay replayinitialwaitingdelay end_replayinitialwaitingdelay aiPlayerWaitingDelay replay_has_ended updateSpectatorList  wouldlikethink updateReflexionTime undoRestorePoint resetInterfaceWithAllDatas zombieModeFail zombieModeFailWarning aiError skipTurnOfPlayer zombieBack allPlayersAreZombie gameResultNeutralized playerConcedeGame showTutorial showCursor showCursorClick skipTurnOfPlayerWarning  banFromTable resultsAvailable switchToTurnbased newPrivateState infomsg&lt;br /&gt;
&lt;br /&gt;
== Tooltips ==&lt;br /&gt;
&lt;br /&gt;
=== Adding static tooltips ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.addTooltip(nodeId: string, helpStringTranslated: string, actionStringTranslated: string, delay?: number): void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Add a simple text tooltip to the DOM node.&lt;br /&gt;
&lt;br /&gt;
Specify &#039;helpStringTranslated&#039; to display some information about &amp;quot;what is this game element?&amp;quot;.&lt;br /&gt;
Specify &#039;actionStringTranslated&#039; to display some information about &amp;quot;what happens when I click on this element?&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
You must specify both of the strings. You can only use one and specify an empty string (&#039;&#039;) for the other one.&lt;br /&gt;
&lt;br /&gt;
When you pass text directly function _() must be used for the text to be marked for translation! Except for empty string.&lt;br /&gt;
&lt;br /&gt;
Parameter &amp;quot;delay&amp;quot; is optional. It is primarily used to specify a zero delay for some game element when the tooltip gives really important information for the game - but remember: no essential information must be placed in tooltips as they won&#039;t be displayed in some browsers (see [[BGA_Studio_Guidelines|Guidelines]]).&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
   this.addTooltip( &#039;cardcount&#039;, _(&#039;Number of cards in hand&#039;), &#039;&#039; );&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note: this generates static tooltip and attaches to existing dom element, if you need to generate tooltip more dynamically you have to call that method every time information about object is updated or use completely different tehnique, see dynamic tooltips below.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.addTooltipHtml(nodeId: string, html: string, delay?: number): void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Add an HTML tooltip to the DOM node (for more elaborate content such as presenting a bigger version of a card).&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.addTooltipToClass(cssClass: string, helpStringTranslated: string, actionStringTranslated: string, delay?: number ): void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Add a simple text tooltip to all the DOM nodes set with this cssClass. See more details above for this.addTooltip.&lt;br /&gt;
     this.addTooltipToClass( &#039;meeple&#039;, _(&#039;This is A Meeple&#039;), _(&#039;Click to tickle&#039;) );&lt;br /&gt;
&lt;br /&gt;
IMPORTANT: all concerned nodes must exist and have IDs to get tooltips.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.addTooltipHtmlToClass(cssClass: string, html: string, delay?: number): void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Add an HTML tooltip to to all the DOM nodes set with this cssClass (for more elaborate content such as presenting a bigger version of a card).&lt;br /&gt;
&lt;br /&gt;
IMPORTANT: all concerned nodes must exist and have IDs to get tooltips.&lt;br /&gt;
&lt;br /&gt;
=== Removing static tooltips ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.removeTooltip(nodeId: string): void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Remove a tooltip from the DOM node with given id.&lt;br /&gt;
&lt;br /&gt;
=== Advanced tooltips ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;force tooltip to open&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
If you want to force tooltip to open in reaction to some other action, i.e. click you can do this&lt;br /&gt;
&lt;br /&gt;
   this.tooltips[id].open(id)&lt;br /&gt;
&lt;br /&gt;
where id is the id of the tooltip node where tooltip was installed.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;dynamic tooltips&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
See [[BGA_Studio_Cookbook#Dynamic_tooltips]]&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;tooltips on mobile&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Tooltips is very unreliable on mobile, it is recommended to implement some other method to obtaining same information,&lt;br /&gt;
such as simple click handler in dedicated &amp;quot;Help&amp;quot; mode or provide dedicated clickable areas such as corner of card.&lt;br /&gt;
&lt;br /&gt;
== Warning messages ==&lt;br /&gt;
&lt;br /&gt;
Sometimes, there is something important that is happening in the game and you have to make sure all players get the message. Most of the time, the evolution of the game situation or the game log is enough, but sometimes you need something more visible.&lt;br /&gt;
&lt;br /&gt;
Ex: someone fulfills one of the end of the game conditions, so this is the last turn.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.showMessage(msg: string, type: string): void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
showMessage shows a message in a big rectangular area on the top of the screen of the current player, and it dissapears after few seconds (also it will be in the log in some cases).&lt;br /&gt;
&lt;br /&gt;
* &amp;quot;msg&amp;quot; is the string to display. It should be translated.&lt;br /&gt;
* &amp;quot;type&amp;quot; can be set to &amp;quot;info&amp;quot;, &amp;quot;error&amp;quot;, &amp;quot;only_to_log&amp;quot; or custom string. If set to &amp;quot;info&amp;quot;, the message will be an informative message on a white background. If set to &amp;quot;error&amp;quot;, the message will be an error message on a red background and it will be added to log. If set to &amp;quot;only_to_log&amp;quot;, the message will be added to the game log but will not popup at the top of the screen.&lt;br /&gt;
If set to custom string, it will be transparent, to use custom type define &amp;quot;head_xxx&amp;quot; in css, where xxx is the type. For example if you want yellow warning, use &amp;quot;warning&amp;quot; as type and add this to css:&lt;br /&gt;
 .head_warning {&lt;br /&gt;
    background-color: #e6c66e;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
Important: the normal way to inform players about the progression of the game is the game log. The &amp;quot;showMessage&amp;quot; is intrusive and should not be used often.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    notif_messageinfo: function(notif) {&lt;br /&gt;
	if (!g_archive_mode) {&lt;br /&gt;
        	var message = this.format_string_recursive(notif.log, notif.args);&lt;br /&gt;
		this.showMessage(_(&#039;Announcement:&#039;) + &amp;quot; &amp;quot; + message, &#039;info&#039;);		&lt;br /&gt;
         }&lt;br /&gt;
    },&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Show message could be used on the client side to prevent user wrong moves before it is send to server.&lt;br /&gt;
Example from &#039;battleship&#039;:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
onGrid: function(event) {&lt;br /&gt;
     if (checkIfPlayerTriesToFireOnThemselves(event)) {&lt;br /&gt;
        this.showMessage(_(&#039;This is your own board silly!&#039;), &#039;error&#039;);&lt;br /&gt;
        return;&lt;br /&gt;
     }&lt;br /&gt;
     ...&lt;br /&gt;
},&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.showMoveUnauthorized(): void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Shows predefined user error that move is unauthorized now&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
onPet: function(event) {&lt;br /&gt;
     if (checkPet(event)==false) {&lt;br /&gt;
        this.showMoveUnauthorized();&lt;br /&gt;
        return;&lt;br /&gt;
     }&lt;br /&gt;
     ...&lt;br /&gt;
},&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Dialogs ==&lt;br /&gt;
&lt;br /&gt;
=== Confirmation dialog ===&lt;br /&gt;
&lt;br /&gt;
When an important action with a lot of consequences is triggered by the player, you may want to propose a confirmation dialog.&lt;br /&gt;
&lt;br /&gt;
CAREFUL: the general guideline of BGA is to AVOID the use of confirmation dialogs. Confirmation dialogs slow down the game and bother players. The players know that they have to pay attention to each move when they are playing online.&lt;br /&gt;
&lt;br /&gt;
The situations where you should use a confirmation dialog are the following:&lt;br /&gt;
* It must not happen very often during a game.&lt;br /&gt;
* It must be linked to an action that can really &amp;quot;kill a game&amp;quot; if the player does not pay attention.&lt;br /&gt;
* It must be something that can be done by mistake (ex: a link on the action status bar).&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.confirmationDialog(message: string, yesHandler: (param: any) =&amp;gt; void, noHandler?: (param: any) =&amp;gt; void, param?: any): void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
* message - message will be shown to user, use _() to translate&lt;br /&gt;
* yesHandler - non-optional handler to be called on yes&lt;br /&gt;
* noHandler - optional handler to called on no&lt;br /&gt;
* param - if specified, it will be passed to both handlers&lt;br /&gt;
NOTE: this is async function, it does not return anything and you should not do anything after, you must do everything in handlers&lt;br /&gt;
&lt;br /&gt;
How to display a confirmation dialog:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    this.confirmationDialog(_(&amp;quot;Are you sure you want to bake a pie?&amp;quot;), () =&amp;gt; {&lt;br /&gt;
      this.bakeThePie();&lt;br /&gt;
    });&lt;br /&gt;
    return; // nothing should be called or done after calling this, all action must be done in the handler&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
With param and both handlers&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    this.confirmationDialog(_(&amp;quot;Are you sure you want to bake a pie?&amp;quot;), &lt;br /&gt;
           (ingredient) =&amp;gt; this.bakeThePie(ingredient), &lt;br /&gt;
           (ingredient) =&amp;gt; console.log(`cancelled baking of ${ingredient}`), &lt;br /&gt;
           &#039;apple&#039;);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Multiple choice dialog ===&lt;br /&gt;
&lt;br /&gt;
You can use this dialog to give user a choice with small amount of options&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.multipleChoiceDialog(message: string, choices: string[], callback: (choice: number) =&amp;gt; void): void&#039;&#039;&#039;&lt;br /&gt;
* message - message will be shown to user, use _() to translate&lt;br /&gt;
* choices - array of choices&lt;br /&gt;
* callback - non-optional handler to be called on choice made, the choice parameter is the INDEX of the choice from the array of choices&lt;br /&gt;
&lt;br /&gt;
NOTE: this is async function, it does not return anything and you should not do anything after, you must do everything in handlers&lt;br /&gt;
NOTE: there is no cancel handler, so make sure you gave user a choice to get out of it&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    const keys = [&amp;quot;0&amp;quot;, &amp;quot;1&amp;quot;, &amp;quot;5&amp;quot;, &amp;quot;10&amp;quot;];&lt;br /&gt;
    this.multipleChoiceDialog(_(&amp;quot;How many bugs to fix?&amp;quot;), keys, (choice) =&amp;gt; {&lt;br /&gt;
      if (choice==0) return; // cancel operation, do not call server action&lt;br /&gt;
      var bugchoice = keys[choice]; // choice will be 0,1,2,3 here&lt;br /&gt;
      this.bgaPerformAction(&amp;quot;fixBugs&amp;quot;, { number: bugchoice });&lt;br /&gt;
    });&lt;br /&gt;
    return; // must return here&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Generic Dialogs ===&lt;br /&gt;
&lt;br /&gt;
As a general rule, you shouldn&#039;t use dialogs windows.&lt;br /&gt;
&lt;br /&gt;
BGA guidelines specify that all game elements should be displayed on the main screen. Players can eventually scroll down to see game elements they don&#039;t need to see anytime, and you may eventually create anchors to move between game area section. Of course dialogs windows are very practical, but the thing is: all players know how to scroll down, and not all players know how to show up your dialog window. In addition, when the dialog shows up, players can&#039;t access the other game components.&lt;br /&gt;
&lt;br /&gt;
Sometimes although, you need to display a dialog window. Here is how you do this:&lt;br /&gt;
&lt;br /&gt;
  // Create the new dialog over the play zone. You should store the handler in a member variable to access it later&lt;br /&gt;
  this.myDlg = new ebg.popindialog();&lt;br /&gt;
  this.myDlg.create( &#039;myDialogUniqueId&#039; );&lt;br /&gt;
  this.myDlg.setTitle( _(&amp;quot;my dialog title to translate&amp;quot;) );&lt;br /&gt;
  this.myDlg.setMaxWidth( 500 ); // Optional&lt;br /&gt;
  &lt;br /&gt;
  // Create the HTML of my dialog. &lt;br /&gt;
  // The best practice here is to use [[Game_layout:_view_and_template:_yourgamename.view.php_and_yourgamename_yourgamename.tpl#Javascript_templates|Javascript templates]]&lt;br /&gt;
  var html = this.format_block( &#039;jstpl_myDialogTemplate&#039;, { &lt;br /&gt;
                arg1: myArg1,&lt;br /&gt;
                arg2: myArg2,&lt;br /&gt;
                ...&lt;br /&gt;
            } );  &lt;br /&gt;
  &lt;br /&gt;
  // Show the dialog&lt;br /&gt;
  this.myDlg.setContent( html ); // Must be set before calling show() so that the size of the content is defined before positioning the dialog&lt;br /&gt;
  this.myDlg.show();&lt;br /&gt;
  &lt;br /&gt;
  // Now that the dialog has been displayed, you can connect your method to some dialog elements&lt;br /&gt;
  // Example, if you have an &amp;quot;OK&amp;quot; button in the HTML of your dialog:&lt;br /&gt;
  dojo.connect($(&#039;my_ok_button&#039;), &#039;onclick&#039;, this, (event) =&amp;gt; {&lt;br /&gt;
                event.preventDefault();&lt;br /&gt;
                this.myDlg.destroy();&lt;br /&gt;
            });&lt;br /&gt;
&lt;br /&gt;
If necessary, you can remove the default top right corner &#039;close&#039; icon, or replace the function called when it is clicked:&lt;br /&gt;
  // Removes the default close icon&lt;br /&gt;
  this.myDlg.hideCloseIcon();&lt;br /&gt;
&lt;br /&gt;
  // Replace the function call when it&#039;s clicked&lt;br /&gt;
  this.myDlg.replaceCloseCallback((event) =&amp;gt; { ... });&lt;br /&gt;
&lt;br /&gt;
=== Scoring dialogs ===&lt;br /&gt;
&lt;br /&gt;
Sometimes at the end of a round you want to display a big table that details the points wins in each section of the game.&lt;br /&gt;
&lt;br /&gt;
Example: in Hearts game, we display at the end of each round the number of &amp;quot;heart&amp;quot; cards collected by each player, the player who collected the Queen of Spades, and the total number of points loose by each player.&lt;br /&gt;
&lt;br /&gt;
Scoring dialogs are managed entirely on &#039;&#039;&#039;PHP side&#039;&#039;&#039;, but they are described here as their effects are visible only on client side.&lt;br /&gt;
&lt;br /&gt;
Displaying a scoring dialog is quite simple and is using a special notification type: &amp;quot;tableWindow&amp;quot;:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  // on PHP side:&lt;br /&gt;
  $this-&amp;gt;notifyAllPlayers( &amp;quot;tableWindow&amp;quot;, &#039;&#039;, array(&lt;br /&gt;
            &amp;quot;id&amp;quot; =&amp;gt; &#039;finalScoring&#039;,&lt;br /&gt;
            &amp;quot;title&amp;quot; =&amp;gt; clienttranslate(&amp;quot;Title of the scoring dialog&amp;quot;),&lt;br /&gt;
            &amp;quot;table&amp;quot; =&amp;gt; $table&lt;br /&gt;
        )); &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The &amp;quot;table&amp;quot; argument is a 2 dimensional PHP array that describes the table you want to display, line by line and column by column.&lt;br /&gt;
&lt;br /&gt;
Example: display an 3x3 array of strings&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
   $table = [&lt;br /&gt;
      [ &amp;quot;one&amp;quot;, &amp;quot;two&amp;quot;, &amp;quot;three&amp;quot; ],    // This is my first line&lt;br /&gt;
      [ &amp;quot;four&amp;quot;, &amp;quot;five&amp;quot;, &amp;quot;six&amp;quot; ],    // This is my second line&lt;br /&gt;
      [ &amp;quot;seven&amp;quot;, &amp;quot;height&amp;quot;, &amp;quot;nine&amp;quot; ]    // This is my third line&lt;br /&gt;
   ];&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
As you can see above, in each &amp;quot;cell&amp;quot; of your array you can display a simple string value. But you can also display a complex value with a template and associated arguments like this:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
   $table = [&lt;br /&gt;
      [ &amp;quot;one&amp;quot;, &amp;quot;two&amp;quot;, [ &amp;quot;str&amp;quot; =&amp;gt; clienttranslate(&amp;quot;a string with an ${argument}&amp;quot;), &amp;quot;args&amp;quot; =&amp;gt; [ &#039;argument&#039; =&amp;gt; &#039;argument_value&#039; ] ] ],&lt;br /&gt;
      [ &amp;quot;four&amp;quot;, &amp;quot;five&amp;quot;, &amp;quot;six&amp;quot; ], &lt;br /&gt;
      [ &amp;quot;seven&amp;quot;, &amp;quot;height&amp;quot;, &amp;quot;nine&amp;quot; ]&lt;br /&gt;
   ];&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This is especially useful when you want to display player names with colors. Example from &amp;quot;Hearts&amp;quot;:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        $firstRow = [ &#039;&#039; ];&lt;br /&gt;
        foreach( $players as $player_id =&amp;gt; $player )    {&lt;br /&gt;
            $cell = [ &#039;str&#039; =&amp;gt; &#039;${player_name}&#039;,&lt;br /&gt;
                      &#039;args&#039; =&amp;gt; [ &#039;player_name&#039; =&amp;gt; $player[&#039;player_name&#039;] ],&lt;br /&gt;
                      &#039;type&#039; =&amp;gt; &#039;header&#039;&lt;br /&gt;
                    ];&lt;br /&gt;
            $firstRow[] = $cell;&lt;br /&gt;
        }&lt;br /&gt;
        $table[] = $firstRow;&lt;br /&gt;
        ...&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You can also use three extra attributes in the parameter array for the notification:&lt;br /&gt;
* &#039;&#039;&#039;header&#039;&#039;&#039;: the content for this parameter displays before the table (also, the html will be parsed and player names will be colored according to the current game colors). &lt;br /&gt;
* &#039;&#039;&#039;footer&#039;&#039;&#039;: the content for this parameter displays after the table (no parsing for coloring the player names)&lt;br /&gt;
* &#039;&#039;&#039;closing&#039;&#039;&#039;: if this parameter is used, a button will be displayed with this label at the bottom of the popup and will allow players to close it (more easily than by clicking the top right &#039;cross&#039; icon).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
   $this-&amp;gt;notifyAllPlayers( &amp;quot;tableWindow&amp;quot;, &#039;&#039;, [&lt;br /&gt;
            &amp;quot;id&amp;quot; =&amp;gt; &#039;finalScoring&#039;,&lt;br /&gt;
            &amp;quot;title&amp;quot; =&amp;gt; clienttranslate(&amp;quot;Title of the scoring dialog&amp;quot;),&lt;br /&gt;
            &amp;quot;table&amp;quot; =&amp;gt; $table,&lt;br /&gt;
            &amp;quot;header&amp;quot; =&amp;gt; [&#039;str&#039; =&amp;gt; clienttranslate(&#039;Table header with parameter ${number}&#039;),&lt;br /&gt;
                                 &#039;args&#039; =&amp;gt; [ &#039;number&#039; =&amp;gt; 3 ],&lt;br /&gt;
                               ],&lt;br /&gt;
            &amp;quot;footer&amp;quot; =&amp;gt; &#039;&amp;lt;div class=&amp;quot;myfoot&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&#039;,&lt;br /&gt;
            &amp;quot;closing&amp;quot; =&amp;gt; clienttranslate( &amp;quot;Closing button label&amp;quot; )&lt;br /&gt;
        ] ); &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note: currently id is not used - so you cannot access resulting div by id on js side&lt;br /&gt;
Note: any traslatable stirng have to be wrapped by clienttranslate() on top level OR it has to be recursive template. &lt;br /&gt;
&lt;br /&gt;
DO NOT DO THIS: &lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
   &amp;quot;footer&amp;quot; =&amp;gt; &#039;&amp;lt;div&amp;gt;&#039;.clienttranslate( &amp;quot;The end&amp;quot; ).&#039;&amp;lt;/div&amp;gt;&#039;, // this will not work for translations!!!&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Scoring animated display ===&lt;br /&gt;
&lt;br /&gt;
Sometimes, you may want to display a score value over an element to make the scoring easier to follow for the players (Terra Mystica final scoring for example).&lt;br /&gt;
You can do it with:&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.displayScoring(anchor_id: string, color: string, score: number | string, duration?: number, offset_x?: number, offset_y?: number): void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;anchor_id&#039;&#039;&#039;: ID of the html element to place the animated score onto (without the &#039;#&#039;) &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;color&#039;&#039;&#039;: hexadecimal RGB representation of the color (should be the color of the scoring player), but without a leading &#039;#&#039;.  For instance, &#039;ff0000&#039; for red.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;score&#039;&#039;&#039;: numeric score to display, prefixed by a &#039;+&#039; or &#039;-&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;duration&#039;&#039;&#039;: animation duration in milliseconds (optional, default is 1000)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;offset_x&#039;&#039;&#039; and &#039;&#039;&#039;offset_y&#039;&#039;&#039;: if both offset_x and offset_y are defined and not null, apply the following offset (in pixels) to the scoring animation. &lt;br /&gt;
Note that the score is centered in the anchor, so the offsets might have to be negative if you calculate the position.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Note: if you want to display successively each score, you can use &#039;&#039;this.notifqueue.setSynchronous()&#039;&#039; function.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    setupNotifications: function()   {&lt;br /&gt;
           dojo.subscribe( &#039;displayScoring&#039;, this, &amp;quot;notif_displayScoring&amp;quot; );&lt;br /&gt;
           ...&lt;br /&gt;
    }&lt;br /&gt;
...&lt;br /&gt;
&lt;br /&gt;
    notif_displayScoring: function(notif) {&lt;br /&gt;
            const duration = notif.args.duration?notif.args.duration:1000;&lt;br /&gt;
            this.notifqueue.setSynchronous(&#039;displayScoring&#039;, duration );&lt;br /&gt;
	    this.displayScoring( notif.args.target, notif.args.color, notif.args.score, duration);&lt;br /&gt;
    },&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Speech bubble ===&lt;br /&gt;
&lt;br /&gt;
For better interactivity in some games (Love Letter for example), you may use comic book style speech bubbles to express the players voices.&lt;br /&gt;
This is done with showBubble:&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.showBubble(anchor_id: string, text: string, delay?: number, duration?: number, custom_class?: string): void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
* anchor_id - where to attach the bubble&lt;br /&gt;
* text - what to put in bubble, can be html&lt;br /&gt;
* delay - delay in milliseconds (optional, default 0)&lt;br /&gt;
* duration -  duration of animation in milliseconds (optional, default 3000)&lt;br /&gt;
* custom_class - extra class to add to bubble (optional), if you need to override the default bubble style&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
   this.showBubble(&#039;meeple_2&#039;, _(&#039;Hello&#039;), 0, 1000, &#039;pink_bubble&#039;);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  notif_speechBubble(notif) {&lt;br /&gt;
    var html = this.format_string_recursive(notif.args.text, notif.args.args);&lt;br /&gt;
    this.showBubble(notif.args.target, html, notif.args.delay ?? 0, notif.args.duration ?? 1000);&lt;br /&gt;
  },&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Warning&#039;&#039;&#039;: if your bubble could overlap other active elements of the interface (buttons in particular), as it stays in place even after disappearing, you should use a custom class to give it the style &amp;quot;pointer-events: none;&amp;quot; in order to intercept click events.&lt;br /&gt;
&lt;br /&gt;
Note: If you want this visually, but want to take complete control over this bubble and its animation (for example to make it permanent) you can just use div with &#039;discussion_bubble&#039; class on it, and content of div is what will be shown.&lt;br /&gt;
&lt;br /&gt;
== Translations ==&lt;br /&gt;
&lt;br /&gt;
See [[Translations]]&lt;br /&gt;
&lt;br /&gt;
== Players panels ==&lt;br /&gt;
&lt;br /&gt;
=== Update players score ===&lt;br /&gt;
&lt;br /&gt;
The column player_score from the player table is automatically loaded into this.scoreCtrl and therefore into the stars location on the player board. This occurs sometime after the game setup() function. However this score must be updated as the game progresses using notifications.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Note: this.scoreCtrl[player_id] is object of class [[Counter]], you can use other counter API.&lt;br /&gt;
&lt;br /&gt;
Increase a player score (with a positive or negative number):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  this.scoreCtrl[ player_id ].incValue( score_delta );&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Set a player score to a specific value:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  this.scoreCtrl[ player_id ].setValue( new_score );&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Set a player score to a specific value with animation:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  this.scoreCtrl[ player_id ].toValue( new_score );&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Typical usage would be (that will process &#039;score&#039; notification):&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        setupNotifications : function() {&lt;br /&gt;
              ...&lt;br /&gt;
             dojo.subscribe(&#039;score&#039;, this, &amp;quot;notif_score&amp;quot;);&lt;br /&gt;
        },&lt;br /&gt;
        notif_score: function(notif) {&lt;br /&gt;
            this.scoreCtrl[notif.args.player_id].setValue(notif.args.player_score);&lt;br /&gt;
        },&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Adding stuff to player&#039;s panel ===&lt;br /&gt;
&lt;br /&gt;
At first, create a new &amp;quot;JS template&amp;quot; string in your template (tpl) file:&lt;br /&gt;
&lt;br /&gt;
(from Gomoku example)&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
var jstpl_player_board = &#039;\&amp;lt;div class=&amp;quot;cp_board&amp;quot;&amp;gt;\&lt;br /&gt;
    &amp;lt;div id=&amp;quot;stoneicon_p${id}&amp;quot; class=&amp;quot;gmk_stoneicon gmk_stoneicon_${color}&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&amp;lt;span id=&amp;quot;stonecount_p${id}&amp;quot;&amp;gt;0&amp;lt;/span&amp;gt;\&lt;br /&gt;
&amp;lt;/div&amp;gt;&#039;;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Then, you add this piece of code in your JS file to add this template to each player panel:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
            // Setting up player boards&lt;br /&gt;
            for( var player_id in gamedatas.players )&lt;br /&gt;
            {&lt;br /&gt;
                var player = gamedatas.players[player_id];&lt;br /&gt;
                         &lt;br /&gt;
                // Setting up players boards if needed&lt;br /&gt;
                var player_board_div = $(&#039;player_board_&#039;+player_id);&lt;br /&gt;
                dojo.place( this.format_block(&#039;jstpl_player_board&#039;, player ), player_board_div );&lt;br /&gt;
            }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
(Note: the code above is of course from your &amp;quot;setup&amp;quot; function in your Javascript).&lt;br /&gt;
&lt;br /&gt;
Very often, you have to distinguish current player and others players. In this case, you just have to create another JS template (ex: jstpl_otherplayer_board) and use it when &amp;quot;player_id&amp;quot; is different than &amp;quot;this.player_id&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Fixing Player Panel heights ===&lt;br /&gt;
&lt;br /&gt;
You may find that the player panels don&#039;t automatically resize when adding something to (or removing something from) a player panel while the display is in portrait mode (i.e. the player summary panels are at the top of the screen rather than down the right side).&lt;br /&gt;
&lt;br /&gt;
When this happens, call &amp;lt;pre&amp;gt;this.adaptPlayersPanels();&amp;lt;/pre&amp;gt; This recalculates the layout and also adjusts the position of the actionbar for you.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Player&#039;s panel disabling/enabling ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.disablePlayerPanel(player_id: number): void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Disable given player panel (the panel background become gray).&lt;br /&gt;
&lt;br /&gt;
Usually, this is used to signal that this played passes, or will be inactive during a while.&lt;br /&gt;
&lt;br /&gt;
Note that the only effect of this is visual. There are no consequences on the behaviour of the panel itself.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.enablePlayerPanel(player_id:number): void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Enable a player panel that has been disabled before.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.enableAllPlayerPanels(): void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Enable all player panels that has been disabled before.&lt;br /&gt;
&lt;br /&gt;
=== Player order ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.updatePlayerOrdering(): void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
This function makes sure that player order in player&#039;s panel matches this.gamedatas.playerorder and its normally called by framework.&lt;br /&gt;
You can call it yoursel if you change this.gamedatas.playerorder from notification.&lt;br /&gt;
Also you can override this function to change defaults  OR insert a non-player panel [[BGA_Studio_Cookbook#Inserting_non-player_panel]].&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Counters ===&lt;br /&gt;
Note: there is bga component called  &amp;quot;ebg/counter&amp;quot; this API is not using it, these methods&lt;br /&gt;
below declared right in core game. If you need animation for counters use ebg/counter&lt;br /&gt;
&lt;br /&gt;
To use this API just create a counter dom element like this (class does not really matter)&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 &amp;lt;div class=&amp;quot;counter&amp;quot; id=&amp;quot;bread&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
 &amp;lt;div class=&amp;quot;counter&amp;quot; id=&amp;quot;coin&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
The &amp;quot;bread&amp;quot; will the counter name.&lt;br /&gt;
&lt;br /&gt;
The php code should send all &amp;quot;counters&amp;quot; data from getAllDatas() method like this&lt;br /&gt;
&lt;br /&gt;
game.php&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  protected function getAllDatas() {&lt;br /&gt;
    // (the key must match counter_name)&lt;br /&gt;
    $result[&#039;counters&#039;]=[&lt;br /&gt;
        &#039;bread&#039; =&amp;gt; [ &lt;br /&gt;
         &#039;counter_name&#039; =&amp;gt; &#039;bread&#039;, &lt;br /&gt;
         &#039;counter_value&#039; =&amp;gt; 3&lt;br /&gt;
         ], &lt;br /&gt;
        &#039;coin&#039; =&amp;gt; [&lt;br /&gt;
          &#039;counter_name&#039; =&amp;gt; &#039;coin&#039;, &lt;br /&gt;
          &#039;counter_value&#039; =&amp;gt; 5&lt;br /&gt;
        ]&lt;br /&gt;
   ];&lt;br /&gt;
   return $result;&lt;br /&gt;
  }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;setCounter(counter_name: stirng, new_value: string | number): void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
updates the global this.gamedatas.counters and value of node $(counter_name)&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  notif_counter: function(notif) { &lt;br /&gt;
    this.setCounter(notif.args.counter_name, notif.args.counter_value);&lt;br /&gt;
  },&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;incCounter(counter_name: string, delta: number): void&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  notif_counter : function(notif) {&lt;br /&gt;
    this.incCounter(notif.args.counter_name, notif.args.inc);&lt;br /&gt;
  },&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;updateCounters(counters: object): void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Useful for updating game counters in the player panel (such as resources). &lt;br /&gt;
&#039;counters&#039; arg is map of counters (the key must match counter_name)&lt;br /&gt;
  {&lt;br /&gt;
    &#039;bread&#039;: { &lt;br /&gt;
         &#039;counter_name&#039; : &#039;bread&#039;, &lt;br /&gt;
         &#039;counter_value&#039; =&amp;gt; 3&lt;br /&gt;
    }, &lt;br /&gt;
    &#039;coin&#039;: { &lt;br /&gt;
         &#039;counter_name&#039; : &#039;coin&#039;, &lt;br /&gt;
         &#039;counter_value&#039; =&amp;gt; 5&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
All counters MUST be referenced in this.gamedatas.counters (means they should be send from php) and will be updated.&lt;br /&gt;
DOM objects referenced by &#039;counter_name&#039; will have their innerHTML updated with &#039;counter_value&#039;.&lt;br /&gt;
&lt;br /&gt;
Usually you call this from notification&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
                        notif_counter : function(notif) {&lt;br /&gt;
                            this.updateCounters(notif.args.counters);&lt;br /&gt;
                        },&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== BGA GUI components ==&lt;br /&gt;
&lt;br /&gt;
BGA framework provides some useful ready-to-use components for the game interface:&lt;br /&gt;
&lt;br /&gt;
[[Studio#BGA_Studio_game_components_reference]]&lt;br /&gt;
&lt;br /&gt;
Note that each time you are using an additional component, you must declare it at the top of your Javascript file in the list of modules used.&lt;br /&gt;
&lt;br /&gt;
Example if you are using &amp;quot;ebg.stock&amp;quot;:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
define([&lt;br /&gt;
    &amp;quot;dojo&amp;quot;,&amp;quot;dojo/_base/declare&amp;quot;,&lt;br /&gt;
    &amp;quot;ebg/core/gamegui&amp;quot;,&lt;br /&gt;
    &amp;quot;ebg/counter&amp;quot;,&lt;br /&gt;
    &amp;quot;ebg/stock&amp;quot;  /// &amp;lt;=== we are using ebg.stock module&lt;br /&gt;
],&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== BGA Buttons ==&lt;br /&gt;
&lt;br /&gt;
=== Basic Button ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.addActionButton(id: string, label: string, method: string | eventhandler, destination?: string, blinking?: boolean, color?: string): void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
You can use this method to add an action button in the main action status bar (or other places).&lt;br /&gt;
&lt;br /&gt;
Arguments:&lt;br /&gt;
* id: an element ID that should be unique in your HTML DOM document.&lt;br /&gt;
* label: the text of the button. Should be translatable (use _() function). Note: this can also be any html, such as &amp;quot;&amp;lt;div class=&#039;brick&#039;&amp;gt;&amp;lt;/div&amp;gt;&amp;quot;, see example below on how to make image action buttons.&lt;br /&gt;
* method: the name of your method that must be triggered when the player clicks on this button (can be name of the method on game class or handler).&lt;br /&gt;
* destination (optional): id of parent on where to add button, ONLY use in rare cases if location is not action bar. Use &#039;&#039;&#039;null&#039;&#039;&#039; as value if you need to specify other arguments.&lt;br /&gt;
* blinking (optional): if set to &#039;&#039;&#039;true&#039;&#039;&#039;, the button is going blink to catch player&#039;s attention. Please DO NOT abuse blinking button. If you need button to blink after some time passed add class &#039;blinking&#039; to the button later.&lt;br /&gt;
* color: could be &#039;&#039;&#039;blue&#039;&#039;&#039; (default), &#039;&#039;&#039;red&#039;&#039;&#039;,&#039;&#039;&#039;gray&#039;&#039;&#039; or &#039;&#039;&#039;none&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
You should only use this method in your &amp;quot;onUpdateActionButtons&amp;quot; method. Usually, you use it like this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        onUpdateActionButtons: function( stateName, args ) {                      &lt;br /&gt;
            if (this.isCurrentPlayerActive()) {            &lt;br /&gt;
                switch( stateName ) {&lt;br /&gt;
                case &#039;giveCards&#039;:&lt;br /&gt;
                    this.addActionButton( &#039;giveCards_button&#039;, _(&#039;Give selected cards&#039;), &#039;onGiveCards&#039; ); &lt;br /&gt;
                    this.addActionButton( &#039;pass_button&#039;, _(&#039;Pass&#039;), () =&amp;gt; this.bgaPerformAction(&#039;actPass&#039;) ); &lt;br /&gt;
                    break;&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        },   &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In the example above, we are adding a &amp;quot;Give selected cards&amp;quot; button in the case we are on game state &amp;quot;giveCards&amp;quot;. When player clicks on this button, it triggers our &amp;quot;onGiveCards&amp;quot; method.&lt;br /&gt;
&lt;br /&gt;
Example using blinking red button:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    this.addActionButton( &#039;button_confirm&#039;, _(&#039;Confirm?&#039;), &#039;onConfirm&#039;, null, true, &#039;red&#039;); &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If you want to call the handler with arguments, you can use arrow functions, like this:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
     this.addActionButton( &#039;commit_button&#039;, _(&#039;Confirm&#039;), () =&amp;gt; this.onConfirm(this.selectedCardId), null, false, &#039;red&#039;); &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Image Button ===&lt;br /&gt;
&lt;br /&gt;
You can use the same method, but add extra class to a button to disable the padding and style it, i.e.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
this.addActionButton( &#039;button_brick&#039;, &#039;&amp;lt;div class=&amp;quot;brick&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&#039;, ()=&amp;gt;{... on brick ...}, null, null, &#039;gray&#039;); &lt;br /&gt;
dojo.addClass(&#039;button_brick&#039;,&#039;bgaimagebutton&#039;);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
where&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
.bgaimagebutton {&lt;br /&gt;
  padding: 0px 12px;&lt;br /&gt;
  min-height: 28px;&lt;br /&gt;
  border: none;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If you use this a lot, you can define a helper function, i.e.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
 * This method can be used instead of addActionButton, to add a button which is an image (i.e. resource). Can be useful when player&lt;br /&gt;
 * need to make a choice of resources or tokens.&lt;br /&gt;
 */&lt;br /&gt;
addImageActionButton: function(id, div, handler, bcolor, tooltip) {&lt;br /&gt;
	if (typeof bcolor == &amp;quot;undefined&amp;quot;) {&lt;br /&gt;
		bcolor = &amp;quot;gray&amp;quot;;&lt;br /&gt;
	}&lt;br /&gt;
	// this will actually make a transparent button id color = gray&lt;br /&gt;
	this.addActionButton(id, div, handler, null, false, bcolor);&lt;br /&gt;
	// remove border, for images it better without&lt;br /&gt;
	dojo.style(id, &amp;quot;border&amp;quot;, &amp;quot;none&amp;quot;);&lt;br /&gt;
	// but add shadow style (box-shadow, see css)&lt;br /&gt;
	dojo.addClass(id, &amp;quot;shadow bgaimagebutton&amp;quot;);&lt;br /&gt;
	// you can also add additional styles, such as background&lt;br /&gt;
	if (tooltip) {&lt;br /&gt;
		dojo.attr(id, &amp;quot;title&amp;quot;, tooltip);&lt;br /&gt;
	}&lt;br /&gt;
	return $(id);&lt;br /&gt;
},&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Disabling Button ===&lt;br /&gt;
&lt;br /&gt;
You can disable the &#039;&#039;&#039;bgabutton&#039;&#039;&#039; by adding the css class &#039;&#039;&#039;disabled&#039;&#039;&#039; in you js. The disabled button is still visible but is grey and not clickable.&lt;br /&gt;
For example in the &#039;&#039;&#039;onUpdateActionButtons&#039;&#039;&#039; : &lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
this.addActionButton(&#039;play_button_id&#039;, _(&#039;Play 1 to 3 cards&#039;), &#039;playFunctionButton&#039;); &lt;br /&gt;
if (condition) {&lt;br /&gt;
  dojo.addClass(&#039;play_button_id&#039;, &#039;disabled&#039;);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Custom Buttons ===&lt;br /&gt;
&lt;br /&gt;
You can create a custom button, but the BGA framework provides a standard button that requires only .css classes: &#039;&#039;&#039;bgabutton&#039;&#039;&#039; and &#039;&#039;&#039;bgabutton_${color}&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Examples:&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;a href=&amp;quot;#&amp;quot; id=&amp;quot;my_button_id&amp;quot; class=&amp;quot;bgabutton bgabutton_blue&amp;quot;&amp;gt;&amp;lt;span&amp;gt;My blue button&amp;lt;/span&amp;gt;&amp;lt;/a&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;a href=&amp;quot;#&amp;quot; id=&amp;quot;my_button_id&amp;quot; class=&amp;quot;bgabutton bgabutton_red bgabutton_big&amp;quot;&amp;gt;&amp;lt;span&amp;gt;My big red button&amp;lt;/span&amp;gt;&amp;lt;/a&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note&#039;&#039;&#039;: To see it in action, check out &#039;&#039;Coloretto&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
=== Button outside of action bar ===&lt;br /&gt;
&lt;br /&gt;
Use addActionButton() method with destination argument set&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
this.addActionButton( &#039;commit_button&#039;, _(&#039;Confirm&#039;), &#039;onConfirm&#039;, &#039;player_board&#039;, true, &#039;red&#039;); &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
in example above the button will be place on object with id &#039;player_board&#039;&lt;br /&gt;
&lt;br /&gt;
== Image loading ==&lt;br /&gt;
&lt;br /&gt;
See also [[Game_art:_img_directory]].&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Be careful&#039;&#039;&#039;: by default, ALL images of your img directory are loaded on a player&#039;s browser when he loads the game. For this reason, don&#039;t let in your img directory images that are not useful, otherwise it&#039;s going to slowdown the game load.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.dontPreloadImage(image_file_name: string)&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Using dontPreloadImage, you tell the interface to not preload a specific image in your img directory.&lt;br /&gt;
&lt;br /&gt;
Example of use:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
this.dontPreloadImage( &#039;cards.png&#039; );&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This is particularly useful if for example you have 2 different themes for a game. To accelerate the loading of the game, you can specify to not preload images corresponding to the other theme.&lt;br /&gt;
&lt;br /&gt;
Another example of use: in &amp;quot;Gosu&amp;quot; game with Kamakor extension, you play with 5 sets of cards among 10 available. Cards images are organized by sets, and we only preload the images corresponding to the 5 current sets with &#039;&#039;&#039;ensureSpecificGameImageLoading( image_file_names_array )&#039;&#039;&#039;.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
// By default, do not preload anything&lt;br /&gt;
this.dontPreloadImage( &#039;cards.png&#039; );&lt;br /&gt;
this.dontPreloadImage( &#039;clan1.png&#039; );&lt;br /&gt;
this.dontPreloadImage( &#039;clan2.png&#039; );&lt;br /&gt;
this.dontPreloadImage( &#039;clan3.png&#039; );&lt;br /&gt;
this.dontPreloadImage( &#039;clan4.png&#039; );&lt;br /&gt;
this.dontPreloadImage( &#039;clan5.png&#039; );&lt;br /&gt;
this.dontPreloadImage( &#039;clan6.png&#039; );&lt;br /&gt;
this.dontPreloadImage( &#039;clan7.png&#039; );&lt;br /&gt;
this.dontPreloadImage( &#039;clan8.png&#039; );&lt;br /&gt;
this.dontPreloadImage( &#039;clan9.png&#039; );&lt;br /&gt;
this.dontPreloadImage( &#039;clan10.png&#039; );&lt;br /&gt;
var to_preload = [];&lt;br /&gt;
for( i in this.gamedatas.clans )&lt;br /&gt;
{&lt;br /&gt;
	var clan_id = this.gamedatas.clans[i];&lt;br /&gt;
	to_preload.push( &#039;clan&#039;+clan_id+&#039;.png&#039; );&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
this.ensureSpecificGameImageLoading( to_preload );&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note:&#039;&#039;&#039; You don&#039;t need to specify to not preload game box images (game_box.png, game_box75.png...) since they are not preloaded by default.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.ensureSpecificGameImageLoading(list: string[])&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
This is oppostive of dontPreloadImage - its ensure specific images is loaded. Note: only makes sense if preload list is empty, otherwise everything is loaded anyway&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;load specific images&#039;&#039;&#039;&lt;br /&gt;
All images that will be preloaded stored in g_img_preload. If you want to override it directly - there is no API, but you can do this in GAME constructor&lt;br /&gt;
&lt;br /&gt;
          g_img_preload = [&#039;tokens.png&#039;, &#039;trains.png&#039;, &#039;loc_plan.png&#039;, &#039;eng.png&#039;, &#039;eng-back.png&#039;];&lt;br /&gt;
&lt;br /&gt;
You can also set it to empty array and call ensureSpecificGameImageLoading() on specific images&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Sounds ==&lt;br /&gt;
&lt;br /&gt;
Add a custom sound and make it load with your interface:&lt;br /&gt;
&lt;br /&gt;
Add this in your template (.tpl) file:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;audio id=&amp;quot;audiosrc_&amp;lt;gamename&amp;gt;_&amp;lt;yoursoundname&amp;gt;&amp;quot; src=&amp;quot;{GAMETHEMEURL}img/&amp;lt;gamename&amp;gt;_&amp;lt;yoursoundname&amp;gt;.mp3&amp;quot; preload=&amp;quot;none&amp;quot; autobuffer&amp;gt;&amp;lt;/audio&amp;gt;&lt;br /&gt;
&amp;lt;audio id=&amp;quot;audiosrc_o_&amp;lt;gamename&amp;gt;_&amp;lt;yoursoundname&amp;gt;&amp;quot; src=&amp;quot;{GAMETHEMEURL}img/&amp;lt;gamename&amp;gt;_&amp;lt;yoursoundname&amp;gt;.ogg&amp;quot; preload=&amp;quot;none&amp;quot; autobuffer&amp;gt;&amp;lt;/audio&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note: this is a requirement to provide both a mp3 and a ogg file with the names &amp;lt;code&amp;gt;&amp;lt;gamename&amp;gt;_&amp;lt;yoursoundname&amp;gt;[.ogg][.mp3]&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Play the sound (from your .js file):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
playSound(&#039;&amp;lt;gamename&amp;gt;_&amp;lt;yoursoundname&amp;gt;&#039;);   // do not add &#039;this.&#039; - its a global function&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Disable the standard &amp;quot;move&amp;quot; sound for this move (to replace it with your custom sound):&lt;br /&gt;
&lt;br /&gt;
Add this to your notification handler:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
this.disableNextMoveSound();&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note: it only disable the sound for the next move.&lt;br /&gt;
&lt;br /&gt;
== Title bar and states ==&lt;br /&gt;
&lt;br /&gt;
=== Client states ===&lt;br /&gt;
&lt;br /&gt;
Client states is a way to simulate the state transition but without actually going&lt;br /&gt;
to server. It is usefull when you need to ask user multiple questions before you&lt;br /&gt;
send things to server&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.setClientState(newState: string, args: object)&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
     this.setClientState(&amp;quot;client_playerPicksLocation&amp;quot;, {&lt;br /&gt;
                               descriptionmyturn : _(&amp;quot;${you} must select location&amp;quot;),&lt;br /&gt;
                           });&lt;br /&gt;
&lt;br /&gt;
For more information see [[BGA_Studio_Cookbook#Multi_Step_Interactions:_Select_Worker.2FPlace_Worker_-_Using_Client_States]]&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.restoreServerGameState()&#039;&#039;&#039;&lt;br /&gt;
If you are in client state it will restore the current server state (cheap undo)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.on_client_state&#039;&#039;&#039;&lt;br /&gt;
Boolean indicating that we are in client state&lt;br /&gt;
&lt;br /&gt;
=== Title bar ===&lt;br /&gt;
If you simply want to show something in title bar you can do it directly &lt;br /&gt;
     $(&#039;pagemaintitletext&#039;).innerHTML = text;&lt;br /&gt;
&lt;br /&gt;
This however will not work with parameters and will not draw You in color,&lt;br /&gt;
if you want to do proper args rendering use method below&lt;br /&gt;
&lt;br /&gt;
;&#039;&#039;&#039;this.removeActionButtons()&#039;&#039;&#039;&lt;br /&gt;
Removes all buttons from title bar&lt;br /&gt;
&lt;br /&gt;
;&#039;&#039;&#039;this.updatePageTitle()&#039;&#039;&#039;&lt;br /&gt;
:This function allows to update the current page title and turn description according to the game state arguments. If the current game state description this.gamedatas.gamestate.descriptionmyturn is modified before calling this function it allows to update the turn description without changing state. This will handle arguments substitutions properly.&lt;br /&gt;
&lt;br /&gt;
Note: this functional also will calls this.onUpdateActionButtons, if you want different buttons then state defaults, use method in example to replace them, if it becomes too clumsy use client states (see above)&lt;br /&gt;
&lt;br /&gt;
Example from Terra Mystica:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
onClickFavorTile: function( evt ) {&lt;br /&gt;
    ...&lt;br /&gt;
    if ( ... ) {&lt;br /&gt;
        this.gamedatas.gamestate.descriptionmyturn = _(&#039;Special action: &#039;) + _(&#039;Advance 1 space	on a Cult track&#039;);&lt;br /&gt;
        this.updatePageTitle();&lt;br /&gt;
        this.removeActionButtons();&lt;br /&gt;
        this.addActionButton( ... );&lt;br /&gt;
         ...&lt;br /&gt;
        return;&lt;br /&gt;
    }&lt;br /&gt;
    ...&lt;br /&gt;
&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== User preferences ==&lt;br /&gt;
&#039;&#039;&#039;this.getGameUserPreference(pref_id)&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Return the value of a user preference. It will return the value currently selected in the select combo box, in the top-right menu.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.setGameUserPreference(pref_id, value)&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Programmatically change a user preference. It will have the same effect as if the player changed the value in the select combo box, in the top-right menu.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.onGameUserPreferenceChanged&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
A callback you can define if you want to be notified when a user changes a user preference.&lt;br /&gt;
&lt;br /&gt;
Example:&amp;lt;pre&amp;gt;&lt;br /&gt;
onGameUserPreferenceChanged: function(pref_id, pref_value) {&lt;br /&gt;
  switch (pref_id) {&lt;br /&gt;
    case 201: &lt;br /&gt;
      document.getElementsByTagName(&#039;html&#039;)[0].classList.toggle(&#039;dark-background&#039;, pref_value == 2);&lt;br /&gt;
      break;&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Other useful stuff ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;dojo.hitch&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
With dojo.hitch, you can create a callback function that will run with your game object context whatever happen.&lt;br /&gt;
&lt;br /&gt;
Typical example: display a BGA confirmation dialog with a callback function created with dojo.hitch:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        this.confirmationDialog( _(&#039;Are you sure you want to make this?&#039;), dojo.hitch( this, function() {&lt;br /&gt;
            this.bgaPerformAction(&#039;makeThis&#039;);&lt;br /&gt;
        } ) );   &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In the example above, using dojo.hitch, we ensure that the &amp;quot;this&amp;quot; object will be set when the callback is called.&lt;br /&gt;
&lt;br /&gt;
NOTE: In modern JS there are lambdas that eliminate need for that, the example above will look like this&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        this.confirmationDialog( _(&#039;Are you sure you want to make this?&#039;), () =&amp;gt; this.bgaPerformAction( &#039;makeThis&#039;) );   &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
;&#039;&#039;&#039;onScreenWidthChange()&#039;&#039;&#039;&lt;br /&gt;
:This function can be overridden in your game to manage some resizing on the client side when the browser window is resized. This function is also triggered at load time, so it can be used to adapt to the :viewport size at the start of the game too.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
; this.bRealtime&lt;br /&gt;
: Return true if the game is in realtime. Note that having a distinct behavior in realtime and turn-based should be exceptional.&lt;br /&gt;
&lt;br /&gt;
; g_replayFrom&lt;br /&gt;
: Global contains replay number in live game, it is set to undefined (i.e. not set) when it is not a replay mode, so consequentially the good check is &#039;&#039;&#039;typeof g_replayFrom != &#039;undefined&#039;&#039;&#039;&#039; which returns true if the game is in replay mode &amp;lt;i&amp;gt;during the game&amp;lt;/i&amp;gt; (the game is ongoing but the user clicked &amp;quot;replay from this move&amp;quot; in the log)&lt;br /&gt;
&lt;br /&gt;
; g_archive_mode&lt;br /&gt;
: Returns true if the game is in archive mode &amp;lt;i&amp;gt;after the game&amp;lt;/i&amp;gt; (the game has ended)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
; this.instantaneousMode&lt;br /&gt;
: Returns true during replay/archive mode if animations should be skipped. Only needed if you are doing custom animations. (The BGA-provided animation functions like &amp;lt;i&amp;gt;this.slideToObject()&amp;lt;/i&amp;gt; automatically handle instantaneous mode.)&lt;br /&gt;
: Technically, when you click &amp;quot;replay from move #20&amp;quot;, the system replays the game from the very beginning with moves 0 - 19 happening in instantaneous mode and moves 20+ happening in normal mode.&lt;br /&gt;
&lt;br /&gt;
; g_tutorialwritten&lt;br /&gt;
: Returns an object like the below if the game is in tutorial mode, or undefined otherwise. Tutorial mode is a special case of archive mode where comments have been added to a previous game to teach new players the rules.&lt;br /&gt;
    {&lt;br /&gt;
        author: &amp;quot;91577332&amp;quot;,&lt;br /&gt;
        id: &amp;quot;576&amp;quot;,&lt;br /&gt;
        mode: &amp;quot;view&amp;quot;&lt;br /&gt;
        status: &amp;quot;alpha&amp;quot;&lt;br /&gt;
        version_override: null&lt;br /&gt;
        viewer_id: &amp;quot;84554161&amp;quot;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;getBgaEnvironment(): string&#039;&#039;&#039;&lt;br /&gt;
: Returns &amp;quot;studio&amp;quot; for studio and &amp;quot;prod&amp;quot; for production environment (i.e. where games current runs). Only useful for debbugging hooks.&lt;br /&gt;
Note: alpha server is also &amp;quot;prod&amp;quot;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Category:Studio]]&lt;/div&gt;</summary>
		<author><name>Sguzzer Gunayer</name></author>
	</entry>
	<entry>
		<id>https://en.doc.boardgamearena.com/index.php?title=Game_interface_logic:_Game.js&amp;diff=22734</id>
		<title>Game interface logic: Game.js</title>
		<link rel="alternate" type="text/html" href="https://en.doc.boardgamearena.com/index.php?title=Game_interface_logic:_Game.js&amp;diff=22734"/>
		<updated>2024-09-25T17:49:26Z</updated>

		<summary type="html">&lt;p&gt;Sguzzer Gunayer: /* Sliding */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Studio_Framework_Navigation}}&lt;br /&gt;
&lt;br /&gt;
__TOC__&lt;br /&gt;
&lt;br /&gt;
This is the main file for your game interface. Here you will define:&lt;br /&gt;
&lt;br /&gt;
* Which actions on the page will generate calls to the server.&lt;br /&gt;
* What happens when you get a notification for a change from the server and how it will show in the browser. &lt;br /&gt;
* Setup user interface&lt;br /&gt;
&lt;br /&gt;
== File structure ==&lt;br /&gt;
&lt;br /&gt;
The details of how the file is structured are described below with comments in the code skeleton provided to you.&lt;br /&gt;
&lt;br /&gt;
Here is the basic structure:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;constructor&#039;&#039;&#039;: here you can define global variables for your whole interface.&lt;br /&gt;
* &#039;&#039;&#039;setup&#039;&#039;&#039;: this method is called when the page is refreshed, and sets up the game interface.&lt;br /&gt;
* &#039;&#039;&#039;onEnteringState&#039;&#039;&#039;: this method is called when entering a new game state. You can use it to customize the view for each game state.&lt;br /&gt;
* &#039;&#039;&#039;onLeavingState&#039;&#039;&#039;: this method is called when leaving a game state.&lt;br /&gt;
* &#039;&#039;&#039;onUpdateActionButtons&#039;&#039;&#039;: called on state changes, in order to add action buttons to the status bar. Note: in a multipleactiveplayer state, it will be called when another player has become inactive.&lt;br /&gt;
* &#039;&#039;(utility methods)&#039;&#039;: this is where you can define your utility methods.&lt;br /&gt;
* &#039;&#039;(player&#039;s actions)&#039;&#039;: this is where you can write your handlers for player actions on the interface (example: click on an item).&lt;br /&gt;
* &#039;&#039;&#039;setupNotifications&#039;&#039;&#039;: this method associates notifications with notification handlers. For each game notification, you can trigger a javascript method to handle it and update the game interface.&lt;br /&gt;
* &#039;&#039;(notification handlers)&#039;&#039;: this is where you define the notifications handlers associated with notifications in &#039;&#039;&#039;setupNotifications&#039;&#039;&#039;, above.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
More details:&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;setup(gamedatas: object)            &#039;&#039;&#039;&lt;br /&gt;
This method must set up the game user interface according to current game situation specified in parameters.&lt;br /&gt;
The method is called each time the game interface is displayed to a player, ie:&lt;br /&gt;
&lt;br /&gt;
* when the game starts&lt;br /&gt;
* when a player opens a game in the browser later &lt;br /&gt;
* when a player refreshes the game page (F5)&lt;br /&gt;
* when player does a server side Undo&lt;br /&gt;
&lt;br /&gt;
&amp;quot;gamedatas&amp;quot; argument contains all data retrieved by your &amp;quot;getAllDatas&amp;quot; PHP method and some more.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;onEnteringState(stateName: string, args: { args: any } | null): void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
This method is called each time we enter a new game state.&lt;br /&gt;
You can use this method to perform some user interface changes at this moment.&lt;br /&gt;
To access state arguments passed via calling php arg* method use args?.args.&lt;br /&gt;
Typically you would do something only for active player, using this.isCurrentPlayerActive() check.&lt;br /&gt;
It is also called (for the current game state only) when doing a browser refresh (after the setup method is called).&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Warning&#039;&#039;&#039;: for multipleactiveplayer states:&lt;br /&gt;
the active players are NOT active yet so you must use onUpdateActionButtons to perform the client side operation which depends on a player active/inactive status.&lt;br /&gt;
If you are doing initialization of some structures which do not depend on the active player, you can just replace (this.isCurrentPlayerActive()) with (!this.isSpectator) &lt;br /&gt;
for the main switch in that method.&lt;br /&gt;
&lt;br /&gt;
See more details in [[Your_game_state_machine:_states.inc.php#Difference_between_Single_active_and_Multi_active_states]]&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;onLeavingState(stateName: string): void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
This method is called each time we leave a game state.&lt;br /&gt;
You can use this method to perform some user interface changes at this point (i.e. cleanup).&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;onUpdateActionButtons(stateName: string, args: object | null): void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
In this method you can manage &amp;quot;action buttons&amp;quot; that are displayed in the action status bar and highlight active UI elements.&lt;br /&gt;
To access state arguments passed via calling php arg* method use &#039;&#039;&#039;args&#039;&#039;&#039; parameter. Note: args can be null! For &#039;&#039;&#039;game&#039;&#039;&#039; states and when you don&#039;t supply state args function - it is null.&lt;br /&gt;
This method is called when the active or multiactive player changes. In a classic &amp;quot;activePlayer&amp;quot; state this method is called before the onEnteringState state.&lt;br /&gt;
In multipleactiveplayer state it is a mess. The sequencing of calls depends on whether you get into that state from transitions OR from reloading the whole game (i.e. F5).&lt;br /&gt;
&lt;br /&gt;
See more details in [[Your_game_state_machine:_states.inc.php#Difference_between_Single_active_and_Multi_active_states]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Dojo framework ==&lt;br /&gt;
&lt;br /&gt;
BGA uses the [http://dojotoolkit.org/ Dojo Javascript framework].&lt;br /&gt;
&lt;br /&gt;
The Dojo framework allows us to do complex things more easily. The BGA framework uses Dojo extensively.&lt;br /&gt;
&lt;br /&gt;
To implement a game, you only need to use a few parts of the Dojo framework. All the Dojo methods you need are described on this page.&lt;br /&gt;
&lt;br /&gt;
== Javascript minimization (after July 2020) ==&lt;br /&gt;
&lt;br /&gt;
For performance reasons, when deploying a game the javascript code is minimized using &#039;&#039;&#039;terser&#039;&#039;&#039; (https://github.com/terser/terser). This minifier works with modern javascript syntax. From your project &amp;quot;Manage game&amp;quot; page, you can now test a minified version of your javascript on the studio (and revert to the original).&lt;br /&gt;
&lt;br /&gt;
NB: it has been reported that there is an issue with this minifier and percentage values for opacity.&lt;br /&gt;
&lt;br /&gt;
== Accessing Players Information ==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.player_id: number&#039;&#039;&#039;&lt;br /&gt;
id of the player who is looking at the game. The player may not be part of the game (i.e. spectator)&lt;br /&gt;
  if (notif.args.player_id == this.player_id) {&lt;br /&gt;
    ...&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.isSpectator: boolean&#039;&#039;&#039;&lt;br /&gt;
Flag set to true if the user at the table is a spectator (not a player).&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    if (this.isSpectator) {&lt;br /&gt;
        this.player_color = &#039;ffffff&#039;;&lt;br /&gt;
    } else {&lt;br /&gt;
        this.player_color = gamedatas.players[this.player_id].color;&lt;br /&gt;
    }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note: If you want to hide an element from spectators, you should use [[Game_interface_stylesheet:_yourgamename.css#spectatorMode|CSS &#039;spectatorMode&#039; class]].&lt;br /&gt;
&lt;br /&gt;
You may consider making a function like this, to detect if the game is in a read-only state (i.e. non-interactive):&lt;br /&gt;
  // Returns true for spectators, instant replay (during game), archive mode (after game end)&lt;br /&gt;
  isReadOnly: function () {&lt;br /&gt;
    return this.isSpectator || typeof g_replayFrom != &#039;undefined&#039; || g_archive_mode;&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.gamedatas: object&#039;&#039;&#039;&lt;br /&gt;
Contains the initial set of data to init the game, created at game start or by game refresh (F5).&lt;br /&gt;
You can update it as needed to keep an up-to-date reference of the game on the client side if you need it, however most of the time this is unnecessary.&lt;br /&gt;
&lt;br /&gt;
Note: In hotseat mode, the framework does not keep this.gamedatas of hotseat players and shares the same set as the main player to store data.&lt;br /&gt;
&lt;br /&gt;
Note: be careful when you update this data structurally, many framework functions expect data to be certain way and they will break if they see something else.&lt;br /&gt;
&lt;br /&gt;
Typical example of accessing player&#039;s info&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
for (var player_id in this.gamedatas.players) { &lt;br /&gt;
    var playerInfo = this.gamedatas.players [player_id];&lt;br /&gt;
    var c = playerInfo.color;&lt;br /&gt;
    var name = playerInfo.name;&lt;br /&gt;
    // do something &lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.isCurrentPlayerActive(): boolean&#039;&#039;&#039;&lt;br /&gt;
Returns true if the player on whose browser the code is running is currently active (it&#039;s his turn to play). Note: see remarks above about usage of this function inside onEnteringState method.&lt;br /&gt;
  if (this.isCurrentPlayerActive()) ...&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.getActivePlayerId(): number&#039;&#039;&#039;&lt;br /&gt;
Return the ID of the active player, or null if we are not in an &amp;quot;activeplayer&amp;quot; type state.&lt;br /&gt;
  if (this.player_id == this.getActivePlayerId()) ...&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.getActivePlayers(): number[]&#039;&#039;&#039;&lt;br /&gt;
Return an array with the IDs of players who are currently active (or an empty array if there are none).&lt;br /&gt;
&lt;br /&gt;
== Accessing and manipulating the DOM ==&lt;br /&gt;
&lt;br /&gt;
=== Element by Id ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;$(elementId: ElementOrId)&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
The $ function is used to get an HTML element using its &amp;quot;id&amp;quot; attribute.&lt;br /&gt;
&lt;br /&gt;
Example: modify the content of a &amp;quot;span&amp;quot; element:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
In your HTML code:&lt;br /&gt;
   &amp;lt;span id=&amp;quot;a_value_in_the_game_interface&amp;quot;&amp;gt;1234&amp;lt;/span&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In your Javascript code:&lt;br /&gt;
   $(&#039;a_value_in_the_game_interface&#039;).innerHTML = &amp;quot;9999&amp;quot;;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Note: It is safe to use if you don&#039;t know if variable is string (id of element) or element itself, i.e. &lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  foo: function(card) {&lt;br /&gt;
       card = $(card); // now its node, no need to write if (typeof card === &#039;string&#039;) ...&lt;br /&gt;
       // but its good idea to check for null here&lt;br /&gt;
       ...&lt;br /&gt;
  }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;getElementById(elementId: string)&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Note: $() is the standard method to access some HTML element with the BGA Framework. You can use &#039;&#039;&#039;getElementById&#039;&#039;&#039; but it is longer to type and less handy as it does not do some checks.&lt;br /&gt;
&lt;br /&gt;
=== Style ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;dojo.style(node: ElementOrId, styleName: string, styleValue: any): void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
With dojo.style you can modify the CSS property of any HTML element in your interface.&lt;br /&gt;
&lt;br /&gt;
Examples:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
     // Make an element disappear&lt;br /&gt;
     dojo.style( &#039;my_element&#039;, &#039;display&#039;, &#039;none&#039; );&lt;br /&gt;
&lt;br /&gt;
     // Give an element a 2px border&lt;br /&gt;
     dojo.style( &#039;my_element&#039;, &#039;borderWidth&#039;, &#039;2px&#039; );&lt;br /&gt;
&lt;br /&gt;
     // Change the background position of an element&lt;br /&gt;
     // (very practical when you are using CSS sprites to transform an element to another)&lt;br /&gt;
     dojo.style( &#039;my_element&#039;, &#039;backgroundPosition&#039;, &#039;-20px -50px&#039; );&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note: if you have to modify several CSS properties of an element, or if you have a complex CSS transformation to do, you should consider using dojo.addClass/dojo.removeClass (see below).&lt;br /&gt;
&lt;br /&gt;
You can also use object to set multiple values&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
dojo.setStyle(&amp;quot;thinger&amp;quot;, {&lt;br /&gt;
  &amp;quot;opacity&amp;quot;: 0.5,&lt;br /&gt;
  &amp;quot;border&amp;quot;: &amp;quot;3px solid black&amp;quot;,&lt;br /&gt;
  &amp;quot;height&amp;quot;: &amp;quot;300px&amp;quot;&lt;br /&gt;
});&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.addStyleToClass(cssClassName: string, styleName: string, styleValue: any):&#039;&#039;&#039; &#039;&#039;&#039;void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Same as dojo.style(), but for all the nodes set with the specified cssClassName&lt;br /&gt;
Equivalent of &lt;br /&gt;
  &lt;br /&gt;
  dojo.query(`.${aclass}`).style(styleName, styleValue)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
dojo.query(&amp;quot;#baz &amp;gt; div&amp;quot;).style({&lt;br /&gt;
  opacity:0.75,&lt;br /&gt;
  fontSize:&amp;quot;13pt&amp;quot;&lt;br /&gt;
});&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Vanilla JS style&#039;&#039;&#039;&lt;br /&gt;
  $(&#039;my_element&#039;).style.display=&#039;none&#039;; // set&lt;br /&gt;
  var display = $(&#039;my_element&#039;).style.display; // get&lt;br /&gt;
  $(&#039;my_element&#039;).style.removeProperty(&#039;display&#039;); // remove&lt;br /&gt;
&lt;br /&gt;
=== Classes ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;dojo.addClass(node: ElementOrId, classes: string): void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;dojo.removeClass(node: ElementOrId, classes: string): void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;dojo.hasClass(node: ElementOrId, aclass: string): void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;dojo.toggleClass(node: ElementOrId, aclass: string): void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
In many situations, many small CSS property updates can be replaced by a CSS class change (i.e., you add a CSS class to your element instead of applying all modifications manually).&lt;br /&gt;
&lt;br /&gt;
Advantages are:&lt;br /&gt;
* All your CSS stuff remains in your CSS file.&lt;br /&gt;
* You can add/remove a list of CSS modifications with a simple function and without error.&lt;br /&gt;
* You can test whether you applied the CSS to an element with the &#039;&#039;&#039;dojo.hasClass&#039;&#039;&#039; method.&lt;br /&gt;
&lt;br /&gt;
Example from &#039;&#039;Reversi&#039;&#039;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    // We add &amp;quot;possibleMove&amp;quot; to an element&lt;br /&gt;
    dojo.addClass( &#039;square_&#039;+x+&#039;_&#039;+y, &#039;possibleMove&#039; );&lt;br /&gt;
&lt;br /&gt;
    // In our CSS file, the class is defined as:&lt;br /&gt;
    .possibleMove {&lt;br /&gt;
      background-color: white;&lt;br /&gt;
      opacity: 0.2;&lt;br /&gt;
      filter:alpha(opacity=20); /* For IE8 and earlier */  &lt;br /&gt;
      cursor: pointer;  &lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
     // So we&#039;ve applied 4 CSS property changes in one line of code.&lt;br /&gt;
&lt;br /&gt;
     // ... and when we need to check if a square is a possible move on the client side:&lt;br /&gt;
     if( dojo.hasClass( &#039;square_&#039;+x+&#039;_&#039;+y, &#039;possibleMove&#039; ) )&lt;br /&gt;
     { ... }&lt;br /&gt;
&lt;br /&gt;
     // ... and if we want to remove all possible moves in one line of code (see &amp;quot;dojo.query&amp;quot; method):&lt;br /&gt;
     dojo.query( &#039;.possibleMove&#039; ).removeClass( &#039;possibleMove&#039; );&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Vanilla JS classList&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
This is the only exception where dojo versions are better&lt;br /&gt;
  // add class&lt;br /&gt;
  $(token_id).classList.addClass(&#039;possibleMove&#039;);&lt;br /&gt;
  // remove class&lt;br /&gt;
  $(token_id).classList.removeClass(&#039;possibleMove&#039;);&lt;br /&gt;
  // add 2 classes&lt;br /&gt;
  const myclasses = [&#039;a&#039;,&#039;b&#039;];&lt;br /&gt;
  $(token_id).classList.addClass(...myclasses);&lt;br /&gt;
  // add classes to query result&lt;br /&gt;
  document.querySelectorAll(&amp;quot;.hand .card&amp;quot;).forEach((node)=&amp;gt;node.classList.addClass(&#039;possibleMove&#039;));&lt;br /&gt;
&lt;br /&gt;
=== Attributes ===&lt;br /&gt;
&lt;br /&gt;
;dojo.attr&lt;br /&gt;
&lt;br /&gt;
With dojo.attr you can access or change the value of an attribute or property of any HTML element in your interface.&lt;br /&gt;
&lt;br /&gt;
Exemple:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
     // Get the title of a node&lt;br /&gt;
     var title = dojo.attr( id, &#039;title&#039; );&lt;br /&gt;
     // Change the height of a node&lt;br /&gt;
     dojo.attr( &#039;img_growing_tree&#039;, &#039;height&#039;, 100 );&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Vanilla JS attr&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
   $(token).id=new_id; // set attr for &amp;quot;id&amp;quot;&lt;br /&gt;
   var id = $(token).id; // get&lt;br /&gt;
&lt;br /&gt;
=== Queries ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;dojo.query(cssSelector: string): Element[]&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
With dojo.query, you can query a bunch of HTML elements with a single function, with a &amp;quot;CSS selector&amp;quot; style.&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
     // All elements with class &amp;quot;possibleMove&amp;quot;:&lt;br /&gt;
     var elements = dojo.query( &#039;.possibleMove&#039; );&lt;br /&gt;
&lt;br /&gt;
     // Count number of tokens (i.e., elements of class &amp;quot;token&amp;quot;) on the board (i.e., the element with id &amp;quot;board&amp;quot;):&lt;br /&gt;
     dojo.query( &#039;#board .token&#039; ).length;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
But what is really cool with dojo.query is that you can combine it with almost all methods above.&lt;br /&gt;
&lt;br /&gt;
Examples:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
     // Trigger a method when the mouse enter in any element with class &amp;quot;meeple&amp;quot;:&lt;br /&gt;
     dojo.query( &#039;.meeple&#039; ).connect( &#039;onmouseenter&#039;, this, &#039;myMethodToTrigger&#039; );&lt;br /&gt;
&lt;br /&gt;
     // Hide all meeples who are on the board&lt;br /&gt;
     dojo.query( &#039;#board .meeple&#039; ).style( &#039;display&#039;, &#039;none&#039; );&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Vanilla JS query&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
  var cards=document.querySelectorAll(&amp;quot;.hand .card&amp;quot;);// all cards in all hands&lt;br /&gt;
  var cards=$(&#039;hand&#039;).querySelectorAll(&amp;quot;.card&amp;quot;);// all cards in specific hand&lt;br /&gt;
  var card=document.querySelector(&amp;quot;.hand .card&amp;quot;);// first card or null if none (super handy)&lt;br /&gt;
&lt;br /&gt;
=== Creating and Destroying elements ===&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;dojo.empty(node: ElementOrId)&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Remove all children of the node element&lt;br /&gt;
   dojo.empty(&#039;my_hand&#039;);&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;dojo.destroy(node: ElementOrId)&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Remove the element&lt;br /&gt;
   dojo.destroy(&#039;my_token&#039;);&lt;br /&gt;
&lt;br /&gt;
   dojo.query(&amp;quot;.green&amp;quot;, mynode).forEach(dojo.destroy); // this remove all subnode of class green from mynode&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;dojo.create(tag: string, attributes?: obj, parent?: ElementOrId): Element&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Create element&lt;br /&gt;
&lt;br /&gt;
    dojo.create(&amp;quot;div&amp;quot;, { class: &amp;quot;yellow_arrow&amp;quot; }, parent); // this creates div with class yellow_array and places it in &amp;quot;parent&amp;quot;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.format_block(name: string, args: object): string&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
This bga function that takes global var from template file and substitute variables, typical use would be&lt;br /&gt;
&lt;br /&gt;
                var player = gamedatas.players[player_id];&lt;br /&gt;
                var div = this.format_block(&#039;jstpl_player_board&#039;, player ); // var jstpl_player_board = ... is defined in .tpl file &lt;br /&gt;
Note: result is trimmed&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.format_string(name: string, args: object): string&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
This bga function just substitute variables in a string, i.e.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
     var div = this.format_string(&#039;&amp;lt;div color=&amp;quot;${player_color}&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&#039;, {player_color: &#039;#ff0000&#039;} );&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Note: result is trimmed&lt;br /&gt;
&lt;br /&gt;
Note: this can be replaced by using backquoted string now: &lt;br /&gt;
     const player_color =  &#039;#ff0000&#039;;&lt;br /&gt;
&lt;br /&gt;
    const div = ``;&lt;br /&gt;
&#039;&#039;&#039;this.format_string_recursive&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
This bga function is similar to this.format_string but is capable of processing recursive argument structures and translations. It is used to format server notifications.&lt;br /&gt;
&lt;br /&gt;
TODO: find better place for these function docs&lt;br /&gt;
&lt;br /&gt;
=== Moving elements ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;dojo.place(node: string | Element, refNode: ElementOrId, pos?: string | number): Element&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
dojo.place is the best function to insert HTML code somewhere in your game interface without breaking something. It is much better to use than the &#039;&#039;&#039;innerHTML=&#039;&#039;&#039; method if you must insert HTML tags and not only values.&lt;br /&gt;
&lt;br /&gt;
node: can be a string or a DOM node. If it is a string starting with “&amp;lt;”, it is assumed to be an HTML fragment, which will be created. Otherwise it is assumed to be an id of a DOM node. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
     // Insert your HTML code as a child of a container element&lt;br /&gt;
     dojo.place( &amp;quot;&amp;lt;div class=&#039;foo&#039;&amp;gt;&amp;lt;/div&amp;gt;&amp;quot;, &amp;quot;your_container_element_id&amp;quot; );&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
pos: optional argument. Can be a number or one of the following strings: “before”, “after”, “replace”, “only”, “first”, or “last”. If omitted, “last” is assumed.&lt;br /&gt;
&lt;br /&gt;
* &amp;quot;replace&amp;quot;: replace the container element with my_node element&lt;br /&gt;
* &amp;quot;first&amp;quot;: places the node as a child of the reference node. The node is placed as the first child.&lt;br /&gt;
* &amp;quot;last&amp;quot; (default): places the node as a child of the reference node. The node is placed as the last child.&lt;br /&gt;
* &amp;quot;before&amp;quot;: places the node right before the reference node.&lt;br /&gt;
* &amp;quot;after&amp;quot;: places the node right after the reference node.&lt;br /&gt;
* &amp;quot;only&amp;quot;: replaces all children of the reference node with the node.&lt;br /&gt;
&lt;br /&gt;
this parameter can be a positive integer. In this case, the node will be placed as a child of the reference node with this number (counting from 0). If the number is more than number of children, the node will be appended to the reference node making it the last child. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
     // Replace all children of container with my_node &lt;br /&gt;
     dojo.place( $(&#039;my_node&#039;), &amp;quot;your_container_element_id&amp;quot;, &amp;quot;only&amp;quot; );&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
See also full doc on dojo.place: [https://dojotoolkit.org/reference-guide/1.7/dojo/place.html]&lt;br /&gt;
&lt;br /&gt;
Usually, when you want to insert some piece of HTML in your game interface, you should use &amp;quot;[[Game_layout:_view_and_template:_yourgamename.view.php_and_yourgamename_yourgamename.tpl#Javascript_templates|Javascript templates]]&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
But you can also relocate elements like that. Note: it won&#039;t animate if you do that.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.placeOnObject(mobile_obj: ElementOrId, target_obj: ElementOrId): void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
places mobile_obj on target_obj, set the absolute positions and centers the mobile_obj on target_obj,&lt;br /&gt;
effect is immediate&lt;br /&gt;
&lt;br /&gt;
This is not really an animation, but placeOnObject is frequently used before starting an animation.&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  // (We just created an object &amp;quot;my_new_token&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
  // Place the new token on current player board&lt;br /&gt;
  this.placeOnObject( &amp;quot;my_new_token&amp;quot;, &amp;quot;overall_player_board_&amp;quot;+this.player_id );&lt;br /&gt;
  &lt;br /&gt;
  // Then slide it to its position on the board&lt;br /&gt;
  this.slideToObject( &amp;quot;my_new_token&amp;quot;, &amp;quot;a_place_on_board&amp;quot; ).play();&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.placeOnObjectPos(mobile_obj: ElementOrId, target_obj: ElementOrId, target_x: number, target_y: number): void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
This method works exactly like placeOnObject, except than you can specify some (x,y) coordinates (in px). This way, the center of &amp;quot;mobile_obj&amp;quot; will be placed to the specified x,y position relatively to the center of &amp;quot;target_obj&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Note: the placement works differently from this.slideToObjectPos&#039;&#039;, since coordinates are calculated based on the center of objects.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.attachToNewParent(mobile_obj: ElementOrId, target_obj: ElementOrId): void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
With this method, you change the HTML parent of &amp;quot;mobile_obj&amp;quot; element without moving it. &lt;br /&gt;
&amp;quot;target_obj&amp;quot; is the new parent of this element. The beauty of &lt;br /&gt;
attachToNewParent is that the mobile_obj element DOES NOT MOVE during this process.&lt;br /&gt;
&lt;br /&gt;
What happens is that the method calculate a relative position of mobile_obj to make sure it does not move after the HTML parent changes.&lt;br /&gt;
&lt;br /&gt;
Why using this method?&lt;br /&gt;
&lt;br /&gt;
Changing the HTML parent of an element can be useful for the following reasons:&lt;br /&gt;
* When the HTML parent moves, all its child are moving with them. If some game elements is no more linked with a parent HTML object, you may want to attach it to another place.&lt;br /&gt;
* The z_order (vertical order of display) depends on the position in the DOM, so you may need to change the parent of some game elements when they are moving in your game area.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;CAREFUL&#039;&#039;&#039;: this function destroys original object and places a clone onto a new parent, this will break all references to this HTML element (ex: dojo.connect).&lt;br /&gt;
If you need version that does not destroy the object but the same otherwise see [[BGA_Studio_Cookbook#Attach_to_new_parent_without_destroying_the_object]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Animations ==&lt;br /&gt;
&lt;br /&gt;
===Dojo Animations===&lt;br /&gt;
&lt;br /&gt;
BGA animations is based on Dojo Animation ([http://dojotoolkit.org/documentation/tutorials/1.8/animation/ see tutorial here]).&lt;br /&gt;
&lt;br /&gt;
However, most of the time, you can just use methods below, which are built on top of Dojo Animation.&lt;br /&gt;
&lt;br /&gt;
Note: one interesting method from Dojo that could be useful from time to time is &amp;quot;Dojo.Animation&amp;quot;. It allows you to make any CSS property &amp;quot;slide&amp;quot; from one value to another.&lt;br /&gt;
&lt;br /&gt;
Note 2: the slideTo methods are not compatible with CSS transform (scale, zoom, rotate...). If possible, avoid using CSS transform on nodes that are being slided. Eventually, the only possible solution to make these 2 compatible is to disable all CSS transform properties, use slideToObjectPos/placeOnObjectPos, and then apply them again.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Sliding===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.slideToObject(mobile_obj: ElementOrId, target_obj: ElementOrId, duration?: number, delay?: number): Animation&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
You can use slideToObject to &amp;quot;slide&amp;quot; an element to a target position.&lt;br /&gt;
&lt;br /&gt;
Sliding element on the game area is the recommended and the most used way to animate your game interface. Using slides allow players to figure out what is happening on the game, as if they were playing with the real boardgame.&lt;br /&gt;
&lt;br /&gt;
The parameters are:&lt;br /&gt;
* mobile_obj: the ID of the object to move. This object must be &amp;quot;relative&amp;quot; or &amp;quot;absolute&amp;quot; positioned.&lt;br /&gt;
* target_obj: the ID of the target object. This object must be &amp;quot;relative&amp;quot; or &amp;quot;absolute&amp;quot; positioned. Note that it is not mandatory that mobile_obj and target_obj have the same size. If their size are different, the system slides the center of mobile_obj to the center of target_obj.&lt;br /&gt;
* duration: (optional) defines the duration in millisecond of the slide. The default is 500 milliseconds.&lt;br /&gt;
* delay: (optional). If you defines a delay, the slide will start only after this delay. This is particularly useful when you want to slide several object from the same position to the same position: you can give a 0ms delay to the first object, a 100ms delay to the second one, a 200ms delay to the third one, ... this way they won&#039;t be superposed during the slide.&lt;br /&gt;
&lt;br /&gt;
BE CAREFUL: The method returns an dojo.fx animation, so you can combine it with other animation if you want to. It means that you have to call the &amp;quot;play()&amp;quot; method, otherwise the animation WON&#039;T START.&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
   this.slideToObject( &amp;quot;some_token&amp;quot;, &amp;quot;some_place_on_board&amp;quot; ).play();&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.slideToObjectPos(mobile_obj: ElementOrId, target_obj: ElementOrId, target_x: number, target_y: number, duration?: number, delay?: number): Animation&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
This method does exactly the same as &amp;quot;slideToObject&amp;quot;, except than you can specify some (x,y) coordinates. This way, &amp;quot;mobile_obj&amp;quot; will slide to the specified x,y position relatively to &amp;quot;target_obj&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
Example: slide a token to some place on the board, 10 pixels from the top:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
   this.slideToObjectPos( &amp;quot;some_token&amp;quot;, &amp;quot;some_place_on_board&amp;quot;, 0, 10 ).play();&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.slideTemporaryObject(mobile_obj_html: string, parent: ElementOrId, from: ElementOrId, to: ElementOrId, duration?: number, delay?: number): Animation&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
This method is useful when you want to slide a temporary HTML object from one place to another. As this object does not exists before the animation and won&#039;t remain after, it could be complex to create this object (with dojo.place), to place it at its origin (with placeOnObject) to slide it (with slideToObject) and to make it disappear at the end.&lt;br /&gt;
&lt;br /&gt;
slideTemporaryObject does all of this for you:&lt;br /&gt;
* mobile_obj_html is a piece of HTML code that represent the object to slide.&lt;br /&gt;
* parent is the ID of an HTML element of your interface that will be the parent of this temporary HTML object.&lt;br /&gt;
* from is the ID of the origin of the slide.&lt;br /&gt;
* to is the ID of the target of the slide.&lt;br /&gt;
* duration/delay works exactly like in &amp;quot;slideToObject&amp;quot;&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
this.slideTemporaryObject( &#039;&amp;lt;div class=&amp;quot;token_icon&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&#039;, &#039;tokens&#039;, &#039;my_origin_div&#039;, &#039;my_target_div&#039; ).play();&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Destroy===&lt;br /&gt;
&#039;&#039;&#039;this.slideToObjectAndDestroy(mobile_obj: ElementOrId, target_obj: ElementOrId, duration?: number, delay?: number): void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
This method is a handy shortcut to slide an existing HTML object to some place then destroy it upon arrival. It can be used for example to move a victory token or a card from the board to the player panel to show that the player earns it, then destroy it when we don&#039;t need to keep it visible on the player panel.&lt;br /&gt;
&lt;br /&gt;
It works the same as this.slideToObject and takes the same arguments, but it starts the animation. &lt;br /&gt;
&lt;br /&gt;
CAREFUL: Make sure nothing is creating the same object at the same time the animation is running, because this will cause some random disappearing effects&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
this.slideToObjectAndDestroy( &amp;quot;some_token&amp;quot;, &amp;quot;some_place_on_board&amp;quot;, 1000, 0 );&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.fadeOutAndDestroy( node: string | Element, duration?: number, delay?: number):&#039;&#039;&#039; &#039;&#039;&#039;void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
This function fade out the target node, then destroy it. Its starts the animation.&lt;br /&gt;
* duration/delay works exactly like in &amp;quot;slideToObject&amp;quot;&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
   this.fadeOutAndDestroy( &amp;quot;a_card_that_must_disappear&amp;quot; );&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
CAREFUL: the HTML node still exists until during few milliseconds, until the fadeOut has been completed.&lt;br /&gt;
Make sure nothing is creating same object at the same time as animation is running, because you will be some random dissapearing effects&lt;br /&gt;
&lt;br /&gt;
===Rotating elements===&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
This example combines &amp;quot;Dojo.Animation&amp;quot; method and a CSS property transform that allow you to rotate the element.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
// node is Element we rotating&lt;br /&gt;
		    var animation = new dojo.Animation({&lt;br /&gt;
			    curve: [fromDegree, toDegree],&lt;br /&gt;
			    onAnimate: (v) =&amp;gt; {&lt;br /&gt;
				    node.style.transform = &#039;rotate(&#039; + v + &#039;deg)&#039;;&lt;br /&gt;
			    } &lt;br /&gt;
		    });&lt;br /&gt;
		    &lt;br /&gt;
		    animation.play();  &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
BGA has its own interface to rotate&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.rotateTo(node: string | Element, degree: number): void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
It starts the animation, and stored the rotation degree in the class, so next time you rotate object - it is additive.&lt;br /&gt;
There is no animation hooks in this one, if you need to change any parameters use dojo animation above.&lt;br /&gt;
&lt;br /&gt;
There is also &#039;&#039;&#039;rotateInstantTo&#039;&#039;&#039; with same signature which does not animate&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Animation Callbacks===&lt;br /&gt;
&lt;br /&gt;
If you wish to run some code only after an animation has completed you can do this by linking a callback method to &#039;onEnd&#039;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
var animation_id = this.slideToObject( mobile_obj, target_obj, 500 );&lt;br /&gt;
dojo.connect(animation_id, &#039;onEnd&#039;, () =&amp;gt; {&lt;br /&gt;
   // do something here&lt;br /&gt;
});&lt;br /&gt;
animation_id.play();&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If you wish to call a second animation after the first (rather than general code) then you can use a dojo animation chain (see tutorial referenced above).&lt;br /&gt;
&lt;br /&gt;
== Players input ==&lt;br /&gt;
&lt;br /&gt;
=== Connecting ===&lt;br /&gt;
&#039;&#039;&#039;dojo.connect(element: Element, event: string, context: object, method: eventHandler): any&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;dojo.connect(element: Element, event: string, hander: eventHandler): any&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Used to associate a player event with one of your notification methods.&lt;br /&gt;
&lt;br /&gt;
Example: associate a click on an element (&amp;quot;my_element&amp;quot;) with one of our methods (&amp;quot;onClickOnMyElement&amp;quot;):&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
      dojo.connect( $(&#039;my_element&#039;), &#039;onclick&#039;, this, &#039;onClickOnMyElement&#039; );&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Same idea but base on query (i.e. all element of &#039;pet&#039; class)&lt;br /&gt;
      dojo.query(&amp;quot;.pet&amp;quot;).connect(&#039;onclick&#039;, this, &#039;onPet&#039;);&lt;br /&gt;
&lt;br /&gt;
Note: if you need to disconnect the handler you have to store handler returned from this method, i.e.&lt;br /&gt;
   &lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    var handler = dojo.connect(...);&lt;br /&gt;
    ...&lt;br /&gt;
    dojo.disconnect(handler);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If you don&#039;t store the handler - you have to destroy the object to disconnect it&lt;br /&gt;
&lt;br /&gt;
Typical function that implements the input handler will look like this&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
onPet: function(event) {&lt;br /&gt;
    var id = event.currentTarget.id;&lt;br /&gt;
    console.log(&#039;onPet &#039; + id);&lt;br /&gt;
    dojo.stopEvent(event);&lt;br /&gt;
    if (this.gamedatas.gamestate.name == &#039;playerTurnPet&#039;) {&lt;br /&gt;
          this.bgaPerformAction(&#039;actPlayPet&#039;, {card: id});&lt;br /&gt;
    } else {&lt;br /&gt;
          this.showMoveUnauthorized();&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.connect(element: ElementOrId, event: string, method: eventHandler): void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Used to associate a player event with one of your notification methods.&lt;br /&gt;
&lt;br /&gt;
      this.connect( $(&#039;my_element&#039;), &#039;onclick&#039;, &#039;onClickOnMyElement&#039; );&lt;br /&gt;
&lt;br /&gt;
Or you can use an in-place handler&lt;br /&gt;
&lt;br /&gt;
      this.connect( $(&#039;my_element&#039;), &#039;onclick&#039;, (e) =&amp;gt; { console.log(&#039;boo&#039;); } );&lt;br /&gt;
&lt;br /&gt;
Note that this function stores the connection handler. That is the only real difference between &#039;&#039;&#039;this.connect&#039;&#039;&#039; and &#039;&#039;&#039;dojo.connect&#039;&#039;&#039;. If you plan to destroy the element you connected, you &#039;&#039;&#039;must&#039;&#039;&#039; call this.disconnect() to prevent memory leaks.&lt;br /&gt;
This function is mainly for permanent objects - if you just want to connect the temp object you should probably not use this method but use dojo.connect which won&#039;t require any clean-up.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.connectClass(cssClassName: string, event: string, method: eventHandler): void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Same as connect(), but for all the nodes set with the specified cssClassName.&lt;br /&gt;
&lt;br /&gt;
	this.connectClass(&#039;pet&#039;, &#039;onclick&#039;, &#039;onPet&#039;);&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.disconnect(element: ElementOrId, event: string): void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Disconnect event handler (previously registered with this.connect or this.connectClass).&lt;br /&gt;
&lt;br /&gt;
   this.disconnect( $(&#039;my_element&#039;), &#039;onclick&#039;);&lt;br /&gt;
&lt;br /&gt;
Note: dynamic connect/disconnect is for advanced cases ONLY, you should always connect elements statically if possible, i.e. in setup() method.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.disconnectAll(): void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Disconnect all previously registed event handlers (registered via this.connect or this.connectClass)&lt;br /&gt;
&lt;br /&gt;
  this.disconnectAll();&lt;br /&gt;
&lt;br /&gt;
=== Actions ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.bgaPerformAction(action: string, args?: object, options: object = { lock: true, checkAction: true }): Promise&amp;lt;void&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Triggers an action on the backend. This is a combination of checkAction and ajaxcall, returning a Promise which resoves when ajaxcall ends.&lt;br /&gt;
&lt;br /&gt;
This method must be used to send a player input to the game server. &#039;&#039;&#039;It should not be triggered programmatically&#039;&#039;&#039;, especially not in loops, in callbacks, in notifications, or in onEnteringState/onUpdateActionButtons/onLeavingState, in order not to create race conditions or break replay game and tutorial features. It should be used only in reaction to a user action in the interface.&lt;br /&gt;
&lt;br /&gt;
* action: name of the action, as it is written in &amp;quot;possibleactions&amp;quot; of the current state.&lt;br /&gt;
* args: an object containing the call parameters to send to the action&lt;br /&gt;
* options: options to tweak the call with some defaults. Default is &amp;lt;code&amp;gt;{ lock: true, checkAction: true }&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Example of a standard call without args:&lt;br /&gt;
  this.bgaPerformAction(&#039;pass&#039;);&lt;br /&gt;
&lt;br /&gt;
Example of a standard call with action args:&lt;br /&gt;
  this.bgaPerformAction(&#039;actPlayCard&#039;, { id: this.selectedCardId });&lt;br /&gt;
&lt;br /&gt;
Example of a call without checking action (because player is inactive in a multiactive state):&lt;br /&gt;
&lt;br /&gt;
 this.bgaPerformAction(&#039;actChangeMind&#039;, {}, { checkAction: false });&lt;br /&gt;
&lt;br /&gt;
Example of a call without lock (because of a special action not directly related to the game flow):&lt;br /&gt;
&lt;br /&gt;
 this.bgaPerformAction(&#039;actSetAutoBid&#039;, { alwaysBidUntil: 500 }, { lock: false, checkAction: false });&lt;br /&gt;
&lt;br /&gt;
Example of call with reaction to exception:&lt;br /&gt;
  this.bgaPerformAction(&#039;actPlayCard&#039;, { id: this.selectedCardId }).catch(()=&amp;gt;{ this.selectedCardId = undefined; });&lt;br /&gt;
&lt;br /&gt;
Example of call with reaction to success:&lt;br /&gt;
  this.bgaPerformAction(&#039;actPlayCard&#039;, { id: this.selectedCardId }).then(()=&amp;gt;{ this.unselectAll(); });&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.ajaxcall(url, parameters, obj_callback, callback, callback_anycase?, ajax_method?: string)&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Note: bgaPerformAction is a simpler way to use ajax calls, ajaxcall stays in the doc for legacy reasons only and should not be used in new projects.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Same warning as &#039;&#039;&#039;this.bgaPerformAction&#039;&#039;&#039; about using on user action only.&lt;br /&gt;
&lt;br /&gt;
* url: the url of the action to perform. For a game, it must be: &amp;quot;/&amp;lt;mygame&amp;gt;/&amp;lt;mygame&amp;gt;/myAction.html&amp;quot;&lt;br /&gt;
* parameters: an array of parameter to send to the game server. &lt;br /&gt;
** Note that &amp;quot;lock: true&amp;quot; must always be specified in this list of parameters in order the interface can be locked during the server call. Cannot use lock: false - to not lock it has to be undefined.&lt;br /&gt;
** Note: Restricted parameter names (please don&#039;t use them):&lt;br /&gt;
*** &amp;quot;action&amp;quot;&lt;br /&gt;
*** &amp;quot;module&amp;quot;&lt;br /&gt;
*** &amp;quot;class&amp;quot;&lt;br /&gt;
* obj_callback: must be set to &amp;quot;this&amp;quot;.&lt;br /&gt;
* callback (non-optional but rarely used): a function to trigger when the server returns result and everything went fine (not used, as all data handling is done via notifications).&lt;br /&gt;
* callback_anycase: (optional) a function to trigger when the server returns ok OR error.  If no error this function is called with parameter value false. If an error occurred, the first parameter will be set to true, the second will contain the error message sent by the PHP back-end, and the third will contain an error code.&lt;br /&gt;
* ajax_method: (optional and rarely used) if you need to send large amounts of data (over 2048 bytes), you can set this parameter to &#039;post&#039; (all lower-case) to send a POST request as opposed to the default GET. This works, but was not officially documented, so only use if you really need to.&lt;br /&gt;
&lt;br /&gt;
Usage:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
this.ajaxcall( &#039;/mygame/mygame/actMyAction.html&#039;, { lock: true, &lt;br /&gt;
   arg1: myarg1, &lt;br /&gt;
   arg2: myarg2&lt;br /&gt;
}, this, (result)=&amp;gt;{} );&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.checkAction(action: string, nomessage?: boolean): boolean &#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Check if player can do the specified action by taking into account:&lt;br /&gt;
* if interface is locked it will return false and show message &amp;quot;An action is already in progress&amp;quot;,  unless nomessage set to true &lt;br /&gt;
* if player is not active it will return false and show message &amp;quot;This is not your turn&amp;quot;, unless nomessage set to true &lt;br /&gt;
* if action is not in list in possible actions (defined by &amp;quot;possibleaction&amp;quot; in current game state) it will return false and show &amp;quot;This move is not authorized now&amp;quot; error (unconditionally).&lt;br /&gt;
* otherwise returns true&lt;br /&gt;
Example:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  function onClickOnGameElement( evt )  {&lt;br /&gt;
     if( this.checkAction( &amp;quot;actMyAction&amp;quot; ) ) {&lt;br /&gt;
        // Do the action&lt;br /&gt;
     }&lt;br /&gt;
  }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.checkPossibleActions(action: string): boolean&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
* this is independent of the player being active, so can be used instead of this.checkAction(). This is particularly useful for multiplayer states when the player is not active in a &#039;player may like to change their mind&#039; scenario. Unlike this.checkAction, this function does NOT take interface locking into account &lt;br /&gt;
&lt;br /&gt;
* if action is not in list in possible actions (defined by &amp;quot;possibleaction&amp;quot; in current game state) it will return false and show &amp;quot;This move is not authorized now&amp;quot; error (unconditionally).&lt;br /&gt;
* otherwise returns true&lt;br /&gt;
&lt;br /&gt;
  function onChangeMyMind( evt )  {&lt;br /&gt;
     if( this.checkPossibleActions( &amp;quot;actMyAction&amp;quot; ) ) {&lt;br /&gt;
        // Do the action&lt;br /&gt;
     }&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.checkLock(nomessage?: boolean): boolean&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
When using &amp;quot;lock: true&amp;quot; in ajax call you can use this function to check if interface is in lock state (it will be locked during server call and notification processing).&lt;br /&gt;
This check can be used to block some other interactions which do not result in ajaxcall or if you want to suppress errors. Note: normally you only need to use this.checkAction(...), this is for advanced cases.&lt;br /&gt;
&lt;br /&gt;
It will also show error unless nomessage is set to true&lt;br /&gt;
&lt;br /&gt;
  function onChangeMyMind( evt )  {&lt;br /&gt;
     if( this.checkLock() ) {&lt;br /&gt;
        // Do the action&lt;br /&gt;
     }&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
== Notifications ==&lt;br /&gt;
&lt;br /&gt;
When something happens on the server side, your game interface Javascript logic received a notification.&lt;br /&gt;
If you have not done so yet check what notification are in [[Main_game_logic:_yourgamename.game.php#Notifications]]&lt;br /&gt;
&lt;br /&gt;
Here&#039;s how you can handle these notifications on the client side.&lt;br /&gt;
&lt;br /&gt;
=== Subscribe to notifications ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;dojo.subscribe(notif_type: string, callback_obj: Object, handler: string|handler)&#039;&#039;&#039;&lt;br /&gt;
* notif_type - notification type/name send by php server&lt;br /&gt;
* callback_obj - usually this&lt;br /&gt;
* handler - if string method of callback_obj with name name is called, when notification is called, with notification object as parameter (see below)&lt;br /&gt;
&lt;br /&gt;
Your Javascript &amp;quot;setupNotifications&amp;quot; method is the place where you can subscribe to notifications from your PHP code.&lt;br /&gt;
&lt;br /&gt;
Here&#039;s how you associate one of your Javascript method to a notification &amp;quot;playDisc&amp;quot; (from Reversi example):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
   setupNotifications: function() {&lt;br /&gt;
      ...&lt;br /&gt;
      dojo.subscribe(&#039;playDisc&#039;, this, &amp;quot;notif_playDisc&amp;quot;);&lt;br /&gt;
   },&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note: the &amp;quot;playDisc&amp;quot; corresponds to the name of the notification you define it in your PHP code, in your &amp;quot;notifyAllPlayers&amp;quot; or &amp;quot;notifyPlayer&amp;quot; method.&lt;br /&gt;
&lt;br /&gt;
Then, you have to define your &amp;quot;notif_playDisc&amp;quot; method:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
   notif_playDisc: function(notif) {&lt;br /&gt;
     // Remove current possible moves (makes the board more clear)&lt;br /&gt;
     dojo.query( &#039;.possibleMove&#039; ).removeClass( &#039;possibleMove&#039; );          &lt;br /&gt;
     this.addDiscOnBoard( notif.args.x, notif.args.y, notif.args.player_id );&lt;br /&gt;
   },&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In a notification handler like our &amp;quot;notif_playDisc&amp;quot; method, you can access all notifications arguments with &amp;quot;notif.args&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&lt;br /&gt;
PHP&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    $this-&amp;gt;notifyAllPlayers( &amp;quot;apples&amp;quot;, clienttranslate(&#039;player takes ${count} apples&#039;), [ &amp;quot;count&amp;quot; =&amp;gt; 3 ] );&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
JavaScript&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    setupNotifications: function() {&lt;br /&gt;
       dojo.subscribe( &#039;apples&#039;, this, &#039;notif_apples&#039; );&lt;br /&gt;
    },&lt;br /&gt;
&lt;br /&gt;
    notif_apples: function(notif) {&lt;br /&gt;
      //You can access the &amp;quot;count&amp;quot; like this:&lt;br /&gt;
       alert(&amp;quot;count = &amp;quot; + notif.args.count);&lt;br /&gt;
    }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== The notification Object received by client ===&lt;br /&gt;
&lt;br /&gt;
When sending a notification on your PHP, the client side will receive an Object with the following attributes:&lt;br /&gt;
&lt;br /&gt;
* type - type of the notification (as passed by php function)&lt;br /&gt;
* log - the log string passed from php notification&lt;br /&gt;
* args - This is the arguments that you passed on your notification method on php&lt;br /&gt;
* bIsTableMsg - is true when you use [[Main_game_logic:_yourgamename.game.php#NotifyAllPlayers|NotifyAllPlayers]] method (false otherwise)&lt;br /&gt;
* channelorig - information about table ID (formatted as : &amp;quot;/table/t[TABLE_NUMBER]&amp;quot;)&lt;br /&gt;
* gamenameorig - name of the game&lt;br /&gt;
* move_id - ID of the move associated with the notification&lt;br /&gt;
* table_id - ID of the table (comes as string)&lt;br /&gt;
* time - UNIX GMT timestamp&lt;br /&gt;
* uid - unique identifier of the notification&lt;br /&gt;
* h - unknown&lt;br /&gt;
&lt;br /&gt;
&#039;&#039; Note that those information were inferred from observation on console log. If an Admin can confirm/correct (and remove this line), you&#039;re welcome :)&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
=== Ignoring notifications ===&lt;br /&gt;
&lt;br /&gt;
Sometimes you need to ignore some notification on client side. You don&#039;t want them to be shown in game log and you don&#039;t want them to be handled.&lt;br /&gt;
&lt;br /&gt;
The most common use case is when a player gets private information. They will receive a specific notification (such as &amp;quot;You received Ace of Heart&amp;quot;), while other players would receive more generic notification (&amp;quot;Player received a card&amp;quot;).&lt;br /&gt;
&lt;br /&gt;
In X.game.php&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        $this-&amp;gt;notifyAllPlayers(&amp;quot;dealCard&amp;quot;, clienttranslate(&#039;${player_name} received a card&#039;), [&lt;br /&gt;
            &#039;player_id&#039; =&amp;gt; $playerId,&lt;br /&gt;
            &#039;player_name&#039; =&amp;gt; $this-&amp;gt;getActivePlayerName()&lt;br /&gt;
        ]);&lt;br /&gt;
&lt;br /&gt;
        $this-&amp;gt;notifyPlayer($playerId, &amp;quot;dealCardPrivate&amp;quot;, clienttranslate(&#039;You received ${cardName}&#039;), [&lt;br /&gt;
            &amp;quot;type&amp;quot; =&amp;gt; $card[&amp;quot;type&amp;quot;],&lt;br /&gt;
            &amp;quot;cardName&amp;quot; =&amp;gt; $this-&amp;gt;getCardName($card[&amp;quot;type&amp;quot;])&lt;br /&gt;
        ]);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The problem with this approach is that the active player will receive two notifications:&lt;br /&gt;
* Player1 received a card&lt;br /&gt;
* You received Ace of Hearts&lt;br /&gt;
&lt;br /&gt;
Hence, notification ignoring.&lt;br /&gt;
&lt;br /&gt;
NOTE: You can think that it would be possible to send such notification to all players except active just by using notifyPlayer and it seems to work. The problem however is that table spectators would miss such notification and their user interface (and game log) wouldn&#039;t be updated. Since there is no way to send notification just to spectators, ignoring the notification (or &amp;quot;filtering&amp;quot;) is the only reasonable solution.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;setIgnoreNotificationCheck(notif_type: string, predicate: ((notif: Notif)=&amp;gt;boolean))&#039;&#039;&#039;&lt;br /&gt;
This method will set a check whether any of notifications of specific type should be ignored.&lt;br /&gt;
&lt;br /&gt;
The parameters are:&lt;br /&gt;
* notif_type: type of the notification &lt;br /&gt;
* predicate (notif =&amp;gt; boolean): a function that will receive notif object and will return true if this specific notification should be ignored&lt;br /&gt;
&lt;br /&gt;
Before dispatching any notification of this type, the framework will call predicate to check whether notification should be ignored, if it return true - the notification will be dispatched, i.e. logged or handled.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    this.notifqueue.setIgnoreNotificationCheck( &#039;dealCard&#039;, (notif) =&amp;gt; (notif.args.player_id == this.player_id) );&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
IMPORTANT: Remember that this notification is ignored on the client side, but was still received by the client. Therefore it shouldn&#039;t contain any private information as cheaters can get it. In other words this is not a way to hide information.&lt;br /&gt;
&lt;br /&gt;
IMPORTANT: When a game is reloaded with F5 or when opening a turn based game, old notifications are replayed as history notification. They are used just to update the game log and are stripped of all arguments except player_id, i18n and any argument present in message. If you use and other argument in your predicate you should &#039;&#039;&#039;preserve&#039;&#039;&#039; it as explained [[Main_game_logic:_yourgamename.game.php#Notify_players|here]].&lt;br /&gt;
&lt;br /&gt;
=== Synchronous notifications ===&lt;br /&gt;
&lt;br /&gt;
When several notifications are received by your game interface, these notifications are processed immediately, one after the other, in the same exact order they have been generated in your PHP game logic.&lt;br /&gt;
&lt;br /&gt;
However, sometimes, you need to give some time to the players to figure out what happened on the game before jumping to the next notification. Indeed, in many games, there are a lot of automatic actions, and the computer is going to resolve all these actions very fast if you don&#039;t tell it not to do so.&lt;br /&gt;
&lt;br /&gt;
As an example, for Reversi, when someone is playing a disc, we want to wait 500 milliseconds before doing anything else in order the opponent player can figure out what move has been played.&lt;br /&gt;
&lt;br /&gt;
Here&#039;s how we do this, right after our subscription:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    dojo.subscribe( &#039;playDisc&#039;, this, &amp;quot;notif_playDisc&amp;quot; );&lt;br /&gt;
    this.notifqueue.setSynchronous( &#039;playDisc&#039;, 500 );   // Wait 500 milliseconds after executing the playDisc handler&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
-----&lt;br /&gt;
&lt;br /&gt;
It is also possible to control the delay timing dynamically (e.g., using notification args). As an example, maybe your notification &#039;cardPlayed&#039; should pause for a different amount of time depending on the number or type of cards played.&lt;br /&gt;
&lt;br /&gt;
For this case, use &#039;&#039;&#039;setSynchronous&#039;&#039;&#039; without specifying the duration and use &#039;&#039;&#039;setSynchronousDuration&#039;&#039;&#039; within the notification callback.&lt;br /&gt;
&lt;br /&gt;
* NOTE: If you forget to invoke &#039;&#039;&#039;setSynchronousDuration&#039;&#039;&#039;, the game will remain paused forever!&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
setupNotifications: function () {&lt;br /&gt;
    dojo.subscribe( &#039;cardPlayed&#039;, this, &#039;notif_cardPlayed&#039; );&lt;br /&gt;
    this.notifqueue.setSynchronous( &#039;cardPlayed&#039; ); // wait time is dynamic&lt;br /&gt;
    ...&lt;br /&gt;
},&lt;br /&gt;
&lt;br /&gt;
notif_cardPlayed: function (notif) {&lt;br /&gt;
    // MUST call setSynchronousDuration&lt;br /&gt;
&lt;br /&gt;
    // Example 1: From notification args (PHP)&lt;br /&gt;
    this.notifqueue.setSynchronousDuration(notif.args.duration);&lt;br /&gt;
    ...&lt;br /&gt;
&lt;br /&gt;
    // Or, example 2: Match the duration to a Dojo animation&lt;br /&gt;
    var anim = dojo.fx.combine([&lt;br /&gt;
        ...&lt;br /&gt;
    ]);&lt;br /&gt;
    anim.play();&lt;br /&gt;
    this.notifqueue.setSynchronousDuration(anim.duration);&lt;br /&gt;
},&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You can also manually call this.notifqueue.setSynchronousDuration(0) once client operations are finished, but be careful that even fast replay still has a path to call it.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;WARNING: combining synchronous and ignored notifications&#039;&#039;&#039;&lt;br /&gt;
You must be careful when combining dynamic synchronous durations (as described above) with ignored notifications. If you have a conditionally ignored notification like this (see below section):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;this.notifqueue.setIgnoreNotificationCheck( &#039;myNotif&#039;, (notif) =&amp;gt; (notif.args.player_id == this.player_id) /* or any other condition */ )&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
then you CANNOT do&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;this.notifqueue.setSynchronous(&#039;myNotif&#039;);&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
as, when the ignored check passes, the notification handler, in which `this.notifqueue.setSychronousDuration` is called, is never called and so the duration is never set and interface locking results.&lt;br /&gt;
&lt;br /&gt;
The workaround is to set a &amp;quot;dummy&amp;quot; time:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;this.notifqueue.setSynchronous(&#039;myNotif&#039;, 5000);&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
whose value is irrelevant but must be large enough to cover the time before the notification handler is called. The large value never actually comes into play because the notification is either ignored, or the synchronous duration is reset to a sensible value inside the handler.&lt;br /&gt;
&lt;br /&gt;
=== Pre-defined notification types ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;tableWindow&#039;&#039;&#039; - This defines notification to display [[Game_interface_logic:_yourgamename.js#Scoring_dialogs|Scoring Dialogs]], see below.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;message&#039;&#039;&#039; - This defines notification that shows on players log and have no other effect (technically any unhandled notification will do the same but its recommended to use this keyword for consistency)&lt;br /&gt;
&lt;br /&gt;
   // You can call this on php side without doing anything on client side&lt;br /&gt;
    self::notifyAllPlayers( &#039;message&#039;, clienttranslate(&#039;hello&#039;), [] );&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;simplePause&#039;&#039;&#039; - This notification will just delay other notifications, maybe useful if you know you need some extra time for animation or something. Requires a time parameter.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    self::notifyAllPlayers( &#039;simplePause&#039;, &#039;&#039;, [ &#039;time&#039; =&amp;gt; 500] ); // time is in milliseconds&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note: the following types are RESERVED by framework, do not use:&lt;br /&gt;
&lt;br /&gt;
gameStateChange gameStateChangePrivateArg gameStateMultipleActiveUpdate newActivePlayer playerstatus yourturnack clockalert tableInfosChanged playerEliminated tableDecision  archivewaitingdelay end_archivewaitingdelay replaywaitingdelay end_replaywaitingdelay replayinitialwaitingdelay end_replayinitialwaitingdelay aiPlayerWaitingDelay replay_has_ended updateSpectatorList  wouldlikethink updateReflexionTime undoRestorePoint resetInterfaceWithAllDatas zombieModeFail zombieModeFailWarning aiError skipTurnOfPlayer zombieBack allPlayersAreZombie gameResultNeutralized playerConcedeGame showTutorial showCursor showCursorClick skipTurnOfPlayerWarning  banFromTable resultsAvailable switchToTurnbased newPrivateState infomsg&lt;br /&gt;
&lt;br /&gt;
== Tooltips ==&lt;br /&gt;
&lt;br /&gt;
=== Adding static tooltips ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.addTooltip(nodeId: string, helpStringTranslated: string, actionStringTranslated: string, delay?: number): void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Add a simple text tooltip to the DOM node.&lt;br /&gt;
&lt;br /&gt;
Specify &#039;helpStringTranslated&#039; to display some information about &amp;quot;what is this game element?&amp;quot;.&lt;br /&gt;
Specify &#039;actionStringTranslated&#039; to display some information about &amp;quot;what happens when I click on this element?&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
You must specify both of the strings. You can only use one and specify an empty string (&#039;&#039;) for the other one.&lt;br /&gt;
&lt;br /&gt;
When you pass text directly function _() must be used for the text to be marked for translation! Except for empty string.&lt;br /&gt;
&lt;br /&gt;
Parameter &amp;quot;delay&amp;quot; is optional. It is primarily used to specify a zero delay for some game element when the tooltip gives really important information for the game - but remember: no essential information must be placed in tooltips as they won&#039;t be displayed in some browsers (see [[BGA_Studio_Guidelines|Guidelines]]).&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
   this.addTooltip( &#039;cardcount&#039;, _(&#039;Number of cards in hand&#039;), &#039;&#039; );&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note: this generates static tooltip and attaches to existing dom element, if you need to generate tooltip more dynamically you have to call that method every time information about object is updated or use completely different tehnique, see dynamic tooltips below.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.addTooltipHtml(nodeId: string, html: string, delay?: number): void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Add an HTML tooltip to the DOM node (for more elaborate content such as presenting a bigger version of a card).&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.addTooltipToClass(cssClass: string, helpStringTranslated: string, actionStringTranslated: string, delay?: number ): void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Add a simple text tooltip to all the DOM nodes set with this cssClass. See more details above for this.addTooltip.&lt;br /&gt;
     this.addTooltipToClass( &#039;meeple&#039;, _(&#039;This is A Meeple&#039;), _(&#039;Click to tickle&#039;) );&lt;br /&gt;
&lt;br /&gt;
IMPORTANT: all concerned nodes must exist and have IDs to get tooltips.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.addTooltipHtmlToClass(cssClass: string, html: string, delay?: number): void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Add an HTML tooltip to to all the DOM nodes set with this cssClass (for more elaborate content such as presenting a bigger version of a card).&lt;br /&gt;
&lt;br /&gt;
IMPORTANT: all concerned nodes must exist and have IDs to get tooltips.&lt;br /&gt;
&lt;br /&gt;
=== Removing static tooltips ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.removeTooltip(nodeId: string): void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Remove a tooltip from the DOM node with given id.&lt;br /&gt;
&lt;br /&gt;
=== Advanced tooltips ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;force tooltip to open&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
If you want to force tooltip to open in reaction to some other action, i.e. click you can do this&lt;br /&gt;
&lt;br /&gt;
   this.tooltips[id].open(id)&lt;br /&gt;
&lt;br /&gt;
where id is the id of the tooltip node where tooltip was installed.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;dynamic tooltips&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
See [[BGA_Studio_Cookbook#Dynamic_tooltips]]&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;tooltips on mobile&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Tooltips is very unreliable on mobile, it is recommended to implement some other method to obtaining same information,&lt;br /&gt;
such as simple click handler in dedicated &amp;quot;Help&amp;quot; mode or provide dedicated clickable areas such as corner of card.&lt;br /&gt;
&lt;br /&gt;
== Warning messages ==&lt;br /&gt;
&lt;br /&gt;
Sometimes, there is something important that is happening in the game and you have to make sure all players get the message. Most of the time, the evolution of the game situation or the game log is enough, but sometimes you need something more visible.&lt;br /&gt;
&lt;br /&gt;
Ex: someone fulfills one of the end of the game conditions, so this is the last turn.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.showMessage(msg: string, type: string): void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
showMessage shows a message in a big rectangular area on the top of the screen of the current player, and it dissapears after few seconds (also it will be in the log in some cases).&lt;br /&gt;
&lt;br /&gt;
* &amp;quot;msg&amp;quot; is the string to display. It should be translated.&lt;br /&gt;
* &amp;quot;type&amp;quot; can be set to &amp;quot;info&amp;quot;, &amp;quot;error&amp;quot;, &amp;quot;only_to_log&amp;quot; or custom string. If set to &amp;quot;info&amp;quot;, the message will be an informative message on a white background. If set to &amp;quot;error&amp;quot;, the message will be an error message on a red background and it will be added to log. If set to &amp;quot;only_to_log&amp;quot;, the message will be added to the game log but will not popup at the top of the screen.&lt;br /&gt;
If set to custom string, it will be transparent, to use custom type define &amp;quot;head_xxx&amp;quot; in css, where xxx is the type. For example if you want yellow warning, use &amp;quot;warning&amp;quot; as type and add this to css:&lt;br /&gt;
 .head_warning {&lt;br /&gt;
    background-color: #e6c66e;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
Important: the normal way to inform players about the progression of the game is the game log. The &amp;quot;showMessage&amp;quot; is intrusive and should not be used often.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    notif_messageinfo: function(notif) {&lt;br /&gt;
	if (!g_archive_mode) {&lt;br /&gt;
        	var message = this.format_string_recursive(notif.log, notif.args);&lt;br /&gt;
		this.showMessage(_(&#039;Announcement:&#039;) + &amp;quot; &amp;quot; + message, &#039;info&#039;);		&lt;br /&gt;
         }&lt;br /&gt;
    },&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Show message could be used on the client side to prevent user wrong moves before it is send to server.&lt;br /&gt;
Example from &#039;battleship&#039;:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
onGrid: function(event) {&lt;br /&gt;
     if (checkIfPlayerTriesToFireOnThemselves(event)) {&lt;br /&gt;
        this.showMessage(_(&#039;This is your own board silly!&#039;), &#039;error&#039;);&lt;br /&gt;
        return;&lt;br /&gt;
     }&lt;br /&gt;
     ...&lt;br /&gt;
},&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.showMoveUnauthorized(): void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Shows predefined user error that move is unauthorized now&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
onPet: function(event) {&lt;br /&gt;
     if (checkPet(event)==false) {&lt;br /&gt;
        this.showMoveUnauthorized();&lt;br /&gt;
        return;&lt;br /&gt;
     }&lt;br /&gt;
     ...&lt;br /&gt;
},&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Dialogs ==&lt;br /&gt;
&lt;br /&gt;
=== Confirmation dialog ===&lt;br /&gt;
&lt;br /&gt;
When an important action with a lot of consequences is triggered by the player, you may want to propose a confirmation dialog.&lt;br /&gt;
&lt;br /&gt;
CAREFUL: the general guideline of BGA is to AVOID the use of confirmation dialogs. Confirmation dialogs slow down the game and bother players. The players know that they have to pay attention to each move when they are playing online.&lt;br /&gt;
&lt;br /&gt;
The situations where you should use a confirmation dialog are the following:&lt;br /&gt;
* It must not happen very often during a game.&lt;br /&gt;
* It must be linked to an action that can really &amp;quot;kill a game&amp;quot; if the player does not pay attention.&lt;br /&gt;
* It must be something that can be done by mistake (ex: a link on the action status bar).&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.confirmationDialog(message: string, yesHandler: (param: any) =&amp;gt; void, noHandler?: (param: any) =&amp;gt; void, param?: any): void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
* message - message will be shown to user, use _() to translate&lt;br /&gt;
* yesHandler - non-optional handler to be called on yes&lt;br /&gt;
* noHandler - optional handler to called on no&lt;br /&gt;
* param - if specified, it will be passed to both handlers&lt;br /&gt;
NOTE: this is async function, it does not return anything and you should not do anything after, you must do everything in handlers&lt;br /&gt;
&lt;br /&gt;
How to display a confirmation dialog:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    this.confirmationDialog(_(&amp;quot;Are you sure you want to bake a pie?&amp;quot;), () =&amp;gt; {&lt;br /&gt;
      this.bakeThePie();&lt;br /&gt;
    });&lt;br /&gt;
    return; // nothing should be called or done after calling this, all action must be done in the handler&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
With param and both handlers&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    this.confirmationDialog(_(&amp;quot;Are you sure you want to bake a pie?&amp;quot;), &lt;br /&gt;
           (ingredient) =&amp;gt; this.bakeThePie(ingredient), &lt;br /&gt;
           (ingredient) =&amp;gt; console.log(`cancelled baking of ${ingredient}`), &lt;br /&gt;
           &#039;apple&#039;);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Multiple choice dialog ===&lt;br /&gt;
&lt;br /&gt;
You can use this dialog to give user a choice with small amount of options&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.multipleChoiceDialog(message: string, choices: string[], callback: (choice: number) =&amp;gt; void): void&#039;&#039;&#039;&lt;br /&gt;
* message - message will be shown to user, use _() to translate&lt;br /&gt;
* choices - array of choices&lt;br /&gt;
* callback - non-optional handler to be called on choice made, the choice parameter is the INDEX of the choice from the array of choices&lt;br /&gt;
&lt;br /&gt;
NOTE: this is async function, it does not return anything and you should not do anything after, you must do everything in handlers&lt;br /&gt;
NOTE: there is no cancel handler, so make sure you gave user a choice to get out of it&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    const keys = [&amp;quot;0&amp;quot;, &amp;quot;1&amp;quot;, &amp;quot;5&amp;quot;, &amp;quot;10&amp;quot;];&lt;br /&gt;
    this.multipleChoiceDialog(_(&amp;quot;How many bugs to fix?&amp;quot;), keys, (choice) =&amp;gt; {&lt;br /&gt;
      if (choice==0) return; // cancel operation, do not call server action&lt;br /&gt;
      var bugchoice = keys[choice]; // choice will be 0,1,2,3 here&lt;br /&gt;
      this.bgaPerformAction(&amp;quot;fixBugs&amp;quot;, { number: bugchoice });&lt;br /&gt;
    });&lt;br /&gt;
    return; // must return here&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Generic Dialogs ===&lt;br /&gt;
&lt;br /&gt;
As a general rule, you shouldn&#039;t use dialogs windows.&lt;br /&gt;
&lt;br /&gt;
BGA guidelines specify that all game elements should be displayed on the main screen. Players can eventually scroll down to see game elements they don&#039;t need to see anytime, and you may eventually create anchors to move between game area section. Of course dialogs windows are very practical, but the thing is: all players know how to scroll down, and not all players know how to show up your dialog window. In addition, when the dialog shows up, players can&#039;t access the other game components.&lt;br /&gt;
&lt;br /&gt;
Sometimes although, you need to display a dialog window. Here is how you do this:&lt;br /&gt;
&lt;br /&gt;
  // Create the new dialog over the play zone. You should store the handler in a member variable to access it later&lt;br /&gt;
  this.myDlg = new ebg.popindialog();&lt;br /&gt;
  this.myDlg.create( &#039;myDialogUniqueId&#039; );&lt;br /&gt;
  this.myDlg.setTitle( _(&amp;quot;my dialog title to translate&amp;quot;) );&lt;br /&gt;
  this.myDlg.setMaxWidth( 500 ); // Optional&lt;br /&gt;
  &lt;br /&gt;
  // Create the HTML of my dialog. &lt;br /&gt;
  // The best practice here is to use [[Game_layout:_view_and_template:_yourgamename.view.php_and_yourgamename_yourgamename.tpl#Javascript_templates|Javascript templates]]&lt;br /&gt;
  var html = this.format_block( &#039;jstpl_myDialogTemplate&#039;, { &lt;br /&gt;
                arg1: myArg1,&lt;br /&gt;
                arg2: myArg2,&lt;br /&gt;
                ...&lt;br /&gt;
            } );  &lt;br /&gt;
  &lt;br /&gt;
  // Show the dialog&lt;br /&gt;
  this.myDlg.setContent( html ); // Must be set before calling show() so that the size of the content is defined before positioning the dialog&lt;br /&gt;
  this.myDlg.show();&lt;br /&gt;
  &lt;br /&gt;
  // Now that the dialog has been displayed, you can connect your method to some dialog elements&lt;br /&gt;
  // Example, if you have an &amp;quot;OK&amp;quot; button in the HTML of your dialog:&lt;br /&gt;
  dojo.connect($(&#039;my_ok_button&#039;), &#039;onclick&#039;, this, (event) =&amp;gt; {&lt;br /&gt;
                event.preventDefault();&lt;br /&gt;
                this.myDlg.destroy();&lt;br /&gt;
            });&lt;br /&gt;
&lt;br /&gt;
If necessary, you can remove the default top right corner &#039;close&#039; icon, or replace the function called when it is clicked:&lt;br /&gt;
  // Removes the default close icon&lt;br /&gt;
  this.myDlg.hideCloseIcon();&lt;br /&gt;
&lt;br /&gt;
  // Replace the function call when it&#039;s clicked&lt;br /&gt;
  this.myDlg.replaceCloseCallback((event) =&amp;gt; { ... });&lt;br /&gt;
&lt;br /&gt;
=== Scoring dialogs ===&lt;br /&gt;
&lt;br /&gt;
Sometimes at the end of a round you want to display a big table that details the points wins in each section of the game.&lt;br /&gt;
&lt;br /&gt;
Example: in Hearts game, we display at the end of each round the number of &amp;quot;heart&amp;quot; cards collected by each player, the player who collected the Queen of Spades, and the total number of points loose by each player.&lt;br /&gt;
&lt;br /&gt;
Scoring dialogs are managed entirely on &#039;&#039;&#039;PHP side&#039;&#039;&#039;, but they are described here as their effects are visible only on client side.&lt;br /&gt;
&lt;br /&gt;
Displaying a scoring dialog is quite simple and is using a special notification type: &amp;quot;tableWindow&amp;quot;:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  // on PHP side:&lt;br /&gt;
  $this-&amp;gt;notifyAllPlayers( &amp;quot;tableWindow&amp;quot;, &#039;&#039;, array(&lt;br /&gt;
            &amp;quot;id&amp;quot; =&amp;gt; &#039;finalScoring&#039;,&lt;br /&gt;
            &amp;quot;title&amp;quot; =&amp;gt; clienttranslate(&amp;quot;Title of the scoring dialog&amp;quot;),&lt;br /&gt;
            &amp;quot;table&amp;quot; =&amp;gt; $table&lt;br /&gt;
        )); &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The &amp;quot;table&amp;quot; argument is a 2 dimensional PHP array that describes the table you want to display, line by line and column by column.&lt;br /&gt;
&lt;br /&gt;
Example: display an 3x3 array of strings&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
   $table = [&lt;br /&gt;
      [ &amp;quot;one&amp;quot;, &amp;quot;two&amp;quot;, &amp;quot;three&amp;quot; ],    // This is my first line&lt;br /&gt;
      [ &amp;quot;four&amp;quot;, &amp;quot;five&amp;quot;, &amp;quot;six&amp;quot; ],    // This is my second line&lt;br /&gt;
      [ &amp;quot;seven&amp;quot;, &amp;quot;height&amp;quot;, &amp;quot;nine&amp;quot; ]    // This is my third line&lt;br /&gt;
   ];&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
As you can see above, in each &amp;quot;cell&amp;quot; of your array you can display a simple string value. But you can also display a complex value with a template and associated arguments like this:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
   $table = [&lt;br /&gt;
      [ &amp;quot;one&amp;quot;, &amp;quot;two&amp;quot;, [ &amp;quot;str&amp;quot; =&amp;gt; clienttranslate(&amp;quot;a string with an ${argument}&amp;quot;), &amp;quot;args&amp;quot; =&amp;gt; [ &#039;argument&#039; =&amp;gt; &#039;argument_value&#039; ] ] ],&lt;br /&gt;
      [ &amp;quot;four&amp;quot;, &amp;quot;five&amp;quot;, &amp;quot;six&amp;quot; ], &lt;br /&gt;
      [ &amp;quot;seven&amp;quot;, &amp;quot;height&amp;quot;, &amp;quot;nine&amp;quot; ]&lt;br /&gt;
   ];&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This is especially useful when you want to display player names with colors. Example from &amp;quot;Hearts&amp;quot;:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        $firstRow = [ &#039;&#039; ];&lt;br /&gt;
        foreach( $players as $player_id =&amp;gt; $player )    {&lt;br /&gt;
            $cell = [ &#039;str&#039; =&amp;gt; &#039;${player_name}&#039;,&lt;br /&gt;
                      &#039;args&#039; =&amp;gt; [ &#039;player_name&#039; =&amp;gt; $player[&#039;player_name&#039;] ],&lt;br /&gt;
                      &#039;type&#039; =&amp;gt; &#039;header&#039;&lt;br /&gt;
                    ];&lt;br /&gt;
            $firstRow[] = $cell;&lt;br /&gt;
        }&lt;br /&gt;
        $table[] = $firstRow;&lt;br /&gt;
        ...&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You can also use three extra attributes in the parameter array for the notification:&lt;br /&gt;
* &#039;&#039;&#039;header&#039;&#039;&#039;: the content for this parameter displays before the table (also, the html will be parsed and player names will be colored according to the current game colors). &lt;br /&gt;
* &#039;&#039;&#039;footer&#039;&#039;&#039;: the content for this parameter displays after the table (no parsing for coloring the player names)&lt;br /&gt;
* &#039;&#039;&#039;closing&#039;&#039;&#039;: if this parameter is used, a button will be displayed with this label at the bottom of the popup and will allow players to close it (more easily than by clicking the top right &#039;cross&#039; icon).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
   $this-&amp;gt;notifyAllPlayers( &amp;quot;tableWindow&amp;quot;, &#039;&#039;, [&lt;br /&gt;
            &amp;quot;id&amp;quot; =&amp;gt; &#039;finalScoring&#039;,&lt;br /&gt;
            &amp;quot;title&amp;quot; =&amp;gt; clienttranslate(&amp;quot;Title of the scoring dialog&amp;quot;),&lt;br /&gt;
            &amp;quot;table&amp;quot; =&amp;gt; $table,&lt;br /&gt;
            &amp;quot;header&amp;quot; =&amp;gt; [&#039;str&#039; =&amp;gt; clienttranslate(&#039;Table header with parameter ${number}&#039;),&lt;br /&gt;
                                 &#039;args&#039; =&amp;gt; [ &#039;number&#039; =&amp;gt; 3 ],&lt;br /&gt;
                               ],&lt;br /&gt;
            &amp;quot;footer&amp;quot; =&amp;gt; &#039;&amp;lt;div class=&amp;quot;myfoot&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&#039;,&lt;br /&gt;
            &amp;quot;closing&amp;quot; =&amp;gt; clienttranslate( &amp;quot;Closing button label&amp;quot; )&lt;br /&gt;
        ] ); &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note: currently id is not used - so you cannot access resulting div by id on js side&lt;br /&gt;
Note: any traslatable stirng have to be wrapped by clienttranslate() on top level OR it has to be recursive template. &lt;br /&gt;
&lt;br /&gt;
DO NOT DO THIS: &lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
   &amp;quot;footer&amp;quot; =&amp;gt; &#039;&amp;lt;div&amp;gt;&#039;.clienttranslate( &amp;quot;The end&amp;quot; ).&#039;&amp;lt;/div&amp;gt;&#039;, // this will not work for translations!!!&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Scoring animated display ===&lt;br /&gt;
&lt;br /&gt;
Sometimes, you may want to display a score value over an element to make the scoring easier to follow for the players (Terra Mystica final scoring for example).&lt;br /&gt;
You can do it with:&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.displayScoring(anchor_id: string, color: string, score: number | string, duration?: number, offset_x?: number, offset_y?: number): void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;anchor_id&#039;&#039;&#039;: ID of the html element to place the animated score onto (without the &#039;#&#039;) &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;color&#039;&#039;&#039;: hexadecimal RGB representation of the color (should be the color of the scoring player), but without a leading &#039;#&#039;.  For instance, &#039;ff0000&#039; for red.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;score&#039;&#039;&#039;: numeric score to display, prefixed by a &#039;+&#039; or &#039;-&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;duration&#039;&#039;&#039;: animation duration in milliseconds (optional, default is 1000)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;offset_x&#039;&#039;&#039; and &#039;&#039;&#039;offset_y&#039;&#039;&#039;: if both offset_x and offset_y are defined and not null, apply the following offset (in pixels) to the scoring animation. &lt;br /&gt;
Note that the score is centered in the anchor, so the offsets might have to be negative if you calculate the position.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Note: if you want to display successively each score, you can use &#039;&#039;this.notifqueue.setSynchronous()&#039;&#039; function.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    setupNotifications: function()   {&lt;br /&gt;
           dojo.subscribe( &#039;displayScoring&#039;, this, &amp;quot;notif_displayScoring&amp;quot; );&lt;br /&gt;
           ...&lt;br /&gt;
    }&lt;br /&gt;
...&lt;br /&gt;
&lt;br /&gt;
    notif_displayScoring: function(notif) {&lt;br /&gt;
            const duration = notif.args.duration?notif.args.duration:1000;&lt;br /&gt;
            this.notifqueue.setSynchronous(&#039;displayScoring&#039;, duration );&lt;br /&gt;
	    this.displayScoring( notif.args.target, notif.args.color, notif.args.score, duration);&lt;br /&gt;
    },&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Speech bubble ===&lt;br /&gt;
&lt;br /&gt;
For better interactivity in some games (Love Letter for example), you may use comic book style speech bubbles to express the players voices.&lt;br /&gt;
This is done with showBubble:&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.showBubble(anchor_id: string, text: string, delay?: number, duration?: number, custom_class?: string): void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
* anchor_id - where to attach the bubble&lt;br /&gt;
* text - what to put in bubble, can be html&lt;br /&gt;
* delay - delay in milliseconds (optional, default 0)&lt;br /&gt;
* duration -  duration of animation in milliseconds (optional, default 3000)&lt;br /&gt;
* custom_class - extra class to add to bubble (optional), if you need to override the default bubble style&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
   this.showBubble(&#039;meeple_2&#039;, _(&#039;Hello&#039;), 0, 1000, &#039;pink_bubble&#039;);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  notif_speechBubble(notif) {&lt;br /&gt;
    var html = this.format_string_recursive(notif.args.text, notif.args.args);&lt;br /&gt;
    this.showBubble(notif.args.target, html, notif.args.delay ?? 0, notif.args.duration ?? 1000);&lt;br /&gt;
  },&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Warning&#039;&#039;&#039;: if your bubble could overlap other active elements of the interface (buttons in particular), as it stays in place even after disappearing, you should use a custom class to give it the style &amp;quot;pointer-events: none;&amp;quot; in order to intercept click events.&lt;br /&gt;
&lt;br /&gt;
Note: If you want this visually, but want to take complete control over this bubble and its animation (for example to make it permanent) you can just use div with &#039;discussion_bubble&#039; class on it, and content of div is what will be shown.&lt;br /&gt;
&lt;br /&gt;
== Translations ==&lt;br /&gt;
&lt;br /&gt;
See [[Translations]]&lt;br /&gt;
&lt;br /&gt;
== Players panels ==&lt;br /&gt;
&lt;br /&gt;
=== Update players score ===&lt;br /&gt;
&lt;br /&gt;
The column player_score from the player table is automatically loaded into this.scoreCtrl and therefore into the stars location on the player board. This occurs sometime after the game setup() function. However this score must be updated as the game progresses using notifications.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Note: this.scoreCtrl[player_id] is object of class [[Counter]], you can use other counter API.&lt;br /&gt;
&lt;br /&gt;
Increase a player score (with a positive or negative number):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  this.scoreCtrl[ player_id ].incValue( score_delta );&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Set a player score to a specific value:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  this.scoreCtrl[ player_id ].setValue( new_score );&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Set a player score to a specific value with animation:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  this.scoreCtrl[ player_id ].toValue( new_score );&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Typical usage would be (that will process &#039;score&#039; notification):&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        setupNotifications : function() {&lt;br /&gt;
              ...&lt;br /&gt;
             dojo.subscribe(&#039;score&#039;, this, &amp;quot;notif_score&amp;quot;);&lt;br /&gt;
        },&lt;br /&gt;
        notif_score: function(notif) {&lt;br /&gt;
            this.scoreCtrl[notif.args.player_id].setValue(notif.args.player_score);&lt;br /&gt;
        },&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Adding stuff to player&#039;s panel ===&lt;br /&gt;
&lt;br /&gt;
At first, create a new &amp;quot;JS template&amp;quot; string in your template (tpl) file:&lt;br /&gt;
&lt;br /&gt;
(from Gomoku example)&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
var jstpl_player_board = &#039;\&amp;lt;div class=&amp;quot;cp_board&amp;quot;&amp;gt;\&lt;br /&gt;
    &amp;lt;div id=&amp;quot;stoneicon_p${id}&amp;quot; class=&amp;quot;gmk_stoneicon gmk_stoneicon_${color}&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&amp;lt;span id=&amp;quot;stonecount_p${id}&amp;quot;&amp;gt;0&amp;lt;/span&amp;gt;\&lt;br /&gt;
&amp;lt;/div&amp;gt;&#039;;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Then, you add this piece of code in your JS file to add this template to each player panel:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
            // Setting up player boards&lt;br /&gt;
            for( var player_id in gamedatas.players )&lt;br /&gt;
            {&lt;br /&gt;
                var player = gamedatas.players[player_id];&lt;br /&gt;
                         &lt;br /&gt;
                // Setting up players boards if needed&lt;br /&gt;
                var player_board_div = $(&#039;player_board_&#039;+player_id);&lt;br /&gt;
                dojo.place( this.format_block(&#039;jstpl_player_board&#039;, player ), player_board_div );&lt;br /&gt;
            }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
(Note: the code above is of course from your &amp;quot;setup&amp;quot; function in your Javascript).&lt;br /&gt;
&lt;br /&gt;
Very often, you have to distinguish current player and others players. In this case, you just have to create another JS template (ex: jstpl_otherplayer_board) and use it when &amp;quot;player_id&amp;quot; is different than &amp;quot;this.player_id&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Fixing Player Panel heights ===&lt;br /&gt;
&lt;br /&gt;
You may find that the player panels don&#039;t automatically resize when adding something to (or removing something from) a player panel while the display is in portrait mode (i.e. the player summary panels are at the top of the screen rather than down the right side).&lt;br /&gt;
&lt;br /&gt;
When this happens, call &amp;lt;pre&amp;gt;this.adaptPlayersPanels();&amp;lt;/pre&amp;gt; This recalculates the layout and also adjusts the position of the actionbar for you.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Player&#039;s panel disabling/enabling ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.disablePlayerPanel(player_id: number): void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Disable given player panel (the panel background become gray).&lt;br /&gt;
&lt;br /&gt;
Usually, this is used to signal that this played passes, or will be inactive during a while.&lt;br /&gt;
&lt;br /&gt;
Note that the only effect of this is visual. There are no consequences on the behaviour of the panel itself.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.enablePlayerPanel(player_id:number): void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Enable a player panel that has been disabled before.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.enableAllPlayerPanels(): void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Enable all player panels that has been disabled before.&lt;br /&gt;
&lt;br /&gt;
=== Player order ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.updatePlayerOrdering(): void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
This function makes sure that player order in player&#039;s panel matches this.gamedatas.playerorder and its normally called by framework.&lt;br /&gt;
You can call it yoursel if you change this.gamedatas.playerorder from notification.&lt;br /&gt;
Also you can override this function to change defaults  OR insert a non-player panel [[BGA_Studio_Cookbook#Inserting_non-player_panel]].&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Counters ===&lt;br /&gt;
Note: there is bga component called  &amp;quot;ebg/counter&amp;quot; this API is not using it, these methods&lt;br /&gt;
below declared right in core game. If you need animation for counters use ebg/counter&lt;br /&gt;
&lt;br /&gt;
To use this API just create a counter dom element like this (class does not really matter)&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 &amp;lt;div class=&amp;quot;counter&amp;quot; id=&amp;quot;bread&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
 &amp;lt;div class=&amp;quot;counter&amp;quot; id=&amp;quot;coin&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
The &amp;quot;bread&amp;quot; will the counter name.&lt;br /&gt;
&lt;br /&gt;
The php code should send all &amp;quot;counters&amp;quot; data from getAllDatas() method like this&lt;br /&gt;
&lt;br /&gt;
game.php&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  protected function getAllDatas() {&lt;br /&gt;
    // (the key must match counter_name)&lt;br /&gt;
    $result[&#039;counters&#039;]=[&lt;br /&gt;
        &#039;bread&#039; =&amp;gt; [ &lt;br /&gt;
         &#039;counter_name&#039; =&amp;gt; &#039;bread&#039;, &lt;br /&gt;
         &#039;counter_value&#039; =&amp;gt; 3&lt;br /&gt;
         ], &lt;br /&gt;
        &#039;coin&#039; =&amp;gt; [&lt;br /&gt;
          &#039;counter_name&#039; =&amp;gt; &#039;coin&#039;, &lt;br /&gt;
          &#039;counter_value&#039; =&amp;gt; 5&lt;br /&gt;
        ]&lt;br /&gt;
   ];&lt;br /&gt;
   return $result;&lt;br /&gt;
  }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;setCounter(counter_name: stirng, new_value: string | number): void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
updates the global this.gamedatas.counters and value of node $(counter_name)&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  notif_counter: function(notif) { &lt;br /&gt;
    this.setCounter(notif.args.counter_name, notif.args.counter_value);&lt;br /&gt;
  },&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;incCounter(counter_name: string, delta: number): void&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  notif_counter : function(notif) {&lt;br /&gt;
    this.incCounter(notif.args.counter_name, notif.args.inc);&lt;br /&gt;
  },&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;updateCounters(counters: object): void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Useful for updating game counters in the player panel (such as resources). &lt;br /&gt;
&#039;counters&#039; arg is map of counters (the key must match counter_name)&lt;br /&gt;
  {&lt;br /&gt;
    &#039;bread&#039;: { &lt;br /&gt;
         &#039;counter_name&#039; : &#039;bread&#039;, &lt;br /&gt;
         &#039;counter_value&#039; =&amp;gt; 3&lt;br /&gt;
    }, &lt;br /&gt;
    &#039;coin&#039;: { &lt;br /&gt;
         &#039;counter_name&#039; : &#039;coin&#039;, &lt;br /&gt;
         &#039;counter_value&#039; =&amp;gt; 5&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
All counters MUST be referenced in this.gamedatas.counters (means they should be send from php) and will be updated.&lt;br /&gt;
DOM objects referenced by &#039;counter_name&#039; will have their innerHTML updated with &#039;counter_value&#039;.&lt;br /&gt;
&lt;br /&gt;
Usually you call this from notification&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
                        notif_counter : function(notif) {&lt;br /&gt;
                            this.updateCounters(notif.args.counters);&lt;br /&gt;
                        },&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== BGA GUI components ==&lt;br /&gt;
&lt;br /&gt;
BGA framework provides some useful ready-to-use components for the game interface:&lt;br /&gt;
&lt;br /&gt;
[[Studio#BGA_Studio_game_components_reference]]&lt;br /&gt;
&lt;br /&gt;
Note that each time you are using an additional component, you must declare it at the top of your Javascript file in the list of modules used.&lt;br /&gt;
&lt;br /&gt;
Example if you are using &amp;quot;ebg.stock&amp;quot;:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
define([&lt;br /&gt;
    &amp;quot;dojo&amp;quot;,&amp;quot;dojo/_base/declare&amp;quot;,&lt;br /&gt;
    &amp;quot;ebg/core/gamegui&amp;quot;,&lt;br /&gt;
    &amp;quot;ebg/counter&amp;quot;,&lt;br /&gt;
    &amp;quot;ebg/stock&amp;quot;  /// &amp;lt;=== we are using ebg.stock module&lt;br /&gt;
],&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== BGA Buttons ==&lt;br /&gt;
&lt;br /&gt;
=== Basic Button ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.addActionButton(id: string, label: string, method: string | eventhandler, destination?: string, blinking?: boolean, color?: string): void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
You can use this method to add an action button in the main action status bar (or other places).&lt;br /&gt;
&lt;br /&gt;
Arguments:&lt;br /&gt;
* id: an element ID that should be unique in your HTML DOM document.&lt;br /&gt;
* label: the text of the button. Should be translatable (use _() function). Note: this can also be any html, such as &amp;quot;&amp;lt;div class=&#039;brick&#039;&amp;gt;&amp;lt;/div&amp;gt;&amp;quot;, see example below on how to make image action buttons.&lt;br /&gt;
* method: the name of your method that must be triggered when the player clicks on this button (can be name of the method on game class or handler).&lt;br /&gt;
* destination (optional): id of parent on where to add button, ONLY use in rare cases if location is not action bar. Use &#039;&#039;&#039;null&#039;&#039;&#039; as value if you need to specify other arguments.&lt;br /&gt;
* blinking (optional): if set to &#039;&#039;&#039;true&#039;&#039;&#039;, the button is going blink to catch player&#039;s attention. Please DO NOT abuse blinking button. If you need button to blink after some time passed add class &#039;blinking&#039; to the button later.&lt;br /&gt;
* color: could be &#039;&#039;&#039;blue&#039;&#039;&#039; (default), &#039;&#039;&#039;red&#039;&#039;&#039;,&#039;&#039;&#039;gray&#039;&#039;&#039; or &#039;&#039;&#039;none&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
You should only use this method in your &amp;quot;onUpdateActionButtons&amp;quot; method. Usually, you use it like this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        onUpdateActionButtons: function( stateName, args ) {                      &lt;br /&gt;
            if (this.isCurrentPlayerActive()) {            &lt;br /&gt;
                switch( stateName ) {&lt;br /&gt;
                case &#039;giveCards&#039;:&lt;br /&gt;
                    this.addActionButton( &#039;giveCards_button&#039;, _(&#039;Give selected cards&#039;), &#039;onGiveCards&#039; ); &lt;br /&gt;
                    this.addActionButton( &#039;pass_button&#039;, _(&#039;Pass&#039;), () =&amp;gt; this.bgaPerformAction(&#039;actPass&#039;) ); &lt;br /&gt;
                    break;&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        },   &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In the example above, we are adding a &amp;quot;Give selected cards&amp;quot; button in the case we are on game state &amp;quot;giveCards&amp;quot;. When player clicks on this button, it triggers our &amp;quot;onGiveCards&amp;quot; method.&lt;br /&gt;
&lt;br /&gt;
Example using blinking red button:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    this.addActionButton( &#039;button_confirm&#039;, _(&#039;Confirm?&#039;), &#039;onConfirm&#039;, null, true, &#039;red&#039;); &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If you want to call the handler with arguments, you can use arrow functions, like this:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
     this.addActionButton( &#039;commit_button&#039;, _(&#039;Confirm&#039;), () =&amp;gt; this.onConfirm(this.selectedCardId), null, false, &#039;red&#039;); &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Image Button ===&lt;br /&gt;
&lt;br /&gt;
You can use the same method, but add extra class to a button to disable the padding and style it, i.e.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
this.addActionButton( &#039;button_brick&#039;, &#039;&amp;lt;div class=&amp;quot;brick&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&#039;, ()=&amp;gt;{... on brick ...}, null, null, &#039;gray&#039;); &lt;br /&gt;
dojo.addClass(&#039;button_brick&#039;,&#039;bgaimagebutton&#039;);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
where&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
.bgaimagebutton {&lt;br /&gt;
  padding: 0px 12px;&lt;br /&gt;
  min-height: 28px;&lt;br /&gt;
  border: none;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If you use this a lot, you can define a helper function, i.e.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
 * This method can be used instead of addActionButton, to add a button which is an image (i.e. resource). Can be useful when player&lt;br /&gt;
 * need to make a choice of resources or tokens.&lt;br /&gt;
 */&lt;br /&gt;
addImageActionButton: function(id, div, handler, bcolor, tooltip) {&lt;br /&gt;
	if (typeof bcolor == &amp;quot;undefined&amp;quot;) {&lt;br /&gt;
		bcolor = &amp;quot;gray&amp;quot;;&lt;br /&gt;
	}&lt;br /&gt;
	// this will actually make a transparent button id color = gray&lt;br /&gt;
	this.addActionButton(id, div, handler, null, false, bcolor);&lt;br /&gt;
	// remove border, for images it better without&lt;br /&gt;
	dojo.style(id, &amp;quot;border&amp;quot;, &amp;quot;none&amp;quot;);&lt;br /&gt;
	// but add shadow style (box-shadow, see css)&lt;br /&gt;
	dojo.addClass(id, &amp;quot;shadow bgaimagebutton&amp;quot;);&lt;br /&gt;
	// you can also add additional styles, such as background&lt;br /&gt;
	if (tooltip) {&lt;br /&gt;
		dojo.attr(id, &amp;quot;title&amp;quot;, tooltip);&lt;br /&gt;
	}&lt;br /&gt;
	return $(id);&lt;br /&gt;
},&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Disabling Button ===&lt;br /&gt;
&lt;br /&gt;
You can disable the &#039;&#039;&#039;bgabutton&#039;&#039;&#039; by adding the css class &#039;&#039;&#039;disabled&#039;&#039;&#039; in you js. The disabled button is still visible but is grey and not clickable.&lt;br /&gt;
For example in the &#039;&#039;&#039;onUpdateActionButtons&#039;&#039;&#039; : &lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
this.addActionButton(&#039;play_button_id&#039;, _(&#039;Play 1 to 3 cards&#039;), &#039;playFunctionButton&#039;); &lt;br /&gt;
if (condition) {&lt;br /&gt;
  dojo.addClass(&#039;play_button_id&#039;, &#039;disabled&#039;);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Custom Buttons ===&lt;br /&gt;
&lt;br /&gt;
You can create a custom button, but the BGA framework provides a standard button that requires only .css classes: &#039;&#039;&#039;bgabutton&#039;&#039;&#039; and &#039;&#039;&#039;bgabutton_${color}&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Examples:&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;a href=&amp;quot;#&amp;quot; id=&amp;quot;my_button_id&amp;quot; class=&amp;quot;bgabutton bgabutton_blue&amp;quot;&amp;gt;&amp;lt;span&amp;gt;My blue button&amp;lt;/span&amp;gt;&amp;lt;/a&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;a href=&amp;quot;#&amp;quot; id=&amp;quot;my_button_id&amp;quot; class=&amp;quot;bgabutton bgabutton_red bgabutton_big&amp;quot;&amp;gt;&amp;lt;span&amp;gt;My big red button&amp;lt;/span&amp;gt;&amp;lt;/a&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note&#039;&#039;&#039;: To see it in action, check out &#039;&#039;Coloretto&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
=== Button outside of action bar ===&lt;br /&gt;
&lt;br /&gt;
Use addActionButton() method with destination argument set&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
this.addActionButton( &#039;commit_button&#039;, _(&#039;Confirm&#039;), &#039;onConfirm&#039;, &#039;player_board&#039;, true, &#039;red&#039;); &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
in example above the button will be place on object with id &#039;player_board&#039;&lt;br /&gt;
&lt;br /&gt;
== Image loading ==&lt;br /&gt;
&lt;br /&gt;
See also [[Game_art:_img_directory]].&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Be careful&#039;&#039;&#039;: by default, ALL images of your img directory are loaded on a player&#039;s browser when he loads the game. For this reason, don&#039;t let in your img directory images that are not useful, otherwise it&#039;s going to slowdown the game load.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.dontPreloadImage(image_file_name: string)&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Using dontPreloadImage, you tell the interface to not preload a specific image in your img directory.&lt;br /&gt;
&lt;br /&gt;
Example of use:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
this.dontPreloadImage( &#039;cards.png&#039; );&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This is particularly useful if for example you have 2 different themes for a game. To accelerate the loading of the game, you can specify to not preload images corresponding to the other theme.&lt;br /&gt;
&lt;br /&gt;
Another example of use: in &amp;quot;Gosu&amp;quot; game with Kamakor extension, you play with 5 sets of cards among 10 available. Cards images are organized by sets, and we only preload the images corresponding to the 5 current sets with &#039;&#039;&#039;ensureSpecificGameImageLoading( image_file_names_array )&#039;&#039;&#039;.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
// By default, do not preload anything&lt;br /&gt;
this.dontPreloadImage( &#039;cards.png&#039; );&lt;br /&gt;
this.dontPreloadImage( &#039;clan1.png&#039; );&lt;br /&gt;
this.dontPreloadImage( &#039;clan2.png&#039; );&lt;br /&gt;
this.dontPreloadImage( &#039;clan3.png&#039; );&lt;br /&gt;
this.dontPreloadImage( &#039;clan4.png&#039; );&lt;br /&gt;
this.dontPreloadImage( &#039;clan5.png&#039; );&lt;br /&gt;
this.dontPreloadImage( &#039;clan6.png&#039; );&lt;br /&gt;
this.dontPreloadImage( &#039;clan7.png&#039; );&lt;br /&gt;
this.dontPreloadImage( &#039;clan8.png&#039; );&lt;br /&gt;
this.dontPreloadImage( &#039;clan9.png&#039; );&lt;br /&gt;
this.dontPreloadImage( &#039;clan10.png&#039; );&lt;br /&gt;
var to_preload = [];&lt;br /&gt;
for( i in this.gamedatas.clans )&lt;br /&gt;
{&lt;br /&gt;
	var clan_id = this.gamedatas.clans[i];&lt;br /&gt;
	to_preload.push( &#039;clan&#039;+clan_id+&#039;.png&#039; );&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
this.ensureSpecificGameImageLoading( to_preload );&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note:&#039;&#039;&#039; You don&#039;t need to specify to not preload game box images (game_box.png, game_box75.png...) since they are not preloaded by default.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.ensureSpecificGameImageLoading(list: string[])&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
This is oppostive of dontPreloadImage - its ensure specific images is loaded. Note: only makes sense if preload list is empty, otherwise everything is loaded anyway&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;load specific images&#039;&#039;&#039;&lt;br /&gt;
All images that will be preloaded stored in g_img_preload. If you want to override it directly - there is no API, but you can do this in GAME constructor&lt;br /&gt;
&lt;br /&gt;
          g_img_preload = [&#039;tokens.png&#039;, &#039;trains.png&#039;, &#039;loc_plan.png&#039;, &#039;eng.png&#039;, &#039;eng-back.png&#039;];&lt;br /&gt;
&lt;br /&gt;
You can also set it to empty array and call ensureSpecificGameImageLoading() on specific images&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Sounds ==&lt;br /&gt;
&lt;br /&gt;
Add a custom sound and make it load with your interface:&lt;br /&gt;
&lt;br /&gt;
Add this in your template (.tpl) file:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;audio id=&amp;quot;audiosrc_&amp;lt;gamename&amp;gt;_&amp;lt;yoursoundname&amp;gt;&amp;quot; src=&amp;quot;{GAMETHEMEURL}img/&amp;lt;gamename&amp;gt;_&amp;lt;yoursoundname&amp;gt;.mp3&amp;quot; preload=&amp;quot;none&amp;quot; autobuffer&amp;gt;&amp;lt;/audio&amp;gt;&lt;br /&gt;
&amp;lt;audio id=&amp;quot;audiosrc_o_&amp;lt;gamename&amp;gt;_&amp;lt;yoursoundname&amp;gt;&amp;quot; src=&amp;quot;{GAMETHEMEURL}img/&amp;lt;gamename&amp;gt;_&amp;lt;yoursoundname&amp;gt;.ogg&amp;quot; preload=&amp;quot;none&amp;quot; autobuffer&amp;gt;&amp;lt;/audio&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note: this is a requirement to provide both a mp3 and a ogg file with the names &amp;lt;code&amp;gt;&amp;lt;gamename&amp;gt;_&amp;lt;yoursoundname&amp;gt;[.ogg][.mp3]&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Play the sound (from your .js file):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
playSound(&#039;&amp;lt;gamename&amp;gt;_&amp;lt;yoursoundname&amp;gt;&#039;);   // do not add &#039;this.&#039; - its a global function&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Disable the standard &amp;quot;move&amp;quot; sound for this move (to replace it with your custom sound):&lt;br /&gt;
&lt;br /&gt;
Add this to your notification handler:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
this.disableNextMoveSound();&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note: it only disable the sound for the next move.&lt;br /&gt;
&lt;br /&gt;
== Title bar and states ==&lt;br /&gt;
&lt;br /&gt;
=== Client states ===&lt;br /&gt;
&lt;br /&gt;
Client states is a way to simulate the state transition but without actually going&lt;br /&gt;
to server. It is usefull when you need to ask user multiple questions before you&lt;br /&gt;
send things to server&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.setClientState(newState: string, args: object)&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
     this.setClientState(&amp;quot;client_playerPicksLocation&amp;quot;, {&lt;br /&gt;
                               descriptionmyturn : _(&amp;quot;${you} must select location&amp;quot;),&lt;br /&gt;
                           });&lt;br /&gt;
&lt;br /&gt;
For more information see [[BGA_Studio_Cookbook#Multi_Step_Interactions:_Select_Worker.2FPlace_Worker_-_Using_Client_States]]&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.restoreServerGameState()&#039;&#039;&#039;&lt;br /&gt;
If you are in client state it will restore the current server state (cheap undo)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.on_client_state&#039;&#039;&#039;&lt;br /&gt;
Boolean indicating that we are in client state&lt;br /&gt;
&lt;br /&gt;
=== Title bar ===&lt;br /&gt;
If you simply want to show something in title bar you can do it directly &lt;br /&gt;
     $(&#039;pagemaintitletext&#039;).innerHTML = text;&lt;br /&gt;
&lt;br /&gt;
This however will not work with parameters and will not draw You in color,&lt;br /&gt;
if you want to do proper args rendering use method below&lt;br /&gt;
&lt;br /&gt;
;&#039;&#039;&#039;this.removeActionButtons()&#039;&#039;&#039;&lt;br /&gt;
Removes all buttons from title bar&lt;br /&gt;
&lt;br /&gt;
;&#039;&#039;&#039;this.updatePageTitle()&#039;&#039;&#039;&lt;br /&gt;
:This function allows to update the current page title and turn description according to the game state arguments. If the current game state description this.gamedatas.gamestate.descriptionmyturn is modified before calling this function it allows to update the turn description without changing state. This will handle arguments substitutions properly.&lt;br /&gt;
&lt;br /&gt;
Note: this functional also will calls this.onUpdateActionButtons, if you want different buttons then state defaults, use method in example to replace them, if it becomes too clumsy use client states (see above)&lt;br /&gt;
&lt;br /&gt;
Example from Terra Mystica:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
onClickFavorTile: function( evt ) {&lt;br /&gt;
    ...&lt;br /&gt;
    if ( ... ) {&lt;br /&gt;
        this.gamedatas.gamestate.descriptionmyturn = _(&#039;Special action: &#039;) + _(&#039;Advance 1 space	on a Cult track&#039;);&lt;br /&gt;
        this.updatePageTitle();&lt;br /&gt;
        this.removeActionButtons();&lt;br /&gt;
        this.addActionButton( ... );&lt;br /&gt;
         ...&lt;br /&gt;
        return;&lt;br /&gt;
    }&lt;br /&gt;
    ...&lt;br /&gt;
&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== User preferences ==&lt;br /&gt;
&#039;&#039;&#039;this.getGameUserPreference(pref_id)&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Return the value of a user preference. It will return the value currently selected in the select combo box, in the top-right menu.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.setGameUserPreference(pref_id, value)&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Programmatically change a user preference. It will have the same effect as if the player changed the value in the select combo box, in the top-right menu.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.onGameUserPreferenceChanged&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
A callback you can define if you want to be notified when a user changes a user preference.&lt;br /&gt;
&lt;br /&gt;
Example:&amp;lt;pre&amp;gt;&lt;br /&gt;
onGameUserPreferenceChanged: function(pref_id, pref_value) {&lt;br /&gt;
  switch (pref_id) {&lt;br /&gt;
    case 201: &lt;br /&gt;
      document.getElementsByTagName(&#039;html&#039;)[0].classList.toggle(&#039;dark-background&#039;, pref_value == 2);&lt;br /&gt;
      break;&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Other useful stuff ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;dojo.hitch&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
With dojo.hitch, you can create a callback function that will run with your game object context whatever happen.&lt;br /&gt;
&lt;br /&gt;
Typical example: display a BGA confirmation dialog with a callback function created with dojo.hitch:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        this.confirmationDialog( _(&#039;Are you sure you want to make this?&#039;), dojo.hitch( this, function() {&lt;br /&gt;
            this.bgaPerformAction(&#039;makeThis&#039;);&lt;br /&gt;
        } ) );   &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In the example above, using dojo.hitch, we ensure that the &amp;quot;this&amp;quot; object will be set when the callback is called.&lt;br /&gt;
&lt;br /&gt;
NOTE: In modern JS there are lambdas that eliminate need for that, the example above will look like this&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        this.confirmationDialog( _(&#039;Are you sure you want to make this?&#039;), () =&amp;gt; this.bgaPerformAction( &#039;makeThis&#039;) );   &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
;&#039;&#039;&#039;onScreenWidthChange()&#039;&#039;&#039;&lt;br /&gt;
:This function can be overridden in your game to manage some resizing on the client side when the browser window is resized. This function is also triggered at load time, so it can be used to adapt to the :viewport size at the start of the game too.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
; this.bRealtime&lt;br /&gt;
: Return true if the game is in realtime. Note that having a distinct behavior in realtime and turn-based should be exceptional.&lt;br /&gt;
&lt;br /&gt;
; g_replayFrom&lt;br /&gt;
: Global contains replay number in live game, it is set to undefined (i.e. not set) when it is not a replay mode, so consequentially the good check is &#039;&#039;&#039;typeof g_replayFrom != &#039;undefined&#039;&#039;&#039;&#039; which returns true if the game is in replay mode &amp;lt;i&amp;gt;during the game&amp;lt;/i&amp;gt; (the game is ongoing but the user clicked &amp;quot;replay from this move&amp;quot; in the log)&lt;br /&gt;
&lt;br /&gt;
; g_archive_mode&lt;br /&gt;
: Returns true if the game is in archive mode &amp;lt;i&amp;gt;after the game&amp;lt;/i&amp;gt; (the game has ended)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
; this.instantaneousMode&lt;br /&gt;
: Returns true during replay/archive mode if animations should be skipped. Only needed if you are doing custom animations. (The BGA-provided animation functions like &amp;lt;i&amp;gt;this.slideToObject()&amp;lt;/i&amp;gt; automatically handle instantaneous mode.)&lt;br /&gt;
: Technically, when you click &amp;quot;replay from move #20&amp;quot;, the system replays the game from the very beginning with moves 0 - 19 happening in instantaneous mode and moves 20+ happening in normal mode.&lt;br /&gt;
&lt;br /&gt;
; g_tutorialwritten&lt;br /&gt;
: Returns an object like the below if the game is in tutorial mode, or undefined otherwise. Tutorial mode is a special case of archive mode where comments have been added to a previous game to teach new players the rules.&lt;br /&gt;
    {&lt;br /&gt;
        author: &amp;quot;91577332&amp;quot;,&lt;br /&gt;
        id: &amp;quot;576&amp;quot;,&lt;br /&gt;
        mode: &amp;quot;view&amp;quot;&lt;br /&gt;
        status: &amp;quot;alpha&amp;quot;&lt;br /&gt;
        version_override: null&lt;br /&gt;
        viewer_id: &amp;quot;84554161&amp;quot;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;getBgaEnvironment(): string&#039;&#039;&#039;&lt;br /&gt;
: Returns &amp;quot;studio&amp;quot; for studio and &amp;quot;prod&amp;quot; for production environment (i.e. where games current runs). Only useful for debbugging hooks.&lt;br /&gt;
Note: alpha server is also &amp;quot;prod&amp;quot;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Category:Studio]]&lt;/div&gt;</summary>
		<author><name>Sguzzer Gunayer</name></author>
	</entry>
	<entry>
		<id>https://en.doc.boardgamearena.com/index.php?title=Game_interface_logic:_Game.js&amp;diff=22733</id>
		<title>Game interface logic: Game.js</title>
		<link rel="alternate" type="text/html" href="https://en.doc.boardgamearena.com/index.php?title=Game_interface_logic:_Game.js&amp;diff=22733"/>
		<updated>2024-09-25T17:45:29Z</updated>

		<summary type="html">&lt;p&gt;Sguzzer Gunayer: /* Moving elements */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Studio_Framework_Navigation}}&lt;br /&gt;
&lt;br /&gt;
__TOC__&lt;br /&gt;
&lt;br /&gt;
This is the main file for your game interface. Here you will define:&lt;br /&gt;
&lt;br /&gt;
* Which actions on the page will generate calls to the server.&lt;br /&gt;
* What happens when you get a notification for a change from the server and how it will show in the browser. &lt;br /&gt;
* Setup user interface&lt;br /&gt;
&lt;br /&gt;
== File structure ==&lt;br /&gt;
&lt;br /&gt;
The details of how the file is structured are described below with comments in the code skeleton provided to you.&lt;br /&gt;
&lt;br /&gt;
Here is the basic structure:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;constructor&#039;&#039;&#039;: here you can define global variables for your whole interface.&lt;br /&gt;
* &#039;&#039;&#039;setup&#039;&#039;&#039;: this method is called when the page is refreshed, and sets up the game interface.&lt;br /&gt;
* &#039;&#039;&#039;onEnteringState&#039;&#039;&#039;: this method is called when entering a new game state. You can use it to customize the view for each game state.&lt;br /&gt;
* &#039;&#039;&#039;onLeavingState&#039;&#039;&#039;: this method is called when leaving a game state.&lt;br /&gt;
* &#039;&#039;&#039;onUpdateActionButtons&#039;&#039;&#039;: called on state changes, in order to add action buttons to the status bar. Note: in a multipleactiveplayer state, it will be called when another player has become inactive.&lt;br /&gt;
* &#039;&#039;(utility methods)&#039;&#039;: this is where you can define your utility methods.&lt;br /&gt;
* &#039;&#039;(player&#039;s actions)&#039;&#039;: this is where you can write your handlers for player actions on the interface (example: click on an item).&lt;br /&gt;
* &#039;&#039;&#039;setupNotifications&#039;&#039;&#039;: this method associates notifications with notification handlers. For each game notification, you can trigger a javascript method to handle it and update the game interface.&lt;br /&gt;
* &#039;&#039;(notification handlers)&#039;&#039;: this is where you define the notifications handlers associated with notifications in &#039;&#039;&#039;setupNotifications&#039;&#039;&#039;, above.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
More details:&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;setup(gamedatas: object)            &#039;&#039;&#039;&lt;br /&gt;
This method must set up the game user interface according to current game situation specified in parameters.&lt;br /&gt;
The method is called each time the game interface is displayed to a player, ie:&lt;br /&gt;
&lt;br /&gt;
* when the game starts&lt;br /&gt;
* when a player opens a game in the browser later &lt;br /&gt;
* when a player refreshes the game page (F5)&lt;br /&gt;
* when player does a server side Undo&lt;br /&gt;
&lt;br /&gt;
&amp;quot;gamedatas&amp;quot; argument contains all data retrieved by your &amp;quot;getAllDatas&amp;quot; PHP method and some more.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;onEnteringState(stateName: string, args: { args: any } | null): void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
This method is called each time we enter a new game state.&lt;br /&gt;
You can use this method to perform some user interface changes at this moment.&lt;br /&gt;
To access state arguments passed via calling php arg* method use args?.args.&lt;br /&gt;
Typically you would do something only for active player, using this.isCurrentPlayerActive() check.&lt;br /&gt;
It is also called (for the current game state only) when doing a browser refresh (after the setup method is called).&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Warning&#039;&#039;&#039;: for multipleactiveplayer states:&lt;br /&gt;
the active players are NOT active yet so you must use onUpdateActionButtons to perform the client side operation which depends on a player active/inactive status.&lt;br /&gt;
If you are doing initialization of some structures which do not depend on the active player, you can just replace (this.isCurrentPlayerActive()) with (!this.isSpectator) &lt;br /&gt;
for the main switch in that method.&lt;br /&gt;
&lt;br /&gt;
See more details in [[Your_game_state_machine:_states.inc.php#Difference_between_Single_active_and_Multi_active_states]]&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;onLeavingState(stateName: string): void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
This method is called each time we leave a game state.&lt;br /&gt;
You can use this method to perform some user interface changes at this point (i.e. cleanup).&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;onUpdateActionButtons(stateName: string, args: object | null): void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
In this method you can manage &amp;quot;action buttons&amp;quot; that are displayed in the action status bar and highlight active UI elements.&lt;br /&gt;
To access state arguments passed via calling php arg* method use &#039;&#039;&#039;args&#039;&#039;&#039; parameter. Note: args can be null! For &#039;&#039;&#039;game&#039;&#039;&#039; states and when you don&#039;t supply state args function - it is null.&lt;br /&gt;
This method is called when the active or multiactive player changes. In a classic &amp;quot;activePlayer&amp;quot; state this method is called before the onEnteringState state.&lt;br /&gt;
In multipleactiveplayer state it is a mess. The sequencing of calls depends on whether you get into that state from transitions OR from reloading the whole game (i.e. F5).&lt;br /&gt;
&lt;br /&gt;
See more details in [[Your_game_state_machine:_states.inc.php#Difference_between_Single_active_and_Multi_active_states]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Dojo framework ==&lt;br /&gt;
&lt;br /&gt;
BGA uses the [http://dojotoolkit.org/ Dojo Javascript framework].&lt;br /&gt;
&lt;br /&gt;
The Dojo framework allows us to do complex things more easily. The BGA framework uses Dojo extensively.&lt;br /&gt;
&lt;br /&gt;
To implement a game, you only need to use a few parts of the Dojo framework. All the Dojo methods you need are described on this page.&lt;br /&gt;
&lt;br /&gt;
== Javascript minimization (after July 2020) ==&lt;br /&gt;
&lt;br /&gt;
For performance reasons, when deploying a game the javascript code is minimized using &#039;&#039;&#039;terser&#039;&#039;&#039; (https://github.com/terser/terser). This minifier works with modern javascript syntax. From your project &amp;quot;Manage game&amp;quot; page, you can now test a minified version of your javascript on the studio (and revert to the original).&lt;br /&gt;
&lt;br /&gt;
NB: it has been reported that there is an issue with this minifier and percentage values for opacity.&lt;br /&gt;
&lt;br /&gt;
== Accessing Players Information ==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.player_id: number&#039;&#039;&#039;&lt;br /&gt;
id of the player who is looking at the game. The player may not be part of the game (i.e. spectator)&lt;br /&gt;
  if (notif.args.player_id == this.player_id) {&lt;br /&gt;
    ...&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.isSpectator: boolean&#039;&#039;&#039;&lt;br /&gt;
Flag set to true if the user at the table is a spectator (not a player).&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    if (this.isSpectator) {&lt;br /&gt;
        this.player_color = &#039;ffffff&#039;;&lt;br /&gt;
    } else {&lt;br /&gt;
        this.player_color = gamedatas.players[this.player_id].color;&lt;br /&gt;
    }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note: If you want to hide an element from spectators, you should use [[Game_interface_stylesheet:_yourgamename.css#spectatorMode|CSS &#039;spectatorMode&#039; class]].&lt;br /&gt;
&lt;br /&gt;
You may consider making a function like this, to detect if the game is in a read-only state (i.e. non-interactive):&lt;br /&gt;
  // Returns true for spectators, instant replay (during game), archive mode (after game end)&lt;br /&gt;
  isReadOnly: function () {&lt;br /&gt;
    return this.isSpectator || typeof g_replayFrom != &#039;undefined&#039; || g_archive_mode;&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.gamedatas: object&#039;&#039;&#039;&lt;br /&gt;
Contains the initial set of data to init the game, created at game start or by game refresh (F5).&lt;br /&gt;
You can update it as needed to keep an up-to-date reference of the game on the client side if you need it, however most of the time this is unnecessary.&lt;br /&gt;
&lt;br /&gt;
Note: In hotseat mode, the framework does not keep this.gamedatas of hotseat players and shares the same set as the main player to store data.&lt;br /&gt;
&lt;br /&gt;
Note: be careful when you update this data structurally, many framework functions expect data to be certain way and they will break if they see something else.&lt;br /&gt;
&lt;br /&gt;
Typical example of accessing player&#039;s info&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
for (var player_id in this.gamedatas.players) { &lt;br /&gt;
    var playerInfo = this.gamedatas.players [player_id];&lt;br /&gt;
    var c = playerInfo.color;&lt;br /&gt;
    var name = playerInfo.name;&lt;br /&gt;
    // do something &lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.isCurrentPlayerActive(): boolean&#039;&#039;&#039;&lt;br /&gt;
Returns true if the player on whose browser the code is running is currently active (it&#039;s his turn to play). Note: see remarks above about usage of this function inside onEnteringState method.&lt;br /&gt;
  if (this.isCurrentPlayerActive()) ...&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.getActivePlayerId(): number&#039;&#039;&#039;&lt;br /&gt;
Return the ID of the active player, or null if we are not in an &amp;quot;activeplayer&amp;quot; type state.&lt;br /&gt;
  if (this.player_id == this.getActivePlayerId()) ...&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.getActivePlayers(): number[]&#039;&#039;&#039;&lt;br /&gt;
Return an array with the IDs of players who are currently active (or an empty array if there are none).&lt;br /&gt;
&lt;br /&gt;
== Accessing and manipulating the DOM ==&lt;br /&gt;
&lt;br /&gt;
=== Element by Id ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;$(elementId: ElementOrId)&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
The $ function is used to get an HTML element using its &amp;quot;id&amp;quot; attribute.&lt;br /&gt;
&lt;br /&gt;
Example: modify the content of a &amp;quot;span&amp;quot; element:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
In your HTML code:&lt;br /&gt;
   &amp;lt;span id=&amp;quot;a_value_in_the_game_interface&amp;quot;&amp;gt;1234&amp;lt;/span&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In your Javascript code:&lt;br /&gt;
   $(&#039;a_value_in_the_game_interface&#039;).innerHTML = &amp;quot;9999&amp;quot;;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Note: It is safe to use if you don&#039;t know if variable is string (id of element) or element itself, i.e. &lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  foo: function(card) {&lt;br /&gt;
       card = $(card); // now its node, no need to write if (typeof card === &#039;string&#039;) ...&lt;br /&gt;
       // but its good idea to check for null here&lt;br /&gt;
       ...&lt;br /&gt;
  }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;getElementById(elementId: string)&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Note: $() is the standard method to access some HTML element with the BGA Framework. You can use &#039;&#039;&#039;getElementById&#039;&#039;&#039; but it is longer to type and less handy as it does not do some checks.&lt;br /&gt;
&lt;br /&gt;
=== Style ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;dojo.style(node: ElementOrId, styleName: string, styleValue: any): void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
With dojo.style you can modify the CSS property of any HTML element in your interface.&lt;br /&gt;
&lt;br /&gt;
Examples:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
     // Make an element disappear&lt;br /&gt;
     dojo.style( &#039;my_element&#039;, &#039;display&#039;, &#039;none&#039; );&lt;br /&gt;
&lt;br /&gt;
     // Give an element a 2px border&lt;br /&gt;
     dojo.style( &#039;my_element&#039;, &#039;borderWidth&#039;, &#039;2px&#039; );&lt;br /&gt;
&lt;br /&gt;
     // Change the background position of an element&lt;br /&gt;
     // (very practical when you are using CSS sprites to transform an element to another)&lt;br /&gt;
     dojo.style( &#039;my_element&#039;, &#039;backgroundPosition&#039;, &#039;-20px -50px&#039; );&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note: if you have to modify several CSS properties of an element, or if you have a complex CSS transformation to do, you should consider using dojo.addClass/dojo.removeClass (see below).&lt;br /&gt;
&lt;br /&gt;
You can also use object to set multiple values&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
dojo.setStyle(&amp;quot;thinger&amp;quot;, {&lt;br /&gt;
  &amp;quot;opacity&amp;quot;: 0.5,&lt;br /&gt;
  &amp;quot;border&amp;quot;: &amp;quot;3px solid black&amp;quot;,&lt;br /&gt;
  &amp;quot;height&amp;quot;: &amp;quot;300px&amp;quot;&lt;br /&gt;
});&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.addStyleToClass(cssClassName: string, styleName: string, styleValue: any):&#039;&#039;&#039; &#039;&#039;&#039;void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Same as dojo.style(), but for all the nodes set with the specified cssClassName&lt;br /&gt;
Equivalent of &lt;br /&gt;
  &lt;br /&gt;
  dojo.query(`.${aclass}`).style(styleName, styleValue)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
dojo.query(&amp;quot;#baz &amp;gt; div&amp;quot;).style({&lt;br /&gt;
  opacity:0.75,&lt;br /&gt;
  fontSize:&amp;quot;13pt&amp;quot;&lt;br /&gt;
});&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Vanilla JS style&#039;&#039;&#039;&lt;br /&gt;
  $(&#039;my_element&#039;).style.display=&#039;none&#039;; // set&lt;br /&gt;
  var display = $(&#039;my_element&#039;).style.display; // get&lt;br /&gt;
  $(&#039;my_element&#039;).style.removeProperty(&#039;display&#039;); // remove&lt;br /&gt;
&lt;br /&gt;
=== Classes ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;dojo.addClass(node: ElementOrId, classes: string): void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;dojo.removeClass(node: ElementOrId, classes: string): void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;dojo.hasClass(node: ElementOrId, aclass: string): void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;dojo.toggleClass(node: ElementOrId, aclass: string): void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
In many situations, many small CSS property updates can be replaced by a CSS class change (i.e., you add a CSS class to your element instead of applying all modifications manually).&lt;br /&gt;
&lt;br /&gt;
Advantages are:&lt;br /&gt;
* All your CSS stuff remains in your CSS file.&lt;br /&gt;
* You can add/remove a list of CSS modifications with a simple function and without error.&lt;br /&gt;
* You can test whether you applied the CSS to an element with the &#039;&#039;&#039;dojo.hasClass&#039;&#039;&#039; method.&lt;br /&gt;
&lt;br /&gt;
Example from &#039;&#039;Reversi&#039;&#039;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    // We add &amp;quot;possibleMove&amp;quot; to an element&lt;br /&gt;
    dojo.addClass( &#039;square_&#039;+x+&#039;_&#039;+y, &#039;possibleMove&#039; );&lt;br /&gt;
&lt;br /&gt;
    // In our CSS file, the class is defined as:&lt;br /&gt;
    .possibleMove {&lt;br /&gt;
      background-color: white;&lt;br /&gt;
      opacity: 0.2;&lt;br /&gt;
      filter:alpha(opacity=20); /* For IE8 and earlier */  &lt;br /&gt;
      cursor: pointer;  &lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
     // So we&#039;ve applied 4 CSS property changes in one line of code.&lt;br /&gt;
&lt;br /&gt;
     // ... and when we need to check if a square is a possible move on the client side:&lt;br /&gt;
     if( dojo.hasClass( &#039;square_&#039;+x+&#039;_&#039;+y, &#039;possibleMove&#039; ) )&lt;br /&gt;
     { ... }&lt;br /&gt;
&lt;br /&gt;
     // ... and if we want to remove all possible moves in one line of code (see &amp;quot;dojo.query&amp;quot; method):&lt;br /&gt;
     dojo.query( &#039;.possibleMove&#039; ).removeClass( &#039;possibleMove&#039; );&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Vanilla JS classList&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
This is the only exception where dojo versions are better&lt;br /&gt;
  // add class&lt;br /&gt;
  $(token_id).classList.addClass(&#039;possibleMove&#039;);&lt;br /&gt;
  // remove class&lt;br /&gt;
  $(token_id).classList.removeClass(&#039;possibleMove&#039;);&lt;br /&gt;
  // add 2 classes&lt;br /&gt;
  const myclasses = [&#039;a&#039;,&#039;b&#039;];&lt;br /&gt;
  $(token_id).classList.addClass(...myclasses);&lt;br /&gt;
  // add classes to query result&lt;br /&gt;
  document.querySelectorAll(&amp;quot;.hand .card&amp;quot;).forEach((node)=&amp;gt;node.classList.addClass(&#039;possibleMove&#039;));&lt;br /&gt;
&lt;br /&gt;
=== Attributes ===&lt;br /&gt;
&lt;br /&gt;
;dojo.attr&lt;br /&gt;
&lt;br /&gt;
With dojo.attr you can access or change the value of an attribute or property of any HTML element in your interface.&lt;br /&gt;
&lt;br /&gt;
Exemple:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
     // Get the title of a node&lt;br /&gt;
     var title = dojo.attr( id, &#039;title&#039; );&lt;br /&gt;
     // Change the height of a node&lt;br /&gt;
     dojo.attr( &#039;img_growing_tree&#039;, &#039;height&#039;, 100 );&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Vanilla JS attr&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
   $(token).id=new_id; // set attr for &amp;quot;id&amp;quot;&lt;br /&gt;
   var id = $(token).id; // get&lt;br /&gt;
&lt;br /&gt;
=== Queries ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;dojo.query(cssSelector: string): Element[]&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
With dojo.query, you can query a bunch of HTML elements with a single function, with a &amp;quot;CSS selector&amp;quot; style.&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
     // All elements with class &amp;quot;possibleMove&amp;quot;:&lt;br /&gt;
     var elements = dojo.query( &#039;.possibleMove&#039; );&lt;br /&gt;
&lt;br /&gt;
     // Count number of tokens (i.e., elements of class &amp;quot;token&amp;quot;) on the board (i.e., the element with id &amp;quot;board&amp;quot;):&lt;br /&gt;
     dojo.query( &#039;#board .token&#039; ).length;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
But what is really cool with dojo.query is that you can combine it with almost all methods above.&lt;br /&gt;
&lt;br /&gt;
Examples:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
     // Trigger a method when the mouse enter in any element with class &amp;quot;meeple&amp;quot;:&lt;br /&gt;
     dojo.query( &#039;.meeple&#039; ).connect( &#039;onmouseenter&#039;, this, &#039;myMethodToTrigger&#039; );&lt;br /&gt;
&lt;br /&gt;
     // Hide all meeples who are on the board&lt;br /&gt;
     dojo.query( &#039;#board .meeple&#039; ).style( &#039;display&#039;, &#039;none&#039; );&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Vanilla JS query&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
  var cards=document.querySelectorAll(&amp;quot;.hand .card&amp;quot;);// all cards in all hands&lt;br /&gt;
  var cards=$(&#039;hand&#039;).querySelectorAll(&amp;quot;.card&amp;quot;);// all cards in specific hand&lt;br /&gt;
  var card=document.querySelector(&amp;quot;.hand .card&amp;quot;);// first card or null if none (super handy)&lt;br /&gt;
&lt;br /&gt;
=== Creating and Destroying elements ===&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;dojo.empty(node: ElementOrId)&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Remove all children of the node element&lt;br /&gt;
   dojo.empty(&#039;my_hand&#039;);&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;dojo.destroy(node: ElementOrId)&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Remove the element&lt;br /&gt;
   dojo.destroy(&#039;my_token&#039;);&lt;br /&gt;
&lt;br /&gt;
   dojo.query(&amp;quot;.green&amp;quot;, mynode).forEach(dojo.destroy); // this remove all subnode of class green from mynode&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;dojo.create(tag: string, attributes?: obj, parent?: ElementOrId): Element&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Create element&lt;br /&gt;
&lt;br /&gt;
    dojo.create(&amp;quot;div&amp;quot;, { class: &amp;quot;yellow_arrow&amp;quot; }, parent); // this creates div with class yellow_array and places it in &amp;quot;parent&amp;quot;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.format_block(name: string, args: object): string&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
This bga function that takes global var from template file and substitute variables, typical use would be&lt;br /&gt;
&lt;br /&gt;
                var player = gamedatas.players[player_id];&lt;br /&gt;
                var div = this.format_block(&#039;jstpl_player_board&#039;, player ); // var jstpl_player_board = ... is defined in .tpl file &lt;br /&gt;
Note: result is trimmed&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.format_string(name: string, args: object): string&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
This bga function just substitute variables in a string, i.e.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
     var div = this.format_string(&#039;&amp;lt;div color=&amp;quot;${player_color}&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&#039;, {player_color: &#039;#ff0000&#039;} );&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Note: result is trimmed&lt;br /&gt;
&lt;br /&gt;
Note: this can be replaced by using backquoted string now: &lt;br /&gt;
     const player_color =  &#039;#ff0000&#039;;&lt;br /&gt;
&lt;br /&gt;
    const div = ``;&lt;br /&gt;
&#039;&#039;&#039;this.format_string_recursive&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
This bga function is similar to this.format_string but is capable of processing recursive argument structures and translations. It is used to format server notifications.&lt;br /&gt;
&lt;br /&gt;
TODO: find better place for these function docs&lt;br /&gt;
&lt;br /&gt;
=== Moving elements ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;dojo.place(node: string | Element, refNode: ElementOrId, pos?: string | number): Element&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
dojo.place is the best function to insert HTML code somewhere in your game interface without breaking something. It is much better to use than the &#039;&#039;&#039;innerHTML=&#039;&#039;&#039; method if you must insert HTML tags and not only values.&lt;br /&gt;
&lt;br /&gt;
node: can be a string or a DOM node. If it is a string starting with “&amp;lt;”, it is assumed to be an HTML fragment, which will be created. Otherwise it is assumed to be an id of a DOM node. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
     // Insert your HTML code as a child of a container element&lt;br /&gt;
     dojo.place( &amp;quot;&amp;lt;div class=&#039;foo&#039;&amp;gt;&amp;lt;/div&amp;gt;&amp;quot;, &amp;quot;your_container_element_id&amp;quot; );&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
pos: optional argument. Can be a number or one of the following strings: “before”, “after”, “replace”, “only”, “first”, or “last”. If omitted, “last” is assumed.&lt;br /&gt;
&lt;br /&gt;
* &amp;quot;replace&amp;quot;: replace the container element with my_node element&lt;br /&gt;
* &amp;quot;first&amp;quot;: places the node as a child of the reference node. The node is placed as the first child.&lt;br /&gt;
* &amp;quot;last&amp;quot; (default): places the node as a child of the reference node. The node is placed as the last child.&lt;br /&gt;
* &amp;quot;before&amp;quot;: places the node right before the reference node.&lt;br /&gt;
* &amp;quot;after&amp;quot;: places the node right after the reference node.&lt;br /&gt;
* &amp;quot;only&amp;quot;: replaces all children of the reference node with the node.&lt;br /&gt;
&lt;br /&gt;
this parameter can be a positive integer. In this case, the node will be placed as a child of the reference node with this number (counting from 0). If the number is more than number of children, the node will be appended to the reference node making it the last child. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
     // Replace all children of container with my_node &lt;br /&gt;
     dojo.place( $(&#039;my_node&#039;), &amp;quot;your_container_element_id&amp;quot;, &amp;quot;only&amp;quot; );&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
See also full doc on dojo.place: [https://dojotoolkit.org/reference-guide/1.7/dojo/place.html]&lt;br /&gt;
&lt;br /&gt;
Usually, when you want to insert some piece of HTML in your game interface, you should use &amp;quot;[[Game_layout:_view_and_template:_yourgamename.view.php_and_yourgamename_yourgamename.tpl#Javascript_templates|Javascript templates]]&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
But you can also relocate elements like that. Note: it won&#039;t animate if you do that.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.placeOnObject(mobile_obj: ElementOrId, target_obj: ElementOrId): void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
places mobile_obj on target_obj, set the absolute positions and centers the mobile_obj on target_obj,&lt;br /&gt;
effect is immediate&lt;br /&gt;
&lt;br /&gt;
This is not really an animation, but placeOnObject is frequently used before starting an animation.&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  // (We just created an object &amp;quot;my_new_token&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
  // Place the new token on current player board&lt;br /&gt;
  this.placeOnObject( &amp;quot;my_new_token&amp;quot;, &amp;quot;overall_player_board_&amp;quot;+this.player_id );&lt;br /&gt;
  &lt;br /&gt;
  // Then slide it to its position on the board&lt;br /&gt;
  this.slideToObject( &amp;quot;my_new_token&amp;quot;, &amp;quot;a_place_on_board&amp;quot; ).play();&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.placeOnObjectPos(mobile_obj: ElementOrId, target_obj: ElementOrId, target_x: number, target_y: number): void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
This method works exactly like placeOnObject, except than you can specify some (x,y) coordinates (in px). This way, the center of &amp;quot;mobile_obj&amp;quot; will be placed to the specified x,y position relatively to the center of &amp;quot;target_obj&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Note: the placement works differently from this.slideToObjectPos&#039;&#039;, since coordinates are calculated based on the center of objects.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.attachToNewParent(mobile_obj: ElementOrId, target_obj: ElementOrId): void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
With this method, you change the HTML parent of &amp;quot;mobile_obj&amp;quot; element without moving it. &lt;br /&gt;
&amp;quot;target_obj&amp;quot; is the new parent of this element. The beauty of &lt;br /&gt;
attachToNewParent is that the mobile_obj element DOES NOT MOVE during this process.&lt;br /&gt;
&lt;br /&gt;
What happens is that the method calculate a relative position of mobile_obj to make sure it does not move after the HTML parent changes.&lt;br /&gt;
&lt;br /&gt;
Why using this method?&lt;br /&gt;
&lt;br /&gt;
Changing the HTML parent of an element can be useful for the following reasons:&lt;br /&gt;
* When the HTML parent moves, all its child are moving with them. If some game elements is no more linked with a parent HTML object, you may want to attach it to another place.&lt;br /&gt;
* The z_order (vertical order of display) depends on the position in the DOM, so you may need to change the parent of some game elements when they are moving in your game area.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;CAREFUL&#039;&#039;&#039;: this function destroys original object and places a clone onto a new parent, this will break all references to this HTML element (ex: dojo.connect).&lt;br /&gt;
If you need version that does not destroy the object but the same otherwise see [[BGA_Studio_Cookbook#Attach_to_new_parent_without_destroying_the_object]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Animations ==&lt;br /&gt;
&lt;br /&gt;
===Dojo Animations===&lt;br /&gt;
&lt;br /&gt;
BGA animations is based on Dojo Animation ([http://dojotoolkit.org/documentation/tutorials/1.8/animation/ see tutorial here]).&lt;br /&gt;
&lt;br /&gt;
However, most of the time, you can just use methods below, which are built on top of Dojo Animation.&lt;br /&gt;
&lt;br /&gt;
Note: one interesting method from Dojo that could be useful from time to time is &amp;quot;Dojo.Animation&amp;quot;. It allows you to make any CSS property &amp;quot;slide&amp;quot; from one value to another.&lt;br /&gt;
&lt;br /&gt;
Note 2: the slideTo methods are not compatible with CSS transform (scale, zoom, rotate...). If possible, avoid using CSS transform on nodes that are being slided. Eventually, the only possible solution to make these 2 compatible is to disable all CSS transform properties, use slideToObjectPos/placeOnObjectPos, and then apply them again.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Sliding===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.slideToObject(mobile_obj: ElementOrId, target_obj: ElementOrId, duration?: number, delay?: number): Animation&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
You can use slideToObject to &amp;quot;slide&amp;quot; an element to a target position.&lt;br /&gt;
&lt;br /&gt;
Sliding element on the game area is the recommended and the most used way to animate your game interface. Using slides allow players to figure out what is happening on the game, as if they were playing with the real boardgame.&lt;br /&gt;
&lt;br /&gt;
The parameters are:&lt;br /&gt;
* mobile_obj: the ID of the object to move. This object must be &amp;quot;relative&amp;quot; or &amp;quot;absolute&amp;quot; positioned.&lt;br /&gt;
* target_obj: the ID of the target object. This object must be &amp;quot;relative&amp;quot; or &amp;quot;absolute&amp;quot; positioned. Note that it is not mandatory that mobile_obj and target_obj have the same size. If their size are different, the system slides the center of mobile_obj to the center of target_obj.&lt;br /&gt;
* duration: (optional) defines the duration in millisecond of the slide. The default is 500 milliseconds.&lt;br /&gt;
* delay: (optional). If you defines a delay, the slide will start only after this delay. This is particularly useful when you want to slide several object from the same position to the same position: you can give a 0ms delay to the first object, a 100ms delay to the second one, a 200ms delay to the third one, ... this way they won&#039;t be superposed during the slide.&lt;br /&gt;
&lt;br /&gt;
BE CAREFUL: The method returns an dojo.fx animation, so you can combine it with other animation if you want to. It means that you have to call the &amp;quot;play()&amp;quot; method, otherwise the animation WON&#039;T START.&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
   this.slideToObject( &amp;quot;some_token&amp;quot;, &amp;quot;some_place_on_board&amp;quot; ).play();&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.slideToObjectPos(mobile_obj: ElementOrId, target_obj: ElementOrId, target_x: number, target_y: number, duration?: number, delay?: number): Animation&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
This method does exactly the same as &amp;quot;slideToObject&amp;quot;, except than you can specify some (x,y) coordinates. This way, &amp;quot;mobile_obj&amp;quot; will slide to the specified x,y position relatively to &amp;quot;target_obj&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
Example: slide a token to some place on the board, 10 pixels from the top:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
   this.slideToObjectPos( &amp;quot;some_token&amp;quot;, &amp;quot;some_place_on_board&amp;quot;, 0, 10 ).play();&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.slideTemporaryObject(mobile_obj_html: string, parent: ElementOrId, from: ElementOrId, to: ElementOrId, duration?: number, delay?: number): Animation&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
This method is useful when you want to slide a temporary HTML object from one place to another. As this object does not exists before the animation and won&#039;t remain after, it could be complex to create this object (with dojo.place), to place it at its origin (with placeOnObject) to slide it (with slideToObject) and to make it disappear at the end.&lt;br /&gt;
&lt;br /&gt;
slideTemporaryObject does all of this for you:&lt;br /&gt;
* mobile_obj_html is a piece of HTML code that represent the object to slide.&lt;br /&gt;
* parent is the ID of an HTML element of your interface that will be the parent of this temporary HTML object.&lt;br /&gt;
* from is the ID of the origin of the slide.&lt;br /&gt;
* to is the ID of the target of the slide.&lt;br /&gt;
* duration/delay works exactly like in &amp;quot;slideToObject&amp;quot;&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
this.slideTemporaryObject( &#039;&amp;lt;div class=&amp;quot;token_icon&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&#039;, &#039;tokens&#039;, &#039;my_origin_div&#039;, &#039;my_target_div&#039; ).play();&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Destroy===&lt;br /&gt;
&#039;&#039;&#039;this.slideToObjectAndDestroy(mobile_obj: ElementOrId, target_obj: ElementOrId, duration?: number, delay?: number): void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
This method is a handy shortcut to slide an existing HTML object to some place then destroy it upon arrival. It can be used for example to move a victory token or a card from the board to the player panel to show that the player earns it, then destroy it when we don&#039;t need to keep it visible on the player panel.&lt;br /&gt;
&lt;br /&gt;
It works the same as this.slideToObject and takes the same arguments, but it starts the animation. &lt;br /&gt;
&lt;br /&gt;
CAREFUL: Make sure nothing is creating the same object at the same time the animation is running, because this will cause some random disappearing effects&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
this.slideToObjectAndDestroy( &amp;quot;some_token&amp;quot;, &amp;quot;some_place_on_board&amp;quot;, 1000, 0 );&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.fadeOutAndDestroy( node: string | Element, duration?: number, delay?: number):&#039;&#039;&#039; &#039;&#039;&#039;void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
This function fade out the target node, then destroy it. Its starts the animation.&lt;br /&gt;
* duration/delay works exactly like in &amp;quot;slideToObject&amp;quot;&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
   this.fadeOutAndDestroy( &amp;quot;a_card_that_must_disappear&amp;quot; );&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
CAREFUL: the HTML node still exists until during few milliseconds, until the fadeOut has been completed.&lt;br /&gt;
Make sure nothing is creating same object at the same time as animation is running, because you will be some random dissapearing effects&lt;br /&gt;
&lt;br /&gt;
===Rotating elements===&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
This example combines &amp;quot;Dojo.Animation&amp;quot; method and a CSS property transform that allow you to rotate the element.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
// node is Element we rotating&lt;br /&gt;
		    var animation = new dojo.Animation({&lt;br /&gt;
			    curve: [fromDegree, toDegree],&lt;br /&gt;
			    onAnimate: (v) =&amp;gt; {&lt;br /&gt;
				    node.style.transform = &#039;rotate(&#039; + v + &#039;deg)&#039;;&lt;br /&gt;
			    } &lt;br /&gt;
		    });&lt;br /&gt;
		    &lt;br /&gt;
		    animation.play();  &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
BGA has its own interface to rotate&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.rotateTo(node: string | Element, degree: number): void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
It starts the animation, and stored the rotation degree in the class, so next time you rotate object - it is additive.&lt;br /&gt;
There is no animation hooks in this one, if you need to change any parameters use dojo animation above.&lt;br /&gt;
&lt;br /&gt;
There is also &#039;&#039;&#039;rotateInstantTo&#039;&#039;&#039; with same signature which does not animate&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Animation Callbacks===&lt;br /&gt;
&lt;br /&gt;
If you wish to run some code only after an animation has completed you can do this by linking a callback method to &#039;onEnd&#039;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
var animation_id = this.slideToObject( mobile_obj, target_obj, 500 );&lt;br /&gt;
dojo.connect(animation_id, &#039;onEnd&#039;, () =&amp;gt; {&lt;br /&gt;
   // do something here&lt;br /&gt;
});&lt;br /&gt;
animation_id.play();&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If you wish to call a second animation after the first (rather than general code) then you can use a dojo animation chain (see tutorial referenced above).&lt;br /&gt;
&lt;br /&gt;
== Players input ==&lt;br /&gt;
&lt;br /&gt;
=== Connecting ===&lt;br /&gt;
&#039;&#039;&#039;dojo.connect(element: Element, event: string, context: object, method: eventHandler): any&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;dojo.connect(element: Element, event: string, hander: eventHandler): any&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Used to associate a player event with one of your notification methods.&lt;br /&gt;
&lt;br /&gt;
Example: associate a click on an element (&amp;quot;my_element&amp;quot;) with one of our methods (&amp;quot;onClickOnMyElement&amp;quot;):&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
      dojo.connect( $(&#039;my_element&#039;), &#039;onclick&#039;, this, &#039;onClickOnMyElement&#039; );&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Same idea but base on query (i.e. all element of &#039;pet&#039; class)&lt;br /&gt;
      dojo.query(&amp;quot;.pet&amp;quot;).connect(&#039;onclick&#039;, this, &#039;onPet&#039;);&lt;br /&gt;
&lt;br /&gt;
Note: if you need to disconnect the handler you have to store handler returned from this method, i.e.&lt;br /&gt;
   &lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    var handler = dojo.connect(...);&lt;br /&gt;
    ...&lt;br /&gt;
    dojo.disconnect(handler);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If you don&#039;t store the handler - you have to destroy the object to disconnect it&lt;br /&gt;
&lt;br /&gt;
Typical function that implements the input handler will look like this&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
onPet: function(event) {&lt;br /&gt;
    var id = event.currentTarget.id;&lt;br /&gt;
    console.log(&#039;onPet &#039; + id);&lt;br /&gt;
    dojo.stopEvent(event);&lt;br /&gt;
    if (this.gamedatas.gamestate.name == &#039;playerTurnPet&#039;) {&lt;br /&gt;
          this.bgaPerformAction(&#039;actPlayPet&#039;, {card: id});&lt;br /&gt;
    } else {&lt;br /&gt;
          this.showMoveUnauthorized();&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.connect(element: ElementOrId, event: string, method: eventHandler): void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Used to associate a player event with one of your notification methods.&lt;br /&gt;
&lt;br /&gt;
      this.connect( $(&#039;my_element&#039;), &#039;onclick&#039;, &#039;onClickOnMyElement&#039; );&lt;br /&gt;
&lt;br /&gt;
Or you can use an in-place handler&lt;br /&gt;
&lt;br /&gt;
      this.connect( $(&#039;my_element&#039;), &#039;onclick&#039;, (e) =&amp;gt; { console.log(&#039;boo&#039;); } );&lt;br /&gt;
&lt;br /&gt;
Note that this function stores the connection handler. That is the only real difference between &#039;&#039;&#039;this.connect&#039;&#039;&#039; and &#039;&#039;&#039;dojo.connect&#039;&#039;&#039;. If you plan to destroy the element you connected, you &#039;&#039;&#039;must&#039;&#039;&#039; call this.disconnect() to prevent memory leaks.&lt;br /&gt;
This function is mainly for permanent objects - if you just want to connect the temp object you should probably not use this method but use dojo.connect which won&#039;t require any clean-up.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.connectClass(cssClassName: string, event: string, method: eventHandler): void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Same as connect(), but for all the nodes set with the specified cssClassName.&lt;br /&gt;
&lt;br /&gt;
	this.connectClass(&#039;pet&#039;, &#039;onclick&#039;, &#039;onPet&#039;);&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.disconnect(element: ElementOrId, event: string): void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Disconnect event handler (previously registered with this.connect or this.connectClass).&lt;br /&gt;
&lt;br /&gt;
   this.disconnect( $(&#039;my_element&#039;), &#039;onclick&#039;);&lt;br /&gt;
&lt;br /&gt;
Note: dynamic connect/disconnect is for advanced cases ONLY, you should always connect elements statically if possible, i.e. in setup() method.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.disconnectAll(): void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Disconnect all previously registed event handlers (registered via this.connect or this.connectClass)&lt;br /&gt;
&lt;br /&gt;
  this.disconnectAll();&lt;br /&gt;
&lt;br /&gt;
=== Actions ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.bgaPerformAction(action: string, args?: object, options: object = { lock: true, checkAction: true }): Promise&amp;lt;void&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Triggers an action on the backend. This is a combination of checkAction and ajaxcall, returning a Promise which resoves when ajaxcall ends.&lt;br /&gt;
&lt;br /&gt;
This method must be used to send a player input to the game server. &#039;&#039;&#039;It should not be triggered programmatically&#039;&#039;&#039;, especially not in loops, in callbacks, in notifications, or in onEnteringState/onUpdateActionButtons/onLeavingState, in order not to create race conditions or break replay game and tutorial features. It should be used only in reaction to a user action in the interface.&lt;br /&gt;
&lt;br /&gt;
* action: name of the action, as it is written in &amp;quot;possibleactions&amp;quot; of the current state.&lt;br /&gt;
* args: an object containing the call parameters to send to the action&lt;br /&gt;
* options: options to tweak the call with some defaults. Default is &amp;lt;code&amp;gt;{ lock: true, checkAction: true }&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Example of a standard call without args:&lt;br /&gt;
  this.bgaPerformAction(&#039;pass&#039;);&lt;br /&gt;
&lt;br /&gt;
Example of a standard call with action args:&lt;br /&gt;
  this.bgaPerformAction(&#039;actPlayCard&#039;, { id: this.selectedCardId });&lt;br /&gt;
&lt;br /&gt;
Example of a call without checking action (because player is inactive in a multiactive state):&lt;br /&gt;
&lt;br /&gt;
 this.bgaPerformAction(&#039;actChangeMind&#039;, {}, { checkAction: false });&lt;br /&gt;
&lt;br /&gt;
Example of a call without lock (because of a special action not directly related to the game flow):&lt;br /&gt;
&lt;br /&gt;
 this.bgaPerformAction(&#039;actSetAutoBid&#039;, { alwaysBidUntil: 500 }, { lock: false, checkAction: false });&lt;br /&gt;
&lt;br /&gt;
Example of call with reaction to exception:&lt;br /&gt;
  this.bgaPerformAction(&#039;actPlayCard&#039;, { id: this.selectedCardId }).catch(()=&amp;gt;{ this.selectedCardId = undefined; });&lt;br /&gt;
&lt;br /&gt;
Example of call with reaction to success:&lt;br /&gt;
  this.bgaPerformAction(&#039;actPlayCard&#039;, { id: this.selectedCardId }).then(()=&amp;gt;{ this.unselectAll(); });&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.ajaxcall(url, parameters, obj_callback, callback, callback_anycase?, ajax_method?: string)&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Note: bgaPerformAction is a simpler way to use ajax calls, ajaxcall stays in the doc for legacy reasons only and should not be used in new projects.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Same warning as &#039;&#039;&#039;this.bgaPerformAction&#039;&#039;&#039; about using on user action only.&lt;br /&gt;
&lt;br /&gt;
* url: the url of the action to perform. For a game, it must be: &amp;quot;/&amp;lt;mygame&amp;gt;/&amp;lt;mygame&amp;gt;/myAction.html&amp;quot;&lt;br /&gt;
* parameters: an array of parameter to send to the game server. &lt;br /&gt;
** Note that &amp;quot;lock: true&amp;quot; must always be specified in this list of parameters in order the interface can be locked during the server call. Cannot use lock: false - to not lock it has to be undefined.&lt;br /&gt;
** Note: Restricted parameter names (please don&#039;t use them):&lt;br /&gt;
*** &amp;quot;action&amp;quot;&lt;br /&gt;
*** &amp;quot;module&amp;quot;&lt;br /&gt;
*** &amp;quot;class&amp;quot;&lt;br /&gt;
* obj_callback: must be set to &amp;quot;this&amp;quot;.&lt;br /&gt;
* callback (non-optional but rarely used): a function to trigger when the server returns result and everything went fine (not used, as all data handling is done via notifications).&lt;br /&gt;
* callback_anycase: (optional) a function to trigger when the server returns ok OR error.  If no error this function is called with parameter value false. If an error occurred, the first parameter will be set to true, the second will contain the error message sent by the PHP back-end, and the third will contain an error code.&lt;br /&gt;
* ajax_method: (optional and rarely used) if you need to send large amounts of data (over 2048 bytes), you can set this parameter to &#039;post&#039; (all lower-case) to send a POST request as opposed to the default GET. This works, but was not officially documented, so only use if you really need to.&lt;br /&gt;
&lt;br /&gt;
Usage:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
this.ajaxcall( &#039;/mygame/mygame/actMyAction.html&#039;, { lock: true, &lt;br /&gt;
   arg1: myarg1, &lt;br /&gt;
   arg2: myarg2&lt;br /&gt;
}, this, (result)=&amp;gt;{} );&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.checkAction(action: string, nomessage?: boolean): boolean &#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Check if player can do the specified action by taking into account:&lt;br /&gt;
* if interface is locked it will return false and show message &amp;quot;An action is already in progress&amp;quot;,  unless nomessage set to true &lt;br /&gt;
* if player is not active it will return false and show message &amp;quot;This is not your turn&amp;quot;, unless nomessage set to true &lt;br /&gt;
* if action is not in list in possible actions (defined by &amp;quot;possibleaction&amp;quot; in current game state) it will return false and show &amp;quot;This move is not authorized now&amp;quot; error (unconditionally).&lt;br /&gt;
* otherwise returns true&lt;br /&gt;
Example:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  function onClickOnGameElement( evt )  {&lt;br /&gt;
     if( this.checkAction( &amp;quot;actMyAction&amp;quot; ) ) {&lt;br /&gt;
        // Do the action&lt;br /&gt;
     }&lt;br /&gt;
  }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.checkPossibleActions(action: string): boolean&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
* this is independent of the player being active, so can be used instead of this.checkAction(). This is particularly useful for multiplayer states when the player is not active in a &#039;player may like to change their mind&#039; scenario. Unlike this.checkAction, this function does NOT take interface locking into account &lt;br /&gt;
&lt;br /&gt;
* if action is not in list in possible actions (defined by &amp;quot;possibleaction&amp;quot; in current game state) it will return false and show &amp;quot;This move is not authorized now&amp;quot; error (unconditionally).&lt;br /&gt;
* otherwise returns true&lt;br /&gt;
&lt;br /&gt;
  function onChangeMyMind( evt )  {&lt;br /&gt;
     if( this.checkPossibleActions( &amp;quot;actMyAction&amp;quot; ) ) {&lt;br /&gt;
        // Do the action&lt;br /&gt;
     }&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.checkLock(nomessage?: boolean): boolean&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
When using &amp;quot;lock: true&amp;quot; in ajax call you can use this function to check if interface is in lock state (it will be locked during server call and notification processing).&lt;br /&gt;
This check can be used to block some other interactions which do not result in ajaxcall or if you want to suppress errors. Note: normally you only need to use this.checkAction(...), this is for advanced cases.&lt;br /&gt;
&lt;br /&gt;
It will also show error unless nomessage is set to true&lt;br /&gt;
&lt;br /&gt;
  function onChangeMyMind( evt )  {&lt;br /&gt;
     if( this.checkLock() ) {&lt;br /&gt;
        // Do the action&lt;br /&gt;
     }&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
== Notifications ==&lt;br /&gt;
&lt;br /&gt;
When something happens on the server side, your game interface Javascript logic received a notification.&lt;br /&gt;
If you have not done so yet check what notification are in [[Main_game_logic:_yourgamename.game.php#Notifications]]&lt;br /&gt;
&lt;br /&gt;
Here&#039;s how you can handle these notifications on the client side.&lt;br /&gt;
&lt;br /&gt;
=== Subscribe to notifications ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;dojo.subscribe(notif_type: string, callback_obj: Object, handler: string|handler)&#039;&#039;&#039;&lt;br /&gt;
* notif_type - notification type/name send by php server&lt;br /&gt;
* callback_obj - usually this&lt;br /&gt;
* handler - if string method of callback_obj with name name is called, when notification is called, with notification object as parameter (see below)&lt;br /&gt;
&lt;br /&gt;
Your Javascript &amp;quot;setupNotifications&amp;quot; method is the place where you can subscribe to notifications from your PHP code.&lt;br /&gt;
&lt;br /&gt;
Here&#039;s how you associate one of your Javascript method to a notification &amp;quot;playDisc&amp;quot; (from Reversi example):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
   setupNotifications: function() {&lt;br /&gt;
      ...&lt;br /&gt;
      dojo.subscribe(&#039;playDisc&#039;, this, &amp;quot;notif_playDisc&amp;quot;);&lt;br /&gt;
   },&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note: the &amp;quot;playDisc&amp;quot; corresponds to the name of the notification you define it in your PHP code, in your &amp;quot;notifyAllPlayers&amp;quot; or &amp;quot;notifyPlayer&amp;quot; method.&lt;br /&gt;
&lt;br /&gt;
Then, you have to define your &amp;quot;notif_playDisc&amp;quot; method:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
   notif_playDisc: function(notif) {&lt;br /&gt;
     // Remove current possible moves (makes the board more clear)&lt;br /&gt;
     dojo.query( &#039;.possibleMove&#039; ).removeClass( &#039;possibleMove&#039; );          &lt;br /&gt;
     this.addDiscOnBoard( notif.args.x, notif.args.y, notif.args.player_id );&lt;br /&gt;
   },&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In a notification handler like our &amp;quot;notif_playDisc&amp;quot; method, you can access all notifications arguments with &amp;quot;notif.args&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&lt;br /&gt;
PHP&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    $this-&amp;gt;notifyAllPlayers( &amp;quot;apples&amp;quot;, clienttranslate(&#039;player takes ${count} apples&#039;), [ &amp;quot;count&amp;quot; =&amp;gt; 3 ] );&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
JavaScript&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    setupNotifications: function() {&lt;br /&gt;
       dojo.subscribe( &#039;apples&#039;, this, &#039;notif_apples&#039; );&lt;br /&gt;
    },&lt;br /&gt;
&lt;br /&gt;
    notif_apples: function(notif) {&lt;br /&gt;
      //You can access the &amp;quot;count&amp;quot; like this:&lt;br /&gt;
       alert(&amp;quot;count = &amp;quot; + notif.args.count);&lt;br /&gt;
    }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== The notification Object received by client ===&lt;br /&gt;
&lt;br /&gt;
When sending a notification on your PHP, the client side will receive an Object with the following attributes:&lt;br /&gt;
&lt;br /&gt;
* type - type of the notification (as passed by php function)&lt;br /&gt;
* log - the log string passed from php notification&lt;br /&gt;
* args - This is the arguments that you passed on your notification method on php&lt;br /&gt;
* bIsTableMsg - is true when you use [[Main_game_logic:_yourgamename.game.php#NotifyAllPlayers|NotifyAllPlayers]] method (false otherwise)&lt;br /&gt;
* channelorig - information about table ID (formatted as : &amp;quot;/table/t[TABLE_NUMBER]&amp;quot;)&lt;br /&gt;
* gamenameorig - name of the game&lt;br /&gt;
* move_id - ID of the move associated with the notification&lt;br /&gt;
* table_id - ID of the table (comes as string)&lt;br /&gt;
* time - UNIX GMT timestamp&lt;br /&gt;
* uid - unique identifier of the notification&lt;br /&gt;
* h - unknown&lt;br /&gt;
&lt;br /&gt;
&#039;&#039; Note that those information were inferred from observation on console log. If an Admin can confirm/correct (and remove this line), you&#039;re welcome :)&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
=== Ignoring notifications ===&lt;br /&gt;
&lt;br /&gt;
Sometimes you need to ignore some notification on client side. You don&#039;t want them to be shown in game log and you don&#039;t want them to be handled.&lt;br /&gt;
&lt;br /&gt;
The most common use case is when a player gets private information. They will receive a specific notification (such as &amp;quot;You received Ace of Heart&amp;quot;), while other players would receive more generic notification (&amp;quot;Player received a card&amp;quot;).&lt;br /&gt;
&lt;br /&gt;
In X.game.php&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        $this-&amp;gt;notifyAllPlayers(&amp;quot;dealCard&amp;quot;, clienttranslate(&#039;${player_name} received a card&#039;), [&lt;br /&gt;
            &#039;player_id&#039; =&amp;gt; $playerId,&lt;br /&gt;
            &#039;player_name&#039; =&amp;gt; $this-&amp;gt;getActivePlayerName()&lt;br /&gt;
        ]);&lt;br /&gt;
&lt;br /&gt;
        $this-&amp;gt;notifyPlayer($playerId, &amp;quot;dealCardPrivate&amp;quot;, clienttranslate(&#039;You received ${cardName}&#039;), [&lt;br /&gt;
            &amp;quot;type&amp;quot; =&amp;gt; $card[&amp;quot;type&amp;quot;],&lt;br /&gt;
            &amp;quot;cardName&amp;quot; =&amp;gt; $this-&amp;gt;getCardName($card[&amp;quot;type&amp;quot;])&lt;br /&gt;
        ]);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The problem with this approach is that the active player will receive two notifications:&lt;br /&gt;
* Player1 received a card&lt;br /&gt;
* You received Ace of Hearts&lt;br /&gt;
&lt;br /&gt;
Hence, notification ignoring.&lt;br /&gt;
&lt;br /&gt;
NOTE: You can think that it would be possible to send such notification to all players except active just by using notifyPlayer and it seems to work. The problem however is that table spectators would miss such notification and their user interface (and game log) wouldn&#039;t be updated. Since there is no way to send notification just to spectators, ignoring the notification (or &amp;quot;filtering&amp;quot;) is the only reasonable solution.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;setIgnoreNotificationCheck(notif_type: string, predicate: ((notif: Notif)=&amp;gt;boolean))&#039;&#039;&#039;&lt;br /&gt;
This method will set a check whether any of notifications of specific type should be ignored.&lt;br /&gt;
&lt;br /&gt;
The parameters are:&lt;br /&gt;
* notif_type: type of the notification &lt;br /&gt;
* predicate (notif =&amp;gt; boolean): a function that will receive notif object and will return true if this specific notification should be ignored&lt;br /&gt;
&lt;br /&gt;
Before dispatching any notification of this type, the framework will call predicate to check whether notification should be ignored, if it return true - the notification will be dispatched, i.e. logged or handled.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    this.notifqueue.setIgnoreNotificationCheck( &#039;dealCard&#039;, (notif) =&amp;gt; (notif.args.player_id == this.player_id) );&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
IMPORTANT: Remember that this notification is ignored on the client side, but was still received by the client. Therefore it shouldn&#039;t contain any private information as cheaters can get it. In other words this is not a way to hide information.&lt;br /&gt;
&lt;br /&gt;
IMPORTANT: When a game is reloaded with F5 or when opening a turn based game, old notifications are replayed as history notification. They are used just to update the game log and are stripped of all arguments except player_id, i18n and any argument present in message. If you use and other argument in your predicate you should &#039;&#039;&#039;preserve&#039;&#039;&#039; it as explained [[Main_game_logic:_yourgamename.game.php#Notify_players|here]].&lt;br /&gt;
&lt;br /&gt;
=== Synchronous notifications ===&lt;br /&gt;
&lt;br /&gt;
When several notifications are received by your game interface, these notifications are processed immediately, one after the other, in the same exact order they have been generated in your PHP game logic.&lt;br /&gt;
&lt;br /&gt;
However, sometimes, you need to give some time to the players to figure out what happened on the game before jumping to the next notification. Indeed, in many games, there are a lot of automatic actions, and the computer is going to resolve all these actions very fast if you don&#039;t tell it not to do so.&lt;br /&gt;
&lt;br /&gt;
As an example, for Reversi, when someone is playing a disc, we want to wait 500 milliseconds before doing anything else in order the opponent player can figure out what move has been played.&lt;br /&gt;
&lt;br /&gt;
Here&#039;s how we do this, right after our subscription:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    dojo.subscribe( &#039;playDisc&#039;, this, &amp;quot;notif_playDisc&amp;quot; );&lt;br /&gt;
    this.notifqueue.setSynchronous( &#039;playDisc&#039;, 500 );   // Wait 500 milliseconds after executing the playDisc handler&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
-----&lt;br /&gt;
&lt;br /&gt;
It is also possible to control the delay timing dynamically (e.g., using notification args). As an example, maybe your notification &#039;cardPlayed&#039; should pause for a different amount of time depending on the number or type of cards played.&lt;br /&gt;
&lt;br /&gt;
For this case, use &#039;&#039;&#039;setSynchronous&#039;&#039;&#039; without specifying the duration and use &#039;&#039;&#039;setSynchronousDuration&#039;&#039;&#039; within the notification callback.&lt;br /&gt;
&lt;br /&gt;
* NOTE: If you forget to invoke &#039;&#039;&#039;setSynchronousDuration&#039;&#039;&#039;, the game will remain paused forever!&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
setupNotifications: function () {&lt;br /&gt;
    dojo.subscribe( &#039;cardPlayed&#039;, this, &#039;notif_cardPlayed&#039; );&lt;br /&gt;
    this.notifqueue.setSynchronous( &#039;cardPlayed&#039; ); // wait time is dynamic&lt;br /&gt;
    ...&lt;br /&gt;
},&lt;br /&gt;
&lt;br /&gt;
notif_cardPlayed: function (notif) {&lt;br /&gt;
    // MUST call setSynchronousDuration&lt;br /&gt;
&lt;br /&gt;
    // Example 1: From notification args (PHP)&lt;br /&gt;
    this.notifqueue.setSynchronousDuration(notif.args.duration);&lt;br /&gt;
    ...&lt;br /&gt;
&lt;br /&gt;
    // Or, example 2: Match the duration to a Dojo animation&lt;br /&gt;
    var anim = dojo.fx.combine([&lt;br /&gt;
        ...&lt;br /&gt;
    ]);&lt;br /&gt;
    anim.play();&lt;br /&gt;
    this.notifqueue.setSynchronousDuration(anim.duration);&lt;br /&gt;
},&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You can also manually call this.notifqueue.setSynchronousDuration(0) once client operations are finished, but be careful that even fast replay still has a path to call it.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;WARNING: combining synchronous and ignored notifications&#039;&#039;&#039;&lt;br /&gt;
You must be careful when combining dynamic synchronous durations (as described above) with ignored notifications. If you have a conditionally ignored notification like this (see below section):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;this.notifqueue.setIgnoreNotificationCheck( &#039;myNotif&#039;, (notif) =&amp;gt; (notif.args.player_id == this.player_id) /* or any other condition */ )&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
then you CANNOT do&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;this.notifqueue.setSynchronous(&#039;myNotif&#039;);&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
as, when the ignored check passes, the notification handler, in which `this.notifqueue.setSychronousDuration` is called, is never called and so the duration is never set and interface locking results.&lt;br /&gt;
&lt;br /&gt;
The workaround is to set a &amp;quot;dummy&amp;quot; time:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;this.notifqueue.setSynchronous(&#039;myNotif&#039;, 5000);&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
whose value is irrelevant but must be large enough to cover the time before the notification handler is called. The large value never actually comes into play because the notification is either ignored, or the synchronous duration is reset to a sensible value inside the handler.&lt;br /&gt;
&lt;br /&gt;
=== Pre-defined notification types ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;tableWindow&#039;&#039;&#039; - This defines notification to display [[Game_interface_logic:_yourgamename.js#Scoring_dialogs|Scoring Dialogs]], see below.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;message&#039;&#039;&#039; - This defines notification that shows on players log and have no other effect (technically any unhandled notification will do the same but its recommended to use this keyword for consistency)&lt;br /&gt;
&lt;br /&gt;
   // You can call this on php side without doing anything on client side&lt;br /&gt;
    self::notifyAllPlayers( &#039;message&#039;, clienttranslate(&#039;hello&#039;), [] );&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;simplePause&#039;&#039;&#039; - This notification will just delay other notifications, maybe useful if you know you need some extra time for animation or something. Requires a time parameter.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    self::notifyAllPlayers( &#039;simplePause&#039;, &#039;&#039;, [ &#039;time&#039; =&amp;gt; 500] ); // time is in milliseconds&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note: the following types are RESERVED by framework, do not use:&lt;br /&gt;
&lt;br /&gt;
gameStateChange gameStateChangePrivateArg gameStateMultipleActiveUpdate newActivePlayer playerstatus yourturnack clockalert tableInfosChanged playerEliminated tableDecision  archivewaitingdelay end_archivewaitingdelay replaywaitingdelay end_replaywaitingdelay replayinitialwaitingdelay end_replayinitialwaitingdelay aiPlayerWaitingDelay replay_has_ended updateSpectatorList  wouldlikethink updateReflexionTime undoRestorePoint resetInterfaceWithAllDatas zombieModeFail zombieModeFailWarning aiError skipTurnOfPlayer zombieBack allPlayersAreZombie gameResultNeutralized playerConcedeGame showTutorial showCursor showCursorClick skipTurnOfPlayerWarning  banFromTable resultsAvailable switchToTurnbased newPrivateState infomsg&lt;br /&gt;
&lt;br /&gt;
== Tooltips ==&lt;br /&gt;
&lt;br /&gt;
=== Adding static tooltips ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.addTooltip(nodeId: string, helpStringTranslated: string, actionStringTranslated: string, delay?: number): void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Add a simple text tooltip to the DOM node.&lt;br /&gt;
&lt;br /&gt;
Specify &#039;helpStringTranslated&#039; to display some information about &amp;quot;what is this game element?&amp;quot;.&lt;br /&gt;
Specify &#039;actionStringTranslated&#039; to display some information about &amp;quot;what happens when I click on this element?&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
You must specify both of the strings. You can only use one and specify an empty string (&#039;&#039;) for the other one.&lt;br /&gt;
&lt;br /&gt;
When you pass text directly function _() must be used for the text to be marked for translation! Except for empty string.&lt;br /&gt;
&lt;br /&gt;
Parameter &amp;quot;delay&amp;quot; is optional. It is primarily used to specify a zero delay for some game element when the tooltip gives really important information for the game - but remember: no essential information must be placed in tooltips as they won&#039;t be displayed in some browsers (see [[BGA_Studio_Guidelines|Guidelines]]).&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
   this.addTooltip( &#039;cardcount&#039;, _(&#039;Number of cards in hand&#039;), &#039;&#039; );&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note: this generates static tooltip and attaches to existing dom element, if you need to generate tooltip more dynamically you have to call that method every time information about object is updated or use completely different tehnique, see dynamic tooltips below.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.addTooltipHtml(nodeId: string, html: string, delay?: number): void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Add an HTML tooltip to the DOM node (for more elaborate content such as presenting a bigger version of a card).&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.addTooltipToClass(cssClass: string, helpStringTranslated: string, actionStringTranslated: string, delay?: number ): void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Add a simple text tooltip to all the DOM nodes set with this cssClass. See more details above for this.addTooltip.&lt;br /&gt;
     this.addTooltipToClass( &#039;meeple&#039;, _(&#039;This is A Meeple&#039;), _(&#039;Click to tickle&#039;) );&lt;br /&gt;
&lt;br /&gt;
IMPORTANT: all concerned nodes must exist and have IDs to get tooltips.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.addTooltipHtmlToClass(cssClass: string, html: string, delay?: number): void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Add an HTML tooltip to to all the DOM nodes set with this cssClass (for more elaborate content such as presenting a bigger version of a card).&lt;br /&gt;
&lt;br /&gt;
IMPORTANT: all concerned nodes must exist and have IDs to get tooltips.&lt;br /&gt;
&lt;br /&gt;
=== Removing static tooltips ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.removeTooltip(nodeId: string): void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Remove a tooltip from the DOM node with given id.&lt;br /&gt;
&lt;br /&gt;
=== Advanced tooltips ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;force tooltip to open&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
If you want to force tooltip to open in reaction to some other action, i.e. click you can do this&lt;br /&gt;
&lt;br /&gt;
   this.tooltips[id].open(id)&lt;br /&gt;
&lt;br /&gt;
where id is the id of the tooltip node where tooltip was installed.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;dynamic tooltips&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
See [[BGA_Studio_Cookbook#Dynamic_tooltips]]&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;tooltips on mobile&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Tooltips is very unreliable on mobile, it is recommended to implement some other method to obtaining same information,&lt;br /&gt;
such as simple click handler in dedicated &amp;quot;Help&amp;quot; mode or provide dedicated clickable areas such as corner of card.&lt;br /&gt;
&lt;br /&gt;
== Warning messages ==&lt;br /&gt;
&lt;br /&gt;
Sometimes, there is something important that is happening in the game and you have to make sure all players get the message. Most of the time, the evolution of the game situation or the game log is enough, but sometimes you need something more visible.&lt;br /&gt;
&lt;br /&gt;
Ex: someone fulfills one of the end of the game conditions, so this is the last turn.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.showMessage(msg: string, type: string): void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
showMessage shows a message in a big rectangular area on the top of the screen of the current player, and it dissapears after few seconds (also it will be in the log in some cases).&lt;br /&gt;
&lt;br /&gt;
* &amp;quot;msg&amp;quot; is the string to display. It should be translated.&lt;br /&gt;
* &amp;quot;type&amp;quot; can be set to &amp;quot;info&amp;quot;, &amp;quot;error&amp;quot;, &amp;quot;only_to_log&amp;quot; or custom string. If set to &amp;quot;info&amp;quot;, the message will be an informative message on a white background. If set to &amp;quot;error&amp;quot;, the message will be an error message on a red background and it will be added to log. If set to &amp;quot;only_to_log&amp;quot;, the message will be added to the game log but will not popup at the top of the screen.&lt;br /&gt;
If set to custom string, it will be transparent, to use custom type define &amp;quot;head_xxx&amp;quot; in css, where xxx is the type. For example if you want yellow warning, use &amp;quot;warning&amp;quot; as type and add this to css:&lt;br /&gt;
 .head_warning {&lt;br /&gt;
    background-color: #e6c66e;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
Important: the normal way to inform players about the progression of the game is the game log. The &amp;quot;showMessage&amp;quot; is intrusive and should not be used often.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    notif_messageinfo: function(notif) {&lt;br /&gt;
	if (!g_archive_mode) {&lt;br /&gt;
        	var message = this.format_string_recursive(notif.log, notif.args);&lt;br /&gt;
		this.showMessage(_(&#039;Announcement:&#039;) + &amp;quot; &amp;quot; + message, &#039;info&#039;);		&lt;br /&gt;
         }&lt;br /&gt;
    },&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Show message could be used on the client side to prevent user wrong moves before it is send to server.&lt;br /&gt;
Example from &#039;battleship&#039;:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
onGrid: function(event) {&lt;br /&gt;
     if (checkIfPlayerTriesToFireOnThemselves(event)) {&lt;br /&gt;
        this.showMessage(_(&#039;This is your own board silly!&#039;), &#039;error&#039;);&lt;br /&gt;
        return;&lt;br /&gt;
     }&lt;br /&gt;
     ...&lt;br /&gt;
},&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.showMoveUnauthorized(): void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Shows predefined user error that move is unauthorized now&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
onPet: function(event) {&lt;br /&gt;
     if (checkPet(event)==false) {&lt;br /&gt;
        this.showMoveUnauthorized();&lt;br /&gt;
        return;&lt;br /&gt;
     }&lt;br /&gt;
     ...&lt;br /&gt;
},&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Dialogs ==&lt;br /&gt;
&lt;br /&gt;
=== Confirmation dialog ===&lt;br /&gt;
&lt;br /&gt;
When an important action with a lot of consequences is triggered by the player, you may want to propose a confirmation dialog.&lt;br /&gt;
&lt;br /&gt;
CAREFUL: the general guideline of BGA is to AVOID the use of confirmation dialogs. Confirmation dialogs slow down the game and bother players. The players know that they have to pay attention to each move when they are playing online.&lt;br /&gt;
&lt;br /&gt;
The situations where you should use a confirmation dialog are the following:&lt;br /&gt;
* It must not happen very often during a game.&lt;br /&gt;
* It must be linked to an action that can really &amp;quot;kill a game&amp;quot; if the player does not pay attention.&lt;br /&gt;
* It must be something that can be done by mistake (ex: a link on the action status bar).&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.confirmationDialog(message: string, yesHandler: (param: any) =&amp;gt; void, noHandler?: (param: any) =&amp;gt; void, param?: any): void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
* message - message will be shown to user, use _() to translate&lt;br /&gt;
* yesHandler - non-optional handler to be called on yes&lt;br /&gt;
* noHandler - optional handler to called on no&lt;br /&gt;
* param - if specified, it will be passed to both handlers&lt;br /&gt;
NOTE: this is async function, it does not return anything and you should not do anything after, you must do everything in handlers&lt;br /&gt;
&lt;br /&gt;
How to display a confirmation dialog:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    this.confirmationDialog(_(&amp;quot;Are you sure you want to bake a pie?&amp;quot;), () =&amp;gt; {&lt;br /&gt;
      this.bakeThePie();&lt;br /&gt;
    });&lt;br /&gt;
    return; // nothing should be called or done after calling this, all action must be done in the handler&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
With param and both handlers&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    this.confirmationDialog(_(&amp;quot;Are you sure you want to bake a pie?&amp;quot;), &lt;br /&gt;
           (ingredient) =&amp;gt; this.bakeThePie(ingredient), &lt;br /&gt;
           (ingredient) =&amp;gt; console.log(`cancelled baking of ${ingredient}`), &lt;br /&gt;
           &#039;apple&#039;);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Multiple choice dialog ===&lt;br /&gt;
&lt;br /&gt;
You can use this dialog to give user a choice with small amount of options&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.multipleChoiceDialog(message: string, choices: string[], callback: (choice: number) =&amp;gt; void): void&#039;&#039;&#039;&lt;br /&gt;
* message - message will be shown to user, use _() to translate&lt;br /&gt;
* choices - array of choices&lt;br /&gt;
* callback - non-optional handler to be called on choice made, the choice parameter is the INDEX of the choice from the array of choices&lt;br /&gt;
&lt;br /&gt;
NOTE: this is async function, it does not return anything and you should not do anything after, you must do everything in handlers&lt;br /&gt;
NOTE: there is no cancel handler, so make sure you gave user a choice to get out of it&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    const keys = [&amp;quot;0&amp;quot;, &amp;quot;1&amp;quot;, &amp;quot;5&amp;quot;, &amp;quot;10&amp;quot;];&lt;br /&gt;
    this.multipleChoiceDialog(_(&amp;quot;How many bugs to fix?&amp;quot;), keys, (choice) =&amp;gt; {&lt;br /&gt;
      if (choice==0) return; // cancel operation, do not call server action&lt;br /&gt;
      var bugchoice = keys[choice]; // choice will be 0,1,2,3 here&lt;br /&gt;
      this.bgaPerformAction(&amp;quot;fixBugs&amp;quot;, { number: bugchoice });&lt;br /&gt;
    });&lt;br /&gt;
    return; // must return here&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Generic Dialogs ===&lt;br /&gt;
&lt;br /&gt;
As a general rule, you shouldn&#039;t use dialogs windows.&lt;br /&gt;
&lt;br /&gt;
BGA guidelines specify that all game elements should be displayed on the main screen. Players can eventually scroll down to see game elements they don&#039;t need to see anytime, and you may eventually create anchors to move between game area section. Of course dialogs windows are very practical, but the thing is: all players know how to scroll down, and not all players know how to show up your dialog window. In addition, when the dialog shows up, players can&#039;t access the other game components.&lt;br /&gt;
&lt;br /&gt;
Sometimes although, you need to display a dialog window. Here is how you do this:&lt;br /&gt;
&lt;br /&gt;
  // Create the new dialog over the play zone. You should store the handler in a member variable to access it later&lt;br /&gt;
  this.myDlg = new ebg.popindialog();&lt;br /&gt;
  this.myDlg.create( &#039;myDialogUniqueId&#039; );&lt;br /&gt;
  this.myDlg.setTitle( _(&amp;quot;my dialog title to translate&amp;quot;) );&lt;br /&gt;
  this.myDlg.setMaxWidth( 500 ); // Optional&lt;br /&gt;
  &lt;br /&gt;
  // Create the HTML of my dialog. &lt;br /&gt;
  // The best practice here is to use [[Game_layout:_view_and_template:_yourgamename.view.php_and_yourgamename_yourgamename.tpl#Javascript_templates|Javascript templates]]&lt;br /&gt;
  var html = this.format_block( &#039;jstpl_myDialogTemplate&#039;, { &lt;br /&gt;
                arg1: myArg1,&lt;br /&gt;
                arg2: myArg2,&lt;br /&gt;
                ...&lt;br /&gt;
            } );  &lt;br /&gt;
  &lt;br /&gt;
  // Show the dialog&lt;br /&gt;
  this.myDlg.setContent( html ); // Must be set before calling show() so that the size of the content is defined before positioning the dialog&lt;br /&gt;
  this.myDlg.show();&lt;br /&gt;
  &lt;br /&gt;
  // Now that the dialog has been displayed, you can connect your method to some dialog elements&lt;br /&gt;
  // Example, if you have an &amp;quot;OK&amp;quot; button in the HTML of your dialog:&lt;br /&gt;
  dojo.connect($(&#039;my_ok_button&#039;), &#039;onclick&#039;, this, (event) =&amp;gt; {&lt;br /&gt;
                event.preventDefault();&lt;br /&gt;
                this.myDlg.destroy();&lt;br /&gt;
            });&lt;br /&gt;
&lt;br /&gt;
If necessary, you can remove the default top right corner &#039;close&#039; icon, or replace the function called when it is clicked:&lt;br /&gt;
  // Removes the default close icon&lt;br /&gt;
  this.myDlg.hideCloseIcon();&lt;br /&gt;
&lt;br /&gt;
  // Replace the function call when it&#039;s clicked&lt;br /&gt;
  this.myDlg.replaceCloseCallback((event) =&amp;gt; { ... });&lt;br /&gt;
&lt;br /&gt;
=== Scoring dialogs ===&lt;br /&gt;
&lt;br /&gt;
Sometimes at the end of a round you want to display a big table that details the points wins in each section of the game.&lt;br /&gt;
&lt;br /&gt;
Example: in Hearts game, we display at the end of each round the number of &amp;quot;heart&amp;quot; cards collected by each player, the player who collected the Queen of Spades, and the total number of points loose by each player.&lt;br /&gt;
&lt;br /&gt;
Scoring dialogs are managed entirely on &#039;&#039;&#039;PHP side&#039;&#039;&#039;, but they are described here as their effects are visible only on client side.&lt;br /&gt;
&lt;br /&gt;
Displaying a scoring dialog is quite simple and is using a special notification type: &amp;quot;tableWindow&amp;quot;:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  // on PHP side:&lt;br /&gt;
  $this-&amp;gt;notifyAllPlayers( &amp;quot;tableWindow&amp;quot;, &#039;&#039;, array(&lt;br /&gt;
            &amp;quot;id&amp;quot; =&amp;gt; &#039;finalScoring&#039;,&lt;br /&gt;
            &amp;quot;title&amp;quot; =&amp;gt; clienttranslate(&amp;quot;Title of the scoring dialog&amp;quot;),&lt;br /&gt;
            &amp;quot;table&amp;quot; =&amp;gt; $table&lt;br /&gt;
        )); &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The &amp;quot;table&amp;quot; argument is a 2 dimensional PHP array that describes the table you want to display, line by line and column by column.&lt;br /&gt;
&lt;br /&gt;
Example: display an 3x3 array of strings&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
   $table = [&lt;br /&gt;
      [ &amp;quot;one&amp;quot;, &amp;quot;two&amp;quot;, &amp;quot;three&amp;quot; ],    // This is my first line&lt;br /&gt;
      [ &amp;quot;four&amp;quot;, &amp;quot;five&amp;quot;, &amp;quot;six&amp;quot; ],    // This is my second line&lt;br /&gt;
      [ &amp;quot;seven&amp;quot;, &amp;quot;height&amp;quot;, &amp;quot;nine&amp;quot; ]    // This is my third line&lt;br /&gt;
   ];&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
As you can see above, in each &amp;quot;cell&amp;quot; of your array you can display a simple string value. But you can also display a complex value with a template and associated arguments like this:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
   $table = [&lt;br /&gt;
      [ &amp;quot;one&amp;quot;, &amp;quot;two&amp;quot;, [ &amp;quot;str&amp;quot; =&amp;gt; clienttranslate(&amp;quot;a string with an ${argument}&amp;quot;), &amp;quot;args&amp;quot; =&amp;gt; [ &#039;argument&#039; =&amp;gt; &#039;argument_value&#039; ] ] ],&lt;br /&gt;
      [ &amp;quot;four&amp;quot;, &amp;quot;five&amp;quot;, &amp;quot;six&amp;quot; ], &lt;br /&gt;
      [ &amp;quot;seven&amp;quot;, &amp;quot;height&amp;quot;, &amp;quot;nine&amp;quot; ]&lt;br /&gt;
   ];&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This is especially useful when you want to display player names with colors. Example from &amp;quot;Hearts&amp;quot;:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        $firstRow = [ &#039;&#039; ];&lt;br /&gt;
        foreach( $players as $player_id =&amp;gt; $player )    {&lt;br /&gt;
            $cell = [ &#039;str&#039; =&amp;gt; &#039;${player_name}&#039;,&lt;br /&gt;
                      &#039;args&#039; =&amp;gt; [ &#039;player_name&#039; =&amp;gt; $player[&#039;player_name&#039;] ],&lt;br /&gt;
                      &#039;type&#039; =&amp;gt; &#039;header&#039;&lt;br /&gt;
                    ];&lt;br /&gt;
            $firstRow[] = $cell;&lt;br /&gt;
        }&lt;br /&gt;
        $table[] = $firstRow;&lt;br /&gt;
        ...&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You can also use three extra attributes in the parameter array for the notification:&lt;br /&gt;
* &#039;&#039;&#039;header&#039;&#039;&#039;: the content for this parameter displays before the table (also, the html will be parsed and player names will be colored according to the current game colors). &lt;br /&gt;
* &#039;&#039;&#039;footer&#039;&#039;&#039;: the content for this parameter displays after the table (no parsing for coloring the player names)&lt;br /&gt;
* &#039;&#039;&#039;closing&#039;&#039;&#039;: if this parameter is used, a button will be displayed with this label at the bottom of the popup and will allow players to close it (more easily than by clicking the top right &#039;cross&#039; icon).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
   $this-&amp;gt;notifyAllPlayers( &amp;quot;tableWindow&amp;quot;, &#039;&#039;, [&lt;br /&gt;
            &amp;quot;id&amp;quot; =&amp;gt; &#039;finalScoring&#039;,&lt;br /&gt;
            &amp;quot;title&amp;quot; =&amp;gt; clienttranslate(&amp;quot;Title of the scoring dialog&amp;quot;),&lt;br /&gt;
            &amp;quot;table&amp;quot; =&amp;gt; $table,&lt;br /&gt;
            &amp;quot;header&amp;quot; =&amp;gt; [&#039;str&#039; =&amp;gt; clienttranslate(&#039;Table header with parameter ${number}&#039;),&lt;br /&gt;
                                 &#039;args&#039; =&amp;gt; [ &#039;number&#039; =&amp;gt; 3 ],&lt;br /&gt;
                               ],&lt;br /&gt;
            &amp;quot;footer&amp;quot; =&amp;gt; &#039;&amp;lt;div class=&amp;quot;myfoot&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&#039;,&lt;br /&gt;
            &amp;quot;closing&amp;quot; =&amp;gt; clienttranslate( &amp;quot;Closing button label&amp;quot; )&lt;br /&gt;
        ] ); &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note: currently id is not used - so you cannot access resulting div by id on js side&lt;br /&gt;
Note: any traslatable stirng have to be wrapped by clienttranslate() on top level OR it has to be recursive template. &lt;br /&gt;
&lt;br /&gt;
DO NOT DO THIS: &lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
   &amp;quot;footer&amp;quot; =&amp;gt; &#039;&amp;lt;div&amp;gt;&#039;.clienttranslate( &amp;quot;The end&amp;quot; ).&#039;&amp;lt;/div&amp;gt;&#039;, // this will not work for translations!!!&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Scoring animated display ===&lt;br /&gt;
&lt;br /&gt;
Sometimes, you may want to display a score value over an element to make the scoring easier to follow for the players (Terra Mystica final scoring for example).&lt;br /&gt;
You can do it with:&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.displayScoring(anchor_id: string, color: string, score: number | string, duration?: number, offset_x?: number, offset_y?: number): void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;anchor_id&#039;&#039;&#039;: ID of the html element to place the animated score onto (without the &#039;#&#039;) &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;color&#039;&#039;&#039;: hexadecimal RGB representation of the color (should be the color of the scoring player), but without a leading &#039;#&#039;.  For instance, &#039;ff0000&#039; for red.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;score&#039;&#039;&#039;: numeric score to display, prefixed by a &#039;+&#039; or &#039;-&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;duration&#039;&#039;&#039;: animation duration in milliseconds (optional, default is 1000)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;offset_x&#039;&#039;&#039; and &#039;&#039;&#039;offset_y&#039;&#039;&#039;: if both offset_x and offset_y are defined and not null, apply the following offset (in pixels) to the scoring animation. &lt;br /&gt;
Note that the score is centered in the anchor, so the offsets might have to be negative if you calculate the position.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Note: if you want to display successively each score, you can use &#039;&#039;this.notifqueue.setSynchronous()&#039;&#039; function.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    setupNotifications: function()   {&lt;br /&gt;
           dojo.subscribe( &#039;displayScoring&#039;, this, &amp;quot;notif_displayScoring&amp;quot; );&lt;br /&gt;
           ...&lt;br /&gt;
    }&lt;br /&gt;
...&lt;br /&gt;
&lt;br /&gt;
    notif_displayScoring: function(notif) {&lt;br /&gt;
            const duration = notif.args.duration?notif.args.duration:1000;&lt;br /&gt;
            this.notifqueue.setSynchronous(&#039;displayScoring&#039;, duration );&lt;br /&gt;
	    this.displayScoring( notif.args.target, notif.args.color, notif.args.score, duration);&lt;br /&gt;
    },&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Speech bubble ===&lt;br /&gt;
&lt;br /&gt;
For better interactivity in some games (Love Letter for example), you may use comic book style speech bubbles to express the players voices.&lt;br /&gt;
This is done with showBubble:&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.showBubble(anchor_id: string, text: string, delay?: number, duration?: number, custom_class?: string): void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
* anchor_id - where to attach the bubble&lt;br /&gt;
* text - what to put in bubble, can be html&lt;br /&gt;
* delay - delay in milliseconds (optional, default 0)&lt;br /&gt;
* duration -  duration of animation in milliseconds (optional, default 3000)&lt;br /&gt;
* custom_class - extra class to add to bubble (optional), if you need to override the default bubble style&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
   this.showBubble(&#039;meeple_2&#039;, _(&#039;Hello&#039;), 0, 1000, &#039;pink_bubble&#039;);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  notif_speechBubble(notif) {&lt;br /&gt;
    var html = this.format_string_recursive(notif.args.text, notif.args.args);&lt;br /&gt;
    this.showBubble(notif.args.target, html, notif.args.delay ?? 0, notif.args.duration ?? 1000);&lt;br /&gt;
  },&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Warning&#039;&#039;&#039;: if your bubble could overlap other active elements of the interface (buttons in particular), as it stays in place even after disappearing, you should use a custom class to give it the style &amp;quot;pointer-events: none;&amp;quot; in order to intercept click events.&lt;br /&gt;
&lt;br /&gt;
Note: If you want this visually, but want to take complete control over this bubble and its animation (for example to make it permanent) you can just use div with &#039;discussion_bubble&#039; class on it, and content of div is what will be shown.&lt;br /&gt;
&lt;br /&gt;
== Translations ==&lt;br /&gt;
&lt;br /&gt;
See [[Translations]]&lt;br /&gt;
&lt;br /&gt;
== Players panels ==&lt;br /&gt;
&lt;br /&gt;
=== Update players score ===&lt;br /&gt;
&lt;br /&gt;
The column player_score from the player table is automatically loaded into this.scoreCtrl and therefore into the stars location on the player board. This occurs sometime after the game setup() function. However this score must be updated as the game progresses using notifications.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Note: this.scoreCtrl[player_id] is object of class [[Counter]], you can use other counter API.&lt;br /&gt;
&lt;br /&gt;
Increase a player score (with a positive or negative number):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  this.scoreCtrl[ player_id ].incValue( score_delta );&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Set a player score to a specific value:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  this.scoreCtrl[ player_id ].setValue( new_score );&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Set a player score to a specific value with animation:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  this.scoreCtrl[ player_id ].toValue( new_score );&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Typical usage would be (that will process &#039;score&#039; notification):&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        setupNotifications : function() {&lt;br /&gt;
              ...&lt;br /&gt;
             dojo.subscribe(&#039;score&#039;, this, &amp;quot;notif_score&amp;quot;);&lt;br /&gt;
        },&lt;br /&gt;
        notif_score: function(notif) {&lt;br /&gt;
            this.scoreCtrl[notif.args.player_id].setValue(notif.args.player_score);&lt;br /&gt;
        },&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Adding stuff to player&#039;s panel ===&lt;br /&gt;
&lt;br /&gt;
At first, create a new &amp;quot;JS template&amp;quot; string in your template (tpl) file:&lt;br /&gt;
&lt;br /&gt;
(from Gomoku example)&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
var jstpl_player_board = &#039;\&amp;lt;div class=&amp;quot;cp_board&amp;quot;&amp;gt;\&lt;br /&gt;
    &amp;lt;div id=&amp;quot;stoneicon_p${id}&amp;quot; class=&amp;quot;gmk_stoneicon gmk_stoneicon_${color}&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&amp;lt;span id=&amp;quot;stonecount_p${id}&amp;quot;&amp;gt;0&amp;lt;/span&amp;gt;\&lt;br /&gt;
&amp;lt;/div&amp;gt;&#039;;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Then, you add this piece of code in your JS file to add this template to each player panel:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
            // Setting up player boards&lt;br /&gt;
            for( var player_id in gamedatas.players )&lt;br /&gt;
            {&lt;br /&gt;
                var player = gamedatas.players[player_id];&lt;br /&gt;
                         &lt;br /&gt;
                // Setting up players boards if needed&lt;br /&gt;
                var player_board_div = $(&#039;player_board_&#039;+player_id);&lt;br /&gt;
                dojo.place( this.format_block(&#039;jstpl_player_board&#039;, player ), player_board_div );&lt;br /&gt;
            }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
(Note: the code above is of course from your &amp;quot;setup&amp;quot; function in your Javascript).&lt;br /&gt;
&lt;br /&gt;
Very often, you have to distinguish current player and others players. In this case, you just have to create another JS template (ex: jstpl_otherplayer_board) and use it when &amp;quot;player_id&amp;quot; is different than &amp;quot;this.player_id&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Fixing Player Panel heights ===&lt;br /&gt;
&lt;br /&gt;
You may find that the player panels don&#039;t automatically resize when adding something to (or removing something from) a player panel while the display is in portrait mode (i.e. the player summary panels are at the top of the screen rather than down the right side).&lt;br /&gt;
&lt;br /&gt;
When this happens, call &amp;lt;pre&amp;gt;this.adaptPlayersPanels();&amp;lt;/pre&amp;gt; This recalculates the layout and also adjusts the position of the actionbar for you.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Player&#039;s panel disabling/enabling ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.disablePlayerPanel(player_id: number): void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Disable given player panel (the panel background become gray).&lt;br /&gt;
&lt;br /&gt;
Usually, this is used to signal that this played passes, or will be inactive during a while.&lt;br /&gt;
&lt;br /&gt;
Note that the only effect of this is visual. There are no consequences on the behaviour of the panel itself.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.enablePlayerPanel(player_id:number): void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Enable a player panel that has been disabled before.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.enableAllPlayerPanels(): void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Enable all player panels that has been disabled before.&lt;br /&gt;
&lt;br /&gt;
=== Player order ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.updatePlayerOrdering(): void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
This function makes sure that player order in player&#039;s panel matches this.gamedatas.playerorder and its normally called by framework.&lt;br /&gt;
You can call it yoursel if you change this.gamedatas.playerorder from notification.&lt;br /&gt;
Also you can override this function to change defaults  OR insert a non-player panel [[BGA_Studio_Cookbook#Inserting_non-player_panel]].&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Counters ===&lt;br /&gt;
Note: there is bga component called  &amp;quot;ebg/counter&amp;quot; this API is not using it, these methods&lt;br /&gt;
below declared right in core game. If you need animation for counters use ebg/counter&lt;br /&gt;
&lt;br /&gt;
To use this API just create a counter dom element like this (class does not really matter)&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 &amp;lt;div class=&amp;quot;counter&amp;quot; id=&amp;quot;bread&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
 &amp;lt;div class=&amp;quot;counter&amp;quot; id=&amp;quot;coin&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
The &amp;quot;bread&amp;quot; will the counter name.&lt;br /&gt;
&lt;br /&gt;
The php code should send all &amp;quot;counters&amp;quot; data from getAllDatas() method like this&lt;br /&gt;
&lt;br /&gt;
game.php&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  protected function getAllDatas() {&lt;br /&gt;
    // (the key must match counter_name)&lt;br /&gt;
    $result[&#039;counters&#039;]=[&lt;br /&gt;
        &#039;bread&#039; =&amp;gt; [ &lt;br /&gt;
         &#039;counter_name&#039; =&amp;gt; &#039;bread&#039;, &lt;br /&gt;
         &#039;counter_value&#039; =&amp;gt; 3&lt;br /&gt;
         ], &lt;br /&gt;
        &#039;coin&#039; =&amp;gt; [&lt;br /&gt;
          &#039;counter_name&#039; =&amp;gt; &#039;coin&#039;, &lt;br /&gt;
          &#039;counter_value&#039; =&amp;gt; 5&lt;br /&gt;
        ]&lt;br /&gt;
   ];&lt;br /&gt;
   return $result;&lt;br /&gt;
  }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;setCounter(counter_name: stirng, new_value: string | number): void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
updates the global this.gamedatas.counters and value of node $(counter_name)&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  notif_counter: function(notif) { &lt;br /&gt;
    this.setCounter(notif.args.counter_name, notif.args.counter_value);&lt;br /&gt;
  },&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;incCounter(counter_name: string, delta: number): void&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  notif_counter : function(notif) {&lt;br /&gt;
    this.incCounter(notif.args.counter_name, notif.args.inc);&lt;br /&gt;
  },&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;updateCounters(counters: object): void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Useful for updating game counters in the player panel (such as resources). &lt;br /&gt;
&#039;counters&#039; arg is map of counters (the key must match counter_name)&lt;br /&gt;
  {&lt;br /&gt;
    &#039;bread&#039;: { &lt;br /&gt;
         &#039;counter_name&#039; : &#039;bread&#039;, &lt;br /&gt;
         &#039;counter_value&#039; =&amp;gt; 3&lt;br /&gt;
    }, &lt;br /&gt;
    &#039;coin&#039;: { &lt;br /&gt;
         &#039;counter_name&#039; : &#039;coin&#039;, &lt;br /&gt;
         &#039;counter_value&#039; =&amp;gt; 5&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
All counters MUST be referenced in this.gamedatas.counters (means they should be send from php) and will be updated.&lt;br /&gt;
DOM objects referenced by &#039;counter_name&#039; will have their innerHTML updated with &#039;counter_value&#039;.&lt;br /&gt;
&lt;br /&gt;
Usually you call this from notification&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
                        notif_counter : function(notif) {&lt;br /&gt;
                            this.updateCounters(notif.args.counters);&lt;br /&gt;
                        },&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== BGA GUI components ==&lt;br /&gt;
&lt;br /&gt;
BGA framework provides some useful ready-to-use components for the game interface:&lt;br /&gt;
&lt;br /&gt;
[[Studio#BGA_Studio_game_components_reference]]&lt;br /&gt;
&lt;br /&gt;
Note that each time you are using an additional component, you must declare it at the top of your Javascript file in the list of modules used.&lt;br /&gt;
&lt;br /&gt;
Example if you are using &amp;quot;ebg.stock&amp;quot;:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
define([&lt;br /&gt;
    &amp;quot;dojo&amp;quot;,&amp;quot;dojo/_base/declare&amp;quot;,&lt;br /&gt;
    &amp;quot;ebg/core/gamegui&amp;quot;,&lt;br /&gt;
    &amp;quot;ebg/counter&amp;quot;,&lt;br /&gt;
    &amp;quot;ebg/stock&amp;quot;  /// &amp;lt;=== we are using ebg.stock module&lt;br /&gt;
],&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== BGA Buttons ==&lt;br /&gt;
&lt;br /&gt;
=== Basic Button ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.addActionButton(id: string, label: string, method: string | eventhandler, destination?: string, blinking?: boolean, color?: string): void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
You can use this method to add an action button in the main action status bar (or other places).&lt;br /&gt;
&lt;br /&gt;
Arguments:&lt;br /&gt;
* id: an element ID that should be unique in your HTML DOM document.&lt;br /&gt;
* label: the text of the button. Should be translatable (use _() function). Note: this can also be any html, such as &amp;quot;&amp;lt;div class=&#039;brick&#039;&amp;gt;&amp;lt;/div&amp;gt;&amp;quot;, see example below on how to make image action buttons.&lt;br /&gt;
* method: the name of your method that must be triggered when the player clicks on this button (can be name of the method on game class or handler).&lt;br /&gt;
* destination (optional): id of parent on where to add button, ONLY use in rare cases if location is not action bar. Use &#039;&#039;&#039;null&#039;&#039;&#039; as value if you need to specify other arguments.&lt;br /&gt;
* blinking (optional): if set to &#039;&#039;&#039;true&#039;&#039;&#039;, the button is going blink to catch player&#039;s attention. Please DO NOT abuse blinking button. If you need button to blink after some time passed add class &#039;blinking&#039; to the button later.&lt;br /&gt;
* color: could be &#039;&#039;&#039;blue&#039;&#039;&#039; (default), &#039;&#039;&#039;red&#039;&#039;&#039;,&#039;&#039;&#039;gray&#039;&#039;&#039; or &#039;&#039;&#039;none&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
You should only use this method in your &amp;quot;onUpdateActionButtons&amp;quot; method. Usually, you use it like this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        onUpdateActionButtons: function( stateName, args ) {                      &lt;br /&gt;
            if (this.isCurrentPlayerActive()) {            &lt;br /&gt;
                switch( stateName ) {&lt;br /&gt;
                case &#039;giveCards&#039;:&lt;br /&gt;
                    this.addActionButton( &#039;giveCards_button&#039;, _(&#039;Give selected cards&#039;), &#039;onGiveCards&#039; ); &lt;br /&gt;
                    this.addActionButton( &#039;pass_button&#039;, _(&#039;Pass&#039;), () =&amp;gt; this.bgaPerformAction(&#039;actPass&#039;) ); &lt;br /&gt;
                    break;&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        },   &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In the example above, we are adding a &amp;quot;Give selected cards&amp;quot; button in the case we are on game state &amp;quot;giveCards&amp;quot;. When player clicks on this button, it triggers our &amp;quot;onGiveCards&amp;quot; method.&lt;br /&gt;
&lt;br /&gt;
Example using blinking red button:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    this.addActionButton( &#039;button_confirm&#039;, _(&#039;Confirm?&#039;), &#039;onConfirm&#039;, null, true, &#039;red&#039;); &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If you want to call the handler with arguments, you can use arrow functions, like this:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
     this.addActionButton( &#039;commit_button&#039;, _(&#039;Confirm&#039;), () =&amp;gt; this.onConfirm(this.selectedCardId), null, false, &#039;red&#039;); &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Image Button ===&lt;br /&gt;
&lt;br /&gt;
You can use the same method, but add extra class to a button to disable the padding and style it, i.e.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
this.addActionButton( &#039;button_brick&#039;, &#039;&amp;lt;div class=&amp;quot;brick&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&#039;, ()=&amp;gt;{... on brick ...}, null, null, &#039;gray&#039;); &lt;br /&gt;
dojo.addClass(&#039;button_brick&#039;,&#039;bgaimagebutton&#039;);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
where&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
.bgaimagebutton {&lt;br /&gt;
  padding: 0px 12px;&lt;br /&gt;
  min-height: 28px;&lt;br /&gt;
  border: none;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If you use this a lot, you can define a helper function, i.e.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
 * This method can be used instead of addActionButton, to add a button which is an image (i.e. resource). Can be useful when player&lt;br /&gt;
 * need to make a choice of resources or tokens.&lt;br /&gt;
 */&lt;br /&gt;
addImageActionButton: function(id, div, handler, bcolor, tooltip) {&lt;br /&gt;
	if (typeof bcolor == &amp;quot;undefined&amp;quot;) {&lt;br /&gt;
		bcolor = &amp;quot;gray&amp;quot;;&lt;br /&gt;
	}&lt;br /&gt;
	// this will actually make a transparent button id color = gray&lt;br /&gt;
	this.addActionButton(id, div, handler, null, false, bcolor);&lt;br /&gt;
	// remove border, for images it better without&lt;br /&gt;
	dojo.style(id, &amp;quot;border&amp;quot;, &amp;quot;none&amp;quot;);&lt;br /&gt;
	// but add shadow style (box-shadow, see css)&lt;br /&gt;
	dojo.addClass(id, &amp;quot;shadow bgaimagebutton&amp;quot;);&lt;br /&gt;
	// you can also add additional styles, such as background&lt;br /&gt;
	if (tooltip) {&lt;br /&gt;
		dojo.attr(id, &amp;quot;title&amp;quot;, tooltip);&lt;br /&gt;
	}&lt;br /&gt;
	return $(id);&lt;br /&gt;
},&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Disabling Button ===&lt;br /&gt;
&lt;br /&gt;
You can disable the &#039;&#039;&#039;bgabutton&#039;&#039;&#039; by adding the css class &#039;&#039;&#039;disabled&#039;&#039;&#039; in you js. The disabled button is still visible but is grey and not clickable.&lt;br /&gt;
For example in the &#039;&#039;&#039;onUpdateActionButtons&#039;&#039;&#039; : &lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
this.addActionButton(&#039;play_button_id&#039;, _(&#039;Play 1 to 3 cards&#039;), &#039;playFunctionButton&#039;); &lt;br /&gt;
if (condition) {&lt;br /&gt;
  dojo.addClass(&#039;play_button_id&#039;, &#039;disabled&#039;);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Custom Buttons ===&lt;br /&gt;
&lt;br /&gt;
You can create a custom button, but the BGA framework provides a standard button that requires only .css classes: &#039;&#039;&#039;bgabutton&#039;&#039;&#039; and &#039;&#039;&#039;bgabutton_${color}&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Examples:&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;a href=&amp;quot;#&amp;quot; id=&amp;quot;my_button_id&amp;quot; class=&amp;quot;bgabutton bgabutton_blue&amp;quot;&amp;gt;&amp;lt;span&amp;gt;My blue button&amp;lt;/span&amp;gt;&amp;lt;/a&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;a href=&amp;quot;#&amp;quot; id=&amp;quot;my_button_id&amp;quot; class=&amp;quot;bgabutton bgabutton_red bgabutton_big&amp;quot;&amp;gt;&amp;lt;span&amp;gt;My big red button&amp;lt;/span&amp;gt;&amp;lt;/a&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note&#039;&#039;&#039;: To see it in action, check out &#039;&#039;Coloretto&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
=== Button outside of action bar ===&lt;br /&gt;
&lt;br /&gt;
Use addActionButton() method with destination argument set&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
this.addActionButton( &#039;commit_button&#039;, _(&#039;Confirm&#039;), &#039;onConfirm&#039;, &#039;player_board&#039;, true, &#039;red&#039;); &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
in example above the button will be place on object with id &#039;player_board&#039;&lt;br /&gt;
&lt;br /&gt;
== Image loading ==&lt;br /&gt;
&lt;br /&gt;
See also [[Game_art:_img_directory]].&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Be careful&#039;&#039;&#039;: by default, ALL images of your img directory are loaded on a player&#039;s browser when he loads the game. For this reason, don&#039;t let in your img directory images that are not useful, otherwise it&#039;s going to slowdown the game load.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.dontPreloadImage(image_file_name: string)&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Using dontPreloadImage, you tell the interface to not preload a specific image in your img directory.&lt;br /&gt;
&lt;br /&gt;
Example of use:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
this.dontPreloadImage( &#039;cards.png&#039; );&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This is particularly useful if for example you have 2 different themes for a game. To accelerate the loading of the game, you can specify to not preload images corresponding to the other theme.&lt;br /&gt;
&lt;br /&gt;
Another example of use: in &amp;quot;Gosu&amp;quot; game with Kamakor extension, you play with 5 sets of cards among 10 available. Cards images are organized by sets, and we only preload the images corresponding to the 5 current sets with &#039;&#039;&#039;ensureSpecificGameImageLoading( image_file_names_array )&#039;&#039;&#039;.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
// By default, do not preload anything&lt;br /&gt;
this.dontPreloadImage( &#039;cards.png&#039; );&lt;br /&gt;
this.dontPreloadImage( &#039;clan1.png&#039; );&lt;br /&gt;
this.dontPreloadImage( &#039;clan2.png&#039; );&lt;br /&gt;
this.dontPreloadImage( &#039;clan3.png&#039; );&lt;br /&gt;
this.dontPreloadImage( &#039;clan4.png&#039; );&lt;br /&gt;
this.dontPreloadImage( &#039;clan5.png&#039; );&lt;br /&gt;
this.dontPreloadImage( &#039;clan6.png&#039; );&lt;br /&gt;
this.dontPreloadImage( &#039;clan7.png&#039; );&lt;br /&gt;
this.dontPreloadImage( &#039;clan8.png&#039; );&lt;br /&gt;
this.dontPreloadImage( &#039;clan9.png&#039; );&lt;br /&gt;
this.dontPreloadImage( &#039;clan10.png&#039; );&lt;br /&gt;
var to_preload = [];&lt;br /&gt;
for( i in this.gamedatas.clans )&lt;br /&gt;
{&lt;br /&gt;
	var clan_id = this.gamedatas.clans[i];&lt;br /&gt;
	to_preload.push( &#039;clan&#039;+clan_id+&#039;.png&#039; );&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
this.ensureSpecificGameImageLoading( to_preload );&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note:&#039;&#039;&#039; You don&#039;t need to specify to not preload game box images (game_box.png, game_box75.png...) since they are not preloaded by default.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.ensureSpecificGameImageLoading(list: string[])&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
This is oppostive of dontPreloadImage - its ensure specific images is loaded. Note: only makes sense if preload list is empty, otherwise everything is loaded anyway&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;load specific images&#039;&#039;&#039;&lt;br /&gt;
All images that will be preloaded stored in g_img_preload. If you want to override it directly - there is no API, but you can do this in GAME constructor&lt;br /&gt;
&lt;br /&gt;
          g_img_preload = [&#039;tokens.png&#039;, &#039;trains.png&#039;, &#039;loc_plan.png&#039;, &#039;eng.png&#039;, &#039;eng-back.png&#039;];&lt;br /&gt;
&lt;br /&gt;
You can also set it to empty array and call ensureSpecificGameImageLoading() on specific images&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Sounds ==&lt;br /&gt;
&lt;br /&gt;
Add a custom sound and make it load with your interface:&lt;br /&gt;
&lt;br /&gt;
Add this in your template (.tpl) file:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;audio id=&amp;quot;audiosrc_&amp;lt;gamename&amp;gt;_&amp;lt;yoursoundname&amp;gt;&amp;quot; src=&amp;quot;{GAMETHEMEURL}img/&amp;lt;gamename&amp;gt;_&amp;lt;yoursoundname&amp;gt;.mp3&amp;quot; preload=&amp;quot;none&amp;quot; autobuffer&amp;gt;&amp;lt;/audio&amp;gt;&lt;br /&gt;
&amp;lt;audio id=&amp;quot;audiosrc_o_&amp;lt;gamename&amp;gt;_&amp;lt;yoursoundname&amp;gt;&amp;quot; src=&amp;quot;{GAMETHEMEURL}img/&amp;lt;gamename&amp;gt;_&amp;lt;yoursoundname&amp;gt;.ogg&amp;quot; preload=&amp;quot;none&amp;quot; autobuffer&amp;gt;&amp;lt;/audio&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note: this is a requirement to provide both a mp3 and a ogg file with the names &amp;lt;code&amp;gt;&amp;lt;gamename&amp;gt;_&amp;lt;yoursoundname&amp;gt;[.ogg][.mp3]&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Play the sound (from your .js file):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
playSound(&#039;&amp;lt;gamename&amp;gt;_&amp;lt;yoursoundname&amp;gt;&#039;);   // do not add &#039;this.&#039; - its a global function&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Disable the standard &amp;quot;move&amp;quot; sound for this move (to replace it with your custom sound):&lt;br /&gt;
&lt;br /&gt;
Add this to your notification handler:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
this.disableNextMoveSound();&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note: it only disable the sound for the next move.&lt;br /&gt;
&lt;br /&gt;
== Title bar and states ==&lt;br /&gt;
&lt;br /&gt;
=== Client states ===&lt;br /&gt;
&lt;br /&gt;
Client states is a way to simulate the state transition but without actually going&lt;br /&gt;
to server. It is usefull when you need to ask user multiple questions before you&lt;br /&gt;
send things to server&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.setClientState(newState: string, args: object)&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
     this.setClientState(&amp;quot;client_playerPicksLocation&amp;quot;, {&lt;br /&gt;
                               descriptionmyturn : _(&amp;quot;${you} must select location&amp;quot;),&lt;br /&gt;
                           });&lt;br /&gt;
&lt;br /&gt;
For more information see [[BGA_Studio_Cookbook#Multi_Step_Interactions:_Select_Worker.2FPlace_Worker_-_Using_Client_States]]&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.restoreServerGameState()&#039;&#039;&#039;&lt;br /&gt;
If you are in client state it will restore the current server state (cheap undo)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.on_client_state&#039;&#039;&#039;&lt;br /&gt;
Boolean indicating that we are in client state&lt;br /&gt;
&lt;br /&gt;
=== Title bar ===&lt;br /&gt;
If you simply want to show something in title bar you can do it directly &lt;br /&gt;
     $(&#039;pagemaintitletext&#039;).innerHTML = text;&lt;br /&gt;
&lt;br /&gt;
This however will not work with parameters and will not draw You in color,&lt;br /&gt;
if you want to do proper args rendering use method below&lt;br /&gt;
&lt;br /&gt;
;&#039;&#039;&#039;this.removeActionButtons()&#039;&#039;&#039;&lt;br /&gt;
Removes all buttons from title bar&lt;br /&gt;
&lt;br /&gt;
;&#039;&#039;&#039;this.updatePageTitle()&#039;&#039;&#039;&lt;br /&gt;
:This function allows to update the current page title and turn description according to the game state arguments. If the current game state description this.gamedatas.gamestate.descriptionmyturn is modified before calling this function it allows to update the turn description without changing state. This will handle arguments substitutions properly.&lt;br /&gt;
&lt;br /&gt;
Note: this functional also will calls this.onUpdateActionButtons, if you want different buttons then state defaults, use method in example to replace them, if it becomes too clumsy use client states (see above)&lt;br /&gt;
&lt;br /&gt;
Example from Terra Mystica:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
onClickFavorTile: function( evt ) {&lt;br /&gt;
    ...&lt;br /&gt;
    if ( ... ) {&lt;br /&gt;
        this.gamedatas.gamestate.descriptionmyturn = _(&#039;Special action: &#039;) + _(&#039;Advance 1 space	on a Cult track&#039;);&lt;br /&gt;
        this.updatePageTitle();&lt;br /&gt;
        this.removeActionButtons();&lt;br /&gt;
        this.addActionButton( ... );&lt;br /&gt;
         ...&lt;br /&gt;
        return;&lt;br /&gt;
    }&lt;br /&gt;
    ...&lt;br /&gt;
&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== User preferences ==&lt;br /&gt;
&#039;&#039;&#039;this.getGameUserPreference(pref_id)&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Return the value of a user preference. It will return the value currently selected in the select combo box, in the top-right menu.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.setGameUserPreference(pref_id, value)&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Programmatically change a user preference. It will have the same effect as if the player changed the value in the select combo box, in the top-right menu.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.onGameUserPreferenceChanged&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
A callback you can define if you want to be notified when a user changes a user preference.&lt;br /&gt;
&lt;br /&gt;
Example:&amp;lt;pre&amp;gt;&lt;br /&gt;
onGameUserPreferenceChanged: function(pref_id, pref_value) {&lt;br /&gt;
  switch (pref_id) {&lt;br /&gt;
    case 201: &lt;br /&gt;
      document.getElementsByTagName(&#039;html&#039;)[0].classList.toggle(&#039;dark-background&#039;, pref_value == 2);&lt;br /&gt;
      break;&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Other useful stuff ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;dojo.hitch&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
With dojo.hitch, you can create a callback function that will run with your game object context whatever happen.&lt;br /&gt;
&lt;br /&gt;
Typical example: display a BGA confirmation dialog with a callback function created with dojo.hitch:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        this.confirmationDialog( _(&#039;Are you sure you want to make this?&#039;), dojo.hitch( this, function() {&lt;br /&gt;
            this.bgaPerformAction(&#039;makeThis&#039;);&lt;br /&gt;
        } ) );   &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In the example above, using dojo.hitch, we ensure that the &amp;quot;this&amp;quot; object will be set when the callback is called.&lt;br /&gt;
&lt;br /&gt;
NOTE: In modern JS there are lambdas that eliminate need for that, the example above will look like this&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        this.confirmationDialog( _(&#039;Are you sure you want to make this?&#039;), () =&amp;gt; this.bgaPerformAction( &#039;makeThis&#039;) );   &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
;&#039;&#039;&#039;onScreenWidthChange()&#039;&#039;&#039;&lt;br /&gt;
:This function can be overridden in your game to manage some resizing on the client side when the browser window is resized. This function is also triggered at load time, so it can be used to adapt to the :viewport size at the start of the game too.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
; this.bRealtime&lt;br /&gt;
: Return true if the game is in realtime. Note that having a distinct behavior in realtime and turn-based should be exceptional.&lt;br /&gt;
&lt;br /&gt;
; g_replayFrom&lt;br /&gt;
: Global contains replay number in live game, it is set to undefined (i.e. not set) when it is not a replay mode, so consequentially the good check is &#039;&#039;&#039;typeof g_replayFrom != &#039;undefined&#039;&#039;&#039;&#039; which returns true if the game is in replay mode &amp;lt;i&amp;gt;during the game&amp;lt;/i&amp;gt; (the game is ongoing but the user clicked &amp;quot;replay from this move&amp;quot; in the log)&lt;br /&gt;
&lt;br /&gt;
; g_archive_mode&lt;br /&gt;
: Returns true if the game is in archive mode &amp;lt;i&amp;gt;after the game&amp;lt;/i&amp;gt; (the game has ended)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
; this.instantaneousMode&lt;br /&gt;
: Returns true during replay/archive mode if animations should be skipped. Only needed if you are doing custom animations. (The BGA-provided animation functions like &amp;lt;i&amp;gt;this.slideToObject()&amp;lt;/i&amp;gt; automatically handle instantaneous mode.)&lt;br /&gt;
: Technically, when you click &amp;quot;replay from move #20&amp;quot;, the system replays the game from the very beginning with moves 0 - 19 happening in instantaneous mode and moves 20+ happening in normal mode.&lt;br /&gt;
&lt;br /&gt;
; g_tutorialwritten&lt;br /&gt;
: Returns an object like the below if the game is in tutorial mode, or undefined otherwise. Tutorial mode is a special case of archive mode where comments have been added to a previous game to teach new players the rules.&lt;br /&gt;
    {&lt;br /&gt;
        author: &amp;quot;91577332&amp;quot;,&lt;br /&gt;
        id: &amp;quot;576&amp;quot;,&lt;br /&gt;
        mode: &amp;quot;view&amp;quot;&lt;br /&gt;
        status: &amp;quot;alpha&amp;quot;&lt;br /&gt;
        version_override: null&lt;br /&gt;
        viewer_id: &amp;quot;84554161&amp;quot;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;getBgaEnvironment(): string&#039;&#039;&#039;&lt;br /&gt;
: Returns &amp;quot;studio&amp;quot; for studio and &amp;quot;prod&amp;quot; for production environment (i.e. where games current runs). Only useful for debbugging hooks.&lt;br /&gt;
Note: alpha server is also &amp;quot;prod&amp;quot;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Category:Studio]]&lt;/div&gt;</summary>
		<author><name>Sguzzer Gunayer</name></author>
	</entry>
	<entry>
		<id>https://en.doc.boardgamearena.com/index.php?title=Game_interface_logic:_Game.js&amp;diff=22731</id>
		<title>Game interface logic: Game.js</title>
		<link rel="alternate" type="text/html" href="https://en.doc.boardgamearena.com/index.php?title=Game_interface_logic:_Game.js&amp;diff=22731"/>
		<updated>2024-09-25T16:47:37Z</updated>

		<summary type="html">&lt;p&gt;Sguzzer Gunayer: /* Creating and Destroying elements */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Studio_Framework_Navigation}}&lt;br /&gt;
&lt;br /&gt;
__TOC__&lt;br /&gt;
&lt;br /&gt;
This is the main file for your game interface. Here you will define:&lt;br /&gt;
&lt;br /&gt;
* Which actions on the page will generate calls to the server.&lt;br /&gt;
* What happens when you get a notification for a change from the server and how it will show in the browser. &lt;br /&gt;
* Setup user interface&lt;br /&gt;
&lt;br /&gt;
== File structure ==&lt;br /&gt;
&lt;br /&gt;
The details of how the file is structured are described below with comments in the code skeleton provided to you.&lt;br /&gt;
&lt;br /&gt;
Here is the basic structure:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;constructor&#039;&#039;&#039;: here you can define global variables for your whole interface.&lt;br /&gt;
* &#039;&#039;&#039;setup&#039;&#039;&#039;: this method is called when the page is refreshed, and sets up the game interface.&lt;br /&gt;
* &#039;&#039;&#039;onEnteringState&#039;&#039;&#039;: this method is called when entering a new game state. You can use it to customize the view for each game state.&lt;br /&gt;
* &#039;&#039;&#039;onLeavingState&#039;&#039;&#039;: this method is called when leaving a game state.&lt;br /&gt;
* &#039;&#039;&#039;onUpdateActionButtons&#039;&#039;&#039;: called on state changes, in order to add action buttons to the status bar. Note: in a multipleactiveplayer state, it will be called when another player has become inactive.&lt;br /&gt;
* &#039;&#039;(utility methods)&#039;&#039;: this is where you can define your utility methods.&lt;br /&gt;
* &#039;&#039;(player&#039;s actions)&#039;&#039;: this is where you can write your handlers for player actions on the interface (example: click on an item).&lt;br /&gt;
* &#039;&#039;&#039;setupNotifications&#039;&#039;&#039;: this method associates notifications with notification handlers. For each game notification, you can trigger a javascript method to handle it and update the game interface.&lt;br /&gt;
* &#039;&#039;(notification handlers)&#039;&#039;: this is where you define the notifications handlers associated with notifications in &#039;&#039;&#039;setupNotifications&#039;&#039;&#039;, above.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
More details:&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;setup(gamedatas: object)            &#039;&#039;&#039;&lt;br /&gt;
This method must set up the game user interface according to current game situation specified in parameters.&lt;br /&gt;
The method is called each time the game interface is displayed to a player, ie:&lt;br /&gt;
&lt;br /&gt;
* when the game starts&lt;br /&gt;
* when a player opens a game in the browser later &lt;br /&gt;
* when a player refreshes the game page (F5)&lt;br /&gt;
* when player does a server side Undo&lt;br /&gt;
&lt;br /&gt;
&amp;quot;gamedatas&amp;quot; argument contains all data retrieved by your &amp;quot;getAllDatas&amp;quot; PHP method and some more.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;onEnteringState(stateName: string, args: { args: any } | null): void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
This method is called each time we enter a new game state.&lt;br /&gt;
You can use this method to perform some user interface changes at this moment.&lt;br /&gt;
To access state arguments passed via calling php arg* method use args?.args.&lt;br /&gt;
Typically you would do something only for active player, using this.isCurrentPlayerActive() check.&lt;br /&gt;
It is also called (for the current game state only) when doing a browser refresh (after the setup method is called).&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Warning&#039;&#039;&#039;: for multipleactiveplayer states:&lt;br /&gt;
the active players are NOT active yet so you must use onUpdateActionButtons to perform the client side operation which depends on a player active/inactive status.&lt;br /&gt;
If you are doing initialization of some structures which do not depend on the active player, you can just replace (this.isCurrentPlayerActive()) with (!this.isSpectator) &lt;br /&gt;
for the main switch in that method.&lt;br /&gt;
&lt;br /&gt;
See more details in [[Your_game_state_machine:_states.inc.php#Difference_between_Single_active_and_Multi_active_states]]&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;onLeavingState(stateName: string): void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
This method is called each time we leave a game state.&lt;br /&gt;
You can use this method to perform some user interface changes at this point (i.e. cleanup).&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;onUpdateActionButtons(stateName: string, args: object | null): void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
In this method you can manage &amp;quot;action buttons&amp;quot; that are displayed in the action status bar and highlight active UI elements.&lt;br /&gt;
To access state arguments passed via calling php arg* method use &#039;&#039;&#039;args&#039;&#039;&#039; parameter. Note: args can be null! For &#039;&#039;&#039;game&#039;&#039;&#039; states and when you don&#039;t supply state args function - it is null.&lt;br /&gt;
This method is called when the active or multiactive player changes. In a classic &amp;quot;activePlayer&amp;quot; state this method is called before the onEnteringState state.&lt;br /&gt;
In multipleactiveplayer state it is a mess. The sequencing of calls depends on whether you get into that state from transitions OR from reloading the whole game (i.e. F5).&lt;br /&gt;
&lt;br /&gt;
See more details in [[Your_game_state_machine:_states.inc.php#Difference_between_Single_active_and_Multi_active_states]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Dojo framework ==&lt;br /&gt;
&lt;br /&gt;
BGA uses the [http://dojotoolkit.org/ Dojo Javascript framework].&lt;br /&gt;
&lt;br /&gt;
The Dojo framework allows us to do complex things more easily. The BGA framework uses Dojo extensively.&lt;br /&gt;
&lt;br /&gt;
To implement a game, you only need to use a few parts of the Dojo framework. All the Dojo methods you need are described on this page.&lt;br /&gt;
&lt;br /&gt;
== Javascript minimization (after July 2020) ==&lt;br /&gt;
&lt;br /&gt;
For performance reasons, when deploying a game the javascript code is minimized using &#039;&#039;&#039;terser&#039;&#039;&#039; (https://github.com/terser/terser). This minifier works with modern javascript syntax. From your project &amp;quot;Manage game&amp;quot; page, you can now test a minified version of your javascript on the studio (and revert to the original).&lt;br /&gt;
&lt;br /&gt;
NB: it has been reported that there is an issue with this minifier and percentage values for opacity.&lt;br /&gt;
&lt;br /&gt;
== Accessing Players Information ==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.player_id: number&#039;&#039;&#039;&lt;br /&gt;
id of the player who is looking at the game. The player may not be part of the game (i.e. spectator)&lt;br /&gt;
  if (notif.args.player_id == this.player_id) {&lt;br /&gt;
    ...&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.isSpectator: boolean&#039;&#039;&#039;&lt;br /&gt;
Flag set to true if the user at the table is a spectator (not a player).&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    if (this.isSpectator) {&lt;br /&gt;
        this.player_color = &#039;ffffff&#039;;&lt;br /&gt;
    } else {&lt;br /&gt;
        this.player_color = gamedatas.players[this.player_id].color;&lt;br /&gt;
    }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note: If you want to hide an element from spectators, you should use [[Game_interface_stylesheet:_yourgamename.css#spectatorMode|CSS &#039;spectatorMode&#039; class]].&lt;br /&gt;
&lt;br /&gt;
You may consider making a function like this, to detect if the game is in a read-only state (i.e. non-interactive):&lt;br /&gt;
  // Returns true for spectators, instant replay (during game), archive mode (after game end)&lt;br /&gt;
  isReadOnly: function () {&lt;br /&gt;
    return this.isSpectator || typeof g_replayFrom != &#039;undefined&#039; || g_archive_mode;&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.gamedatas: object&#039;&#039;&#039;&lt;br /&gt;
Contains the initial set of data to init the game, created at game start or by game refresh (F5).&lt;br /&gt;
You can update it as needed to keep an up-to-date reference of the game on the client side if you need it, however most of the time this is unnecessary.&lt;br /&gt;
&lt;br /&gt;
Note: In hotseat mode, the framework does not keep this.gamedatas of hotseat players and shares the same set as the main player to store data.&lt;br /&gt;
&lt;br /&gt;
Note: be careful when you update this data structurally, many framework functions expect data to be certain way and they will break if they see something else.&lt;br /&gt;
&lt;br /&gt;
Typical example of accessing player&#039;s info&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
for (var player_id in this.gamedatas.players) { &lt;br /&gt;
    var playerInfo = this.gamedatas.players [player_id];&lt;br /&gt;
    var c = playerInfo.color;&lt;br /&gt;
    var name = playerInfo.name;&lt;br /&gt;
    // do something &lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.isCurrentPlayerActive(): boolean&#039;&#039;&#039;&lt;br /&gt;
Returns true if the player on whose browser the code is running is currently active (it&#039;s his turn to play). Note: see remarks above about usage of this function inside onEnteringState method.&lt;br /&gt;
  if (this.isCurrentPlayerActive()) ...&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.getActivePlayerId(): number&#039;&#039;&#039;&lt;br /&gt;
Return the ID of the active player, or null if we are not in an &amp;quot;activeplayer&amp;quot; type state.&lt;br /&gt;
  if (this.player_id == this.getActivePlayerId()) ...&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.getActivePlayers(): number[]&#039;&#039;&#039;&lt;br /&gt;
Return an array with the IDs of players who are currently active (or an empty array if there are none).&lt;br /&gt;
&lt;br /&gt;
== Accessing and manipulating the DOM ==&lt;br /&gt;
&lt;br /&gt;
=== Element by Id ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;$(elementId: ElementOrId)&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
The $ function is used to get an HTML element using its &amp;quot;id&amp;quot; attribute.&lt;br /&gt;
&lt;br /&gt;
Example: modify the content of a &amp;quot;span&amp;quot; element:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
In your HTML code:&lt;br /&gt;
   &amp;lt;span id=&amp;quot;a_value_in_the_game_interface&amp;quot;&amp;gt;1234&amp;lt;/span&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In your Javascript code:&lt;br /&gt;
   $(&#039;a_value_in_the_game_interface&#039;).innerHTML = &amp;quot;9999&amp;quot;;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Note: It is safe to use if you don&#039;t know if variable is string (id of element) or element itself, i.e. &lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  foo: function(card) {&lt;br /&gt;
       card = $(card); // now its node, no need to write if (typeof card === &#039;string&#039;) ...&lt;br /&gt;
       // but its good idea to check for null here&lt;br /&gt;
       ...&lt;br /&gt;
  }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;getElementById(elementId: string)&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Note: $() is the standard method to access some HTML element with the BGA Framework. You can use &#039;&#039;&#039;getElementById&#039;&#039;&#039; but it is longer to type and less handy as it does not do some checks.&lt;br /&gt;
&lt;br /&gt;
=== Style ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;dojo.style(node: ElementOrId, styleName: string, styleValue: any): void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
With dojo.style you can modify the CSS property of any HTML element in your interface.&lt;br /&gt;
&lt;br /&gt;
Examples:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
     // Make an element disappear&lt;br /&gt;
     dojo.style( &#039;my_element&#039;, &#039;display&#039;, &#039;none&#039; );&lt;br /&gt;
&lt;br /&gt;
     // Give an element a 2px border&lt;br /&gt;
     dojo.style( &#039;my_element&#039;, &#039;borderWidth&#039;, &#039;2px&#039; );&lt;br /&gt;
&lt;br /&gt;
     // Change the background position of an element&lt;br /&gt;
     // (very practical when you are using CSS sprites to transform an element to another)&lt;br /&gt;
     dojo.style( &#039;my_element&#039;, &#039;backgroundPosition&#039;, &#039;-20px -50px&#039; );&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note: if you have to modify several CSS properties of an element, or if you have a complex CSS transformation to do, you should consider using dojo.addClass/dojo.removeClass (see below).&lt;br /&gt;
&lt;br /&gt;
You can also use object to set multiple values&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
dojo.setStyle(&amp;quot;thinger&amp;quot;, {&lt;br /&gt;
  &amp;quot;opacity&amp;quot;: 0.5,&lt;br /&gt;
  &amp;quot;border&amp;quot;: &amp;quot;3px solid black&amp;quot;,&lt;br /&gt;
  &amp;quot;height&amp;quot;: &amp;quot;300px&amp;quot;&lt;br /&gt;
});&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.addStyleToClass(cssClassName: string, styleName: string, styleValue: any):&#039;&#039;&#039; &#039;&#039;&#039;void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Same as dojo.style(), but for all the nodes set with the specified cssClassName&lt;br /&gt;
Equivalent of &lt;br /&gt;
  &lt;br /&gt;
  dojo.query(`.${aclass}`).style(styleName, styleValue)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
dojo.query(&amp;quot;#baz &amp;gt; div&amp;quot;).style({&lt;br /&gt;
  opacity:0.75,&lt;br /&gt;
  fontSize:&amp;quot;13pt&amp;quot;&lt;br /&gt;
});&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Vanilla JS style&#039;&#039;&#039;&lt;br /&gt;
  $(&#039;my_element&#039;).style.display=&#039;none&#039;; // set&lt;br /&gt;
  var display = $(&#039;my_element&#039;).style.display; // get&lt;br /&gt;
  $(&#039;my_element&#039;).style.removeProperty(&#039;display&#039;); // remove&lt;br /&gt;
&lt;br /&gt;
=== Classes ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;dojo.addClass(node: ElementOrId, classes: string): void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;dojo.removeClass(node: ElementOrId, classes: string): void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;dojo.hasClass(node: ElementOrId, aclass: string): void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;dojo.toggleClass(node: ElementOrId, aclass: string): void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
In many situations, many small CSS property updates can be replaced by a CSS class change (i.e., you add a CSS class to your element instead of applying all modifications manually).&lt;br /&gt;
&lt;br /&gt;
Advantages are:&lt;br /&gt;
* All your CSS stuff remains in your CSS file.&lt;br /&gt;
* You can add/remove a list of CSS modifications with a simple function and without error.&lt;br /&gt;
* You can test whether you applied the CSS to an element with the &#039;&#039;&#039;dojo.hasClass&#039;&#039;&#039; method.&lt;br /&gt;
&lt;br /&gt;
Example from &#039;&#039;Reversi&#039;&#039;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    // We add &amp;quot;possibleMove&amp;quot; to an element&lt;br /&gt;
    dojo.addClass( &#039;square_&#039;+x+&#039;_&#039;+y, &#039;possibleMove&#039; );&lt;br /&gt;
&lt;br /&gt;
    // In our CSS file, the class is defined as:&lt;br /&gt;
    .possibleMove {&lt;br /&gt;
      background-color: white;&lt;br /&gt;
      opacity: 0.2;&lt;br /&gt;
      filter:alpha(opacity=20); /* For IE8 and earlier */  &lt;br /&gt;
      cursor: pointer;  &lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
     // So we&#039;ve applied 4 CSS property changes in one line of code.&lt;br /&gt;
&lt;br /&gt;
     // ... and when we need to check if a square is a possible move on the client side:&lt;br /&gt;
     if( dojo.hasClass( &#039;square_&#039;+x+&#039;_&#039;+y, &#039;possibleMove&#039; ) )&lt;br /&gt;
     { ... }&lt;br /&gt;
&lt;br /&gt;
     // ... and if we want to remove all possible moves in one line of code (see &amp;quot;dojo.query&amp;quot; method):&lt;br /&gt;
     dojo.query( &#039;.possibleMove&#039; ).removeClass( &#039;possibleMove&#039; );&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Vanilla JS classList&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
This is the only exception where dojo versions are better&lt;br /&gt;
  // add class&lt;br /&gt;
  $(token_id).classList.addClass(&#039;possibleMove&#039;);&lt;br /&gt;
  // remove class&lt;br /&gt;
  $(token_id).classList.removeClass(&#039;possibleMove&#039;);&lt;br /&gt;
  // add 2 classes&lt;br /&gt;
  const myclasses = [&#039;a&#039;,&#039;b&#039;];&lt;br /&gt;
  $(token_id).classList.addClass(...myclasses);&lt;br /&gt;
  // add classes to query result&lt;br /&gt;
  document.querySelectorAll(&amp;quot;.hand .card&amp;quot;).forEach((node)=&amp;gt;node.classList.addClass(&#039;possibleMove&#039;));&lt;br /&gt;
&lt;br /&gt;
=== Attributes ===&lt;br /&gt;
&lt;br /&gt;
;dojo.attr&lt;br /&gt;
&lt;br /&gt;
With dojo.attr you can access or change the value of an attribute or property of any HTML element in your interface.&lt;br /&gt;
&lt;br /&gt;
Exemple:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
     // Get the title of a node&lt;br /&gt;
     var title = dojo.attr( id, &#039;title&#039; );&lt;br /&gt;
     // Change the height of a node&lt;br /&gt;
     dojo.attr( &#039;img_growing_tree&#039;, &#039;height&#039;, 100 );&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Vanilla JS attr&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
   $(token).id=new_id; // set attr for &amp;quot;id&amp;quot;&lt;br /&gt;
   var id = $(token).id; // get&lt;br /&gt;
&lt;br /&gt;
=== Queries ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;dojo.query(cssSelector: string): Element[]&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
With dojo.query, you can query a bunch of HTML elements with a single function, with a &amp;quot;CSS selector&amp;quot; style.&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
     // All elements with class &amp;quot;possibleMove&amp;quot;:&lt;br /&gt;
     var elements = dojo.query( &#039;.possibleMove&#039; );&lt;br /&gt;
&lt;br /&gt;
     // Count number of tokens (i.e., elements of class &amp;quot;token&amp;quot;) on the board (i.e., the element with id &amp;quot;board&amp;quot;):&lt;br /&gt;
     dojo.query( &#039;#board .token&#039; ).length;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
But what is really cool with dojo.query is that you can combine it with almost all methods above.&lt;br /&gt;
&lt;br /&gt;
Examples:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
     // Trigger a method when the mouse enter in any element with class &amp;quot;meeple&amp;quot;:&lt;br /&gt;
     dojo.query( &#039;.meeple&#039; ).connect( &#039;onmouseenter&#039;, this, &#039;myMethodToTrigger&#039; );&lt;br /&gt;
&lt;br /&gt;
     // Hide all meeples who are on the board&lt;br /&gt;
     dojo.query( &#039;#board .meeple&#039; ).style( &#039;display&#039;, &#039;none&#039; );&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Vanilla JS query&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
  var cards=document.querySelectorAll(&amp;quot;.hand .card&amp;quot;);// all cards in all hands&lt;br /&gt;
  var cards=$(&#039;hand&#039;).querySelectorAll(&amp;quot;.card&amp;quot;);// all cards in specific hand&lt;br /&gt;
  var card=document.querySelector(&amp;quot;.hand .card&amp;quot;);// first card or null if none (super handy)&lt;br /&gt;
&lt;br /&gt;
=== Creating and Destroying elements ===&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;dojo.empty(node: ElementOrId)&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Remove all children of the node element&lt;br /&gt;
   dojo.empty(&#039;my_hand&#039;);&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;dojo.destroy(node: ElementOrId)&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Remove the element&lt;br /&gt;
   dojo.destroy(&#039;my_token&#039;);&lt;br /&gt;
&lt;br /&gt;
   dojo.query(&amp;quot;.green&amp;quot;, mynode).forEach(dojo.destroy); // this remove all subnode of class green from mynode&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;dojo.create(tag: string, attributes?: obj, parent?: ElementOrId): Element&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Create element&lt;br /&gt;
&lt;br /&gt;
    dojo.create(&amp;quot;div&amp;quot;, { class: &amp;quot;yellow_arrow&amp;quot; }, parent); // this creates div with class yellow_array and places it in &amp;quot;parent&amp;quot;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.format_block(name: string, args: object): string&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
This bga function that takes global var from template file and substitute variables, typical use would be&lt;br /&gt;
&lt;br /&gt;
                var player = gamedatas.players[player_id];&lt;br /&gt;
                var div = this.format_block(&#039;jstpl_player_board&#039;, player ); // var jstpl_player_board = ... is defined in .tpl file &lt;br /&gt;
Note: result is trimmed&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.format_string(name: string, args: object): string&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
This bga function just substitute variables in a string, i.e.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
     var div = this.format_string(&#039;&amp;lt;div color=&amp;quot;${player_color}&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&#039;, {player_color: &#039;#ff0000&#039;} );&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Note: result is trimmed&lt;br /&gt;
&lt;br /&gt;
Note: this can be replaced by using backquoted string now: &lt;br /&gt;
     const player_color =  &#039;#ff0000&#039;;&lt;br /&gt;
&lt;br /&gt;
    const div = ``;&lt;br /&gt;
&#039;&#039;&#039;this.format_string_recursive&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
This bga function is similar to this.format_string but is capable of processing recursive argument structures and translations. It is used to format server notifications.&lt;br /&gt;
&lt;br /&gt;
TODO: find better place for these function docs&lt;br /&gt;
&lt;br /&gt;
=== Moving elements ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;dojo.place(node: string | Element, refNode: ElementOrId, pos?: string | number): Element&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
dojo.place is the best function to insert HTML code somewhere in your game interface without breaking something. It is much better to use than the &#039;&#039;&#039;innerHTML=&#039;&#039;&#039; method if you must insert HTML tags and not only values.&lt;br /&gt;
&lt;br /&gt;
node: &lt;br /&gt;
&lt;br /&gt;
Can be a String or a DOM node. If it is a string starting with “&amp;lt;”, it is assumed to be an HTML fragment, which will be created. Otherwise it is assumed to be an id of a DOM node.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
     // Insert your HTML code as a child of a container element&lt;br /&gt;
     dojo.place( &amp;quot;&amp;lt;div class=&#039;foo&#039;&amp;gt;&amp;lt;/div&amp;gt;&amp;quot;, &amp;quot;your_container_element_id&amp;quot; );&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
pos:&lt;br /&gt;
&lt;br /&gt;
Optional argument. Can be a number or one of the following strings: “before”, “after”, “replace”, “only”, “first”, or “last”. If omitted, “last” is assumed. &lt;br /&gt;
&lt;br /&gt;
&amp;quot;replace&amp;quot;: Replace the container element with my_node element&lt;br /&gt;
&lt;br /&gt;
&amp;quot;first&amp;quot;: Places the node as a child of the reference node. The node is placed as the first child.&lt;br /&gt;
&lt;br /&gt;
&amp;quot;last&amp;quot; (default): Places the node as a child of the reference node. The node is placed as the last child.&lt;br /&gt;
&lt;br /&gt;
&amp;quot;before&amp;quot;: places the node right before the reference node.&lt;br /&gt;
&lt;br /&gt;
&amp;quot;after&amp;quot;: places the node right after the reference node.&lt;br /&gt;
&lt;br /&gt;
&amp;quot;only&amp;quot;: replaces all children of the reference node with the node.&lt;br /&gt;
&lt;br /&gt;
positive integer: This parameter can be a positive integer. In this case, the node will be placed as a child of the reference node with this number (counting from 0). If the number is more than number of children, the node will be appended to the reference node making it the last child. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
     // Replace all children of container with my_node &lt;br /&gt;
     dojo.place( $(&#039;my_node&#039;), &amp;quot;your_container_element_id&amp;quot;, &amp;quot;only&amp;quot; );&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
See also full doc on dojo.place: [https://dojotoolkit.org/reference-guide/1.7/dojo/place.html]&lt;br /&gt;
&lt;br /&gt;
Usually, when you want to insert some piece of HTML in your game interface, you should use &amp;quot;[[Game_layout:_view_and_template:_yourgamename.view.php_and_yourgamename_yourgamename.tpl#Javascript_templates|Javascript templates]]&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
But you can also relocate elements like that. Note: it won&#039;t animate if you do that.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.placeOnObject(mobile_obj: ElementOrId, target_obj: ElementOrId): void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
places mobile_obj on target_obj, set the absolute positions and centers the mobile_obj on target_obj,&lt;br /&gt;
effect is immediate&lt;br /&gt;
&lt;br /&gt;
This is not really an animation, but placeOnObject is frequently used before starting an animation.&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  // (We just created an object &amp;quot;my_new_token&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
  // Place the new token on current player board&lt;br /&gt;
  this.placeOnObject( &amp;quot;my_new_token&amp;quot;, &amp;quot;overall_player_board_&amp;quot;+this.player_id );&lt;br /&gt;
  &lt;br /&gt;
  // Then slide it to its position on the board&lt;br /&gt;
  this.slideToObject( &amp;quot;my_new_token&amp;quot;, &amp;quot;a_place_on_board&amp;quot; ).play();&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.placeOnObjectPos(mobile_obj: ElementOrId, target_obj: ElementOrId, target_x: number, target_y: number): void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
This method works exactly like placeOnObject, except than you can specify some (x,y) coordinates (in px). This way, the center of &amp;quot;mobile_obj&amp;quot; will be placed to the specified x,y position relatively to the center of &amp;quot;target_obj&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Note: the placement works differently from this.slideToObjectPos&#039;&#039;, since coordinates are calculated based on the center of objects.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.attachToNewParent(mobile_obj: ElementOrId, target_obj: ElementOrId): void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
With this method, you change the HTML parent of &amp;quot;mobile_obj&amp;quot; element without moving it. &lt;br /&gt;
&amp;quot;target_obj&amp;quot; is the new parent of this element. The beauty of &lt;br /&gt;
attachToNewParent is that the mobile_obj element DOES NOT MOVE during this process.&lt;br /&gt;
&lt;br /&gt;
What happens is that the method calculate a relative position of mobile_obj to make sure it does not move after the HTML parent changes.&lt;br /&gt;
&lt;br /&gt;
Why using this method?&lt;br /&gt;
&lt;br /&gt;
Changing the HTML parent of an element can be useful for the following reasons:&lt;br /&gt;
* When the HTML parent moves, all its child are moving with them. If some game elements is no more linked with a parent HTML object, you may want to attach it to another place.&lt;br /&gt;
* The z_order (vertical order of display) depends on the position in the DOM, so you may need to change the parent of some game elements when they are moving in your game area.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;CAREFUL&#039;&#039;&#039;: this function destroys original object and places a clone onto a new parent, this will break all references to this HTML element (ex: dojo.connect).&lt;br /&gt;
If you need version that does not destroy the object but the same otherwise see [[BGA_Studio_Cookbook#Attach_to_new_parent_without_destroying_the_object]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Animations ==&lt;br /&gt;
&lt;br /&gt;
===Dojo Animations===&lt;br /&gt;
&lt;br /&gt;
BGA animations is based on Dojo Animation ([http://dojotoolkit.org/documentation/tutorials/1.8/animation/ see tutorial here]).&lt;br /&gt;
&lt;br /&gt;
However, most of the time, you can just use methods below, which are built on top of Dojo Animation.&lt;br /&gt;
&lt;br /&gt;
Note: one interesting method from Dojo that could be useful from time to time is &amp;quot;Dojo.Animation&amp;quot;. It allows you to make any CSS property &amp;quot;slide&amp;quot; from one value to another.&lt;br /&gt;
&lt;br /&gt;
Note 2: the slideTo methods are not compatible with CSS transform (scale, zoom, rotate...). If possible, avoid using CSS transform on nodes that are being slided. Eventually, the only possible solution to make these 2 compatible is to disable all CSS transform properties, use slideToObjectPos/placeOnObjectPos, and then apply them again.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Sliding===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.slideToObject(mobile_obj: ElementOrId, target_obj: ElementOrId, duration?: number, delay?: number): Animation&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
You can use slideToObject to &amp;quot;slide&amp;quot; an element to a target position.&lt;br /&gt;
&lt;br /&gt;
Sliding element on the game area is the recommended and the most used way to animate your game interface. Using slides allow players to figure out what is happening on the game, as if they were playing with the real boardgame.&lt;br /&gt;
&lt;br /&gt;
The parameters are:&lt;br /&gt;
* mobile_obj: the ID of the object to move. This object must be &amp;quot;relative&amp;quot; or &amp;quot;absolute&amp;quot; positioned.&lt;br /&gt;
* target_obj: the ID of the target object. This object must be &amp;quot;relative&amp;quot; or &amp;quot;absolute&amp;quot; positioned. Note that it is not mandatory that mobile_obj and target_obj have the same size. If their size are different, the system slides the center of mobile_obj to the center of target_obj.&lt;br /&gt;
* duration: (optional) defines the duration in millisecond of the slide. The default is 500 milliseconds.&lt;br /&gt;
* delay: (optional). If you defines a delay, the slide will start only after this delay. This is particularly useful when you want to slide several object from the same position to the same position: you can give a 0ms delay to the first object, a 100ms delay to the second one, a 200ms delay to the third one, ... this way they won&#039;t be superposed during the slide.&lt;br /&gt;
&lt;br /&gt;
BE CAREFUL: The method returns an dojo.fx animation, so you can combine it with other animation if you want to. It means that you have to call the &amp;quot;play()&amp;quot; method, otherwise the animation WON&#039;T START.&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
   this.slideToObject( &amp;quot;some_token&amp;quot;, &amp;quot;some_place_on_board&amp;quot; ).play();&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.slideToObjectPos(mobile_obj: ElementOrId, target_obj: ElementOrId, target_x: number, target_y: number, duration?: number, delay?: number): Animation&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
This method does exactly the same as &amp;quot;slideToObject&amp;quot;, except than you can specify some (x,y) coordinates. This way, &amp;quot;mobile_obj&amp;quot; will slide to the specified x,y position relatively to &amp;quot;target_obj&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
Example: slide a token to some place on the board, 10 pixels from the top:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
   this.slideToObjectPos( &amp;quot;some_token&amp;quot;, &amp;quot;some_place_on_board&amp;quot;, 0, 10 ).play();&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.slideTemporaryObject(mobile_obj_html: string, parent: ElementOrId, from: ElementOrId, to: ElementOrId, duration?: number, delay?: number): Animation&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
This method is useful when you want to slide a temporary HTML object from one place to another. As this object does not exists before the animation and won&#039;t remain after, it could be complex to create this object (with dojo.place), to place it at its origin (with placeOnObject) to slide it (with slideToObject) and to make it disappear at the end.&lt;br /&gt;
&lt;br /&gt;
slideTemporaryObject does all of this for you:&lt;br /&gt;
* mobile_obj_html is a piece of HTML code that represent the object to slide.&lt;br /&gt;
* parent is the ID of an HTML element of your interface that will be the parent of this temporary HTML object.&lt;br /&gt;
* from is the ID of the origin of the slide.&lt;br /&gt;
* to is the ID of the target of the slide.&lt;br /&gt;
* duration/delay works exactly like in &amp;quot;slideToObject&amp;quot;&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
this.slideTemporaryObject( &#039;&amp;lt;div class=&amp;quot;token_icon&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&#039;, &#039;tokens&#039;, &#039;my_origin_div&#039;, &#039;my_target_div&#039; ).play();&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Destroy===&lt;br /&gt;
&#039;&#039;&#039;this.slideToObjectAndDestroy(mobile_obj: ElementOrId, target_obj: ElementOrId, duration?: number, delay?: number): void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
This method is a handy shortcut to slide an existing HTML object to some place then destroy it upon arrival. It can be used for example to move a victory token or a card from the board to the player panel to show that the player earns it, then destroy it when we don&#039;t need to keep it visible on the player panel.&lt;br /&gt;
&lt;br /&gt;
It works the same as this.slideToObject and takes the same arguments, but it starts the animation. &lt;br /&gt;
&lt;br /&gt;
CAREFUL: Make sure nothing is creating the same object at the same time the animation is running, because this will cause some random disappearing effects&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
this.slideToObjectAndDestroy( &amp;quot;some_token&amp;quot;, &amp;quot;some_place_on_board&amp;quot;, 1000, 0 );&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.fadeOutAndDestroy( node: string | Element, duration?: number, delay?: number):&#039;&#039;&#039; &#039;&#039;&#039;void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
This function fade out the target node, then destroy it. Its starts the animation.&lt;br /&gt;
* duration/delay works exactly like in &amp;quot;slideToObject&amp;quot;&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
   this.fadeOutAndDestroy( &amp;quot;a_card_that_must_disappear&amp;quot; );&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
CAREFUL: the HTML node still exists until during few milliseconds, until the fadeOut has been completed.&lt;br /&gt;
Make sure nothing is creating same object at the same time as animation is running, because you will be some random dissapearing effects&lt;br /&gt;
&lt;br /&gt;
===Rotating elements===&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
This example combines &amp;quot;Dojo.Animation&amp;quot; method and a CSS property transform that allow you to rotate the element.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
// node is Element we rotating&lt;br /&gt;
		    var animation = new dojo.Animation({&lt;br /&gt;
			    curve: [fromDegree, toDegree],&lt;br /&gt;
			    onAnimate: (v) =&amp;gt; {&lt;br /&gt;
				    node.style.transform = &#039;rotate(&#039; + v + &#039;deg)&#039;;&lt;br /&gt;
			    } &lt;br /&gt;
		    });&lt;br /&gt;
		    &lt;br /&gt;
		    animation.play();  &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
BGA has its own interface to rotate&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.rotateTo(node: string | Element, degree: number): void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
It starts the animation, and stored the rotation degree in the class, so next time you rotate object - it is additive.&lt;br /&gt;
There is no animation hooks in this one, if you need to change any parameters use dojo animation above.&lt;br /&gt;
&lt;br /&gt;
There is also &#039;&#039;&#039;rotateInstantTo&#039;&#039;&#039; with same signature which does not animate&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Animation Callbacks===&lt;br /&gt;
&lt;br /&gt;
If you wish to run some code only after an animation has completed you can do this by linking a callback method to &#039;onEnd&#039;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
var animation_id = this.slideToObject( mobile_obj, target_obj, 500 );&lt;br /&gt;
dojo.connect(animation_id, &#039;onEnd&#039;, () =&amp;gt; {&lt;br /&gt;
   // do something here&lt;br /&gt;
});&lt;br /&gt;
animation_id.play();&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If you wish to call a second animation after the first (rather than general code) then you can use a dojo animation chain (see tutorial referenced above).&lt;br /&gt;
&lt;br /&gt;
== Players input ==&lt;br /&gt;
&lt;br /&gt;
=== Connecting ===&lt;br /&gt;
&#039;&#039;&#039;dojo.connect(element: Element, event: string, context: object, method: eventHandler): any&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;dojo.connect(element: Element, event: string, hander: eventHandler): any&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Used to associate a player event with one of your notification methods.&lt;br /&gt;
&lt;br /&gt;
Example: associate a click on an element (&amp;quot;my_element&amp;quot;) with one of our methods (&amp;quot;onClickOnMyElement&amp;quot;):&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
      dojo.connect( $(&#039;my_element&#039;), &#039;onclick&#039;, this, &#039;onClickOnMyElement&#039; );&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Same idea but base on query (i.e. all element of &#039;pet&#039; class)&lt;br /&gt;
      dojo.query(&amp;quot;.pet&amp;quot;).connect(&#039;onclick&#039;, this, &#039;onPet&#039;);&lt;br /&gt;
&lt;br /&gt;
Note: if you need to disconnect the handler you have to store handler returned from this method, i.e.&lt;br /&gt;
   &lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    var handler = dojo.connect(...);&lt;br /&gt;
    ...&lt;br /&gt;
    dojo.disconnect(handler);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If you don&#039;t store the handler - you have to destroy the object to disconnect it&lt;br /&gt;
&lt;br /&gt;
Typical function that implements the input handler will look like this&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
onPet: function(event) {&lt;br /&gt;
    var id = event.currentTarget.id;&lt;br /&gt;
    console.log(&#039;onPet &#039; + id);&lt;br /&gt;
    dojo.stopEvent(event);&lt;br /&gt;
    if (this.gamedatas.gamestate.name == &#039;playerTurnPet&#039;) {&lt;br /&gt;
          this.bgaPerformAction(&#039;actPlayPet&#039;, {card: id});&lt;br /&gt;
    } else {&lt;br /&gt;
          this.showMoveUnauthorized();&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.connect(element: ElementOrId, event: string, method: eventHandler): void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Used to associate a player event with one of your notification methods.&lt;br /&gt;
&lt;br /&gt;
      this.connect( $(&#039;my_element&#039;), &#039;onclick&#039;, &#039;onClickOnMyElement&#039; );&lt;br /&gt;
&lt;br /&gt;
Or you can use an in-place handler&lt;br /&gt;
&lt;br /&gt;
      this.connect( $(&#039;my_element&#039;), &#039;onclick&#039;, (e) =&amp;gt; { console.log(&#039;boo&#039;); } );&lt;br /&gt;
&lt;br /&gt;
Note that this function stores the connection handler. That is the only real difference between &#039;&#039;&#039;this.connect&#039;&#039;&#039; and &#039;&#039;&#039;dojo.connect&#039;&#039;&#039;. If you plan to destroy the element you connected, you &#039;&#039;&#039;must&#039;&#039;&#039; call this.disconnect() to prevent memory leaks.&lt;br /&gt;
This function is mainly for permanent objects - if you just want to connect the temp object you should probably not use this method but use dojo.connect which won&#039;t require any clean-up.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.connectClass(cssClassName: string, event: string, method: eventHandler): void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Same as connect(), but for all the nodes set with the specified cssClassName.&lt;br /&gt;
&lt;br /&gt;
	this.connectClass(&#039;pet&#039;, &#039;onclick&#039;, &#039;onPet&#039;);&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.disconnect(element: ElementOrId, event: string): void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Disconnect event handler (previously registered with this.connect or this.connectClass).&lt;br /&gt;
&lt;br /&gt;
   this.disconnect( $(&#039;my_element&#039;), &#039;onclick&#039;);&lt;br /&gt;
&lt;br /&gt;
Note: dynamic connect/disconnect is for advanced cases ONLY, you should always connect elements statically if possible, i.e. in setup() method.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.disconnectAll(): void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Disconnect all previously registed event handlers (registered via this.connect or this.connectClass)&lt;br /&gt;
&lt;br /&gt;
  this.disconnectAll();&lt;br /&gt;
&lt;br /&gt;
=== Actions ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.bgaPerformAction(action: string, args?: object, options: object = { lock: true, checkAction: true }): Promise&amp;lt;void&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Triggers an action on the backend. This is a combination of checkAction and ajaxcall, returning a Promise which resoves when ajaxcall ends.&lt;br /&gt;
&lt;br /&gt;
This method must be used to send a player input to the game server. &#039;&#039;&#039;It should not be triggered programmatically&#039;&#039;&#039;, especially not in loops, in callbacks, in notifications, or in onEnteringState/onUpdateActionButtons/onLeavingState, in order not to create race conditions or break replay game and tutorial features. It should be used only in reaction to a user action in the interface.&lt;br /&gt;
&lt;br /&gt;
* action: name of the action, as it is written in &amp;quot;possibleactions&amp;quot; of the current state.&lt;br /&gt;
* args: an object containing the call parameters to send to the action&lt;br /&gt;
* options: options to tweak the call with some defaults. Default is &amp;lt;code&amp;gt;{ lock: true, checkAction: true }&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Example of a standard call without args:&lt;br /&gt;
  this.bgaPerformAction(&#039;pass&#039;);&lt;br /&gt;
&lt;br /&gt;
Example of a standard call with action args:&lt;br /&gt;
  this.bgaPerformAction(&#039;actPlayCard&#039;, { id: this.selectedCardId });&lt;br /&gt;
&lt;br /&gt;
Example of a call without checking action (because player is inactive in a multiactive state):&lt;br /&gt;
&lt;br /&gt;
 this.bgaPerformAction(&#039;actChangeMind&#039;, {}, { checkAction: false });&lt;br /&gt;
&lt;br /&gt;
Example of a call without lock (because of a special action not directly related to the game flow):&lt;br /&gt;
&lt;br /&gt;
 this.bgaPerformAction(&#039;actSetAutoBid&#039;, { alwaysBidUntil: 500 }, { lock: false, checkAction: false });&lt;br /&gt;
&lt;br /&gt;
Example of call with reaction to exception:&lt;br /&gt;
  this.bgaPerformAction(&#039;actPlayCard&#039;, { id: this.selectedCardId }).catch(()=&amp;gt;{ this.selectedCardId = undefined; });&lt;br /&gt;
&lt;br /&gt;
Example of call with reaction to success:&lt;br /&gt;
  this.bgaPerformAction(&#039;actPlayCard&#039;, { id: this.selectedCardId }).then(()=&amp;gt;{ this.unselectAll(); });&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.ajaxcall(url, parameters, obj_callback, callback, callback_anycase?, ajax_method?: string)&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Note: bgaPerformAction is a simpler way to use ajax calls, ajaxcall stays in the doc for legacy reasons only and should not be used in new projects.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Same warning as &#039;&#039;&#039;this.bgaPerformAction&#039;&#039;&#039; about using on user action only.&lt;br /&gt;
&lt;br /&gt;
* url: the url of the action to perform. For a game, it must be: &amp;quot;/&amp;lt;mygame&amp;gt;/&amp;lt;mygame&amp;gt;/myAction.html&amp;quot;&lt;br /&gt;
* parameters: an array of parameter to send to the game server. &lt;br /&gt;
** Note that &amp;quot;lock: true&amp;quot; must always be specified in this list of parameters in order the interface can be locked during the server call. Cannot use lock: false - to not lock it has to be undefined.&lt;br /&gt;
** Note: Restricted parameter names (please don&#039;t use them):&lt;br /&gt;
*** &amp;quot;action&amp;quot;&lt;br /&gt;
*** &amp;quot;module&amp;quot;&lt;br /&gt;
*** &amp;quot;class&amp;quot;&lt;br /&gt;
* obj_callback: must be set to &amp;quot;this&amp;quot;.&lt;br /&gt;
* callback (non-optional but rarely used): a function to trigger when the server returns result and everything went fine (not used, as all data handling is done via notifications).&lt;br /&gt;
* callback_anycase: (optional) a function to trigger when the server returns ok OR error.  If no error this function is called with parameter value false. If an error occurred, the first parameter will be set to true, the second will contain the error message sent by the PHP back-end, and the third will contain an error code.&lt;br /&gt;
* ajax_method: (optional and rarely used) if you need to send large amounts of data (over 2048 bytes), you can set this parameter to &#039;post&#039; (all lower-case) to send a POST request as opposed to the default GET. This works, but was not officially documented, so only use if you really need to.&lt;br /&gt;
&lt;br /&gt;
Usage:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
this.ajaxcall( &#039;/mygame/mygame/actMyAction.html&#039;, { lock: true, &lt;br /&gt;
   arg1: myarg1, &lt;br /&gt;
   arg2: myarg2&lt;br /&gt;
}, this, (result)=&amp;gt;{} );&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.checkAction(action: string, nomessage?: boolean): boolean &#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Check if player can do the specified action by taking into account:&lt;br /&gt;
* if interface is locked it will return false and show message &amp;quot;An action is already in progress&amp;quot;,  unless nomessage set to true &lt;br /&gt;
* if player is not active it will return false and show message &amp;quot;This is not your turn&amp;quot;, unless nomessage set to true &lt;br /&gt;
* if action is not in list in possible actions (defined by &amp;quot;possibleaction&amp;quot; in current game state) it will return false and show &amp;quot;This move is not authorized now&amp;quot; error (unconditionally).&lt;br /&gt;
* otherwise returns true&lt;br /&gt;
Example:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  function onClickOnGameElement( evt )  {&lt;br /&gt;
     if( this.checkAction( &amp;quot;actMyAction&amp;quot; ) ) {&lt;br /&gt;
        // Do the action&lt;br /&gt;
     }&lt;br /&gt;
  }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.checkPossibleActions(action: string): boolean&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
* this is independent of the player being active, so can be used instead of this.checkAction(). This is particularly useful for multiplayer states when the player is not active in a &#039;player may like to change their mind&#039; scenario. Unlike this.checkAction, this function does NOT take interface locking into account &lt;br /&gt;
&lt;br /&gt;
* if action is not in list in possible actions (defined by &amp;quot;possibleaction&amp;quot; in current game state) it will return false and show &amp;quot;This move is not authorized now&amp;quot; error (unconditionally).&lt;br /&gt;
* otherwise returns true&lt;br /&gt;
&lt;br /&gt;
  function onChangeMyMind( evt )  {&lt;br /&gt;
     if( this.checkPossibleActions( &amp;quot;actMyAction&amp;quot; ) ) {&lt;br /&gt;
        // Do the action&lt;br /&gt;
     }&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.checkLock(nomessage?: boolean): boolean&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
When using &amp;quot;lock: true&amp;quot; in ajax call you can use this function to check if interface is in lock state (it will be locked during server call and notification processing).&lt;br /&gt;
This check can be used to block some other interactions which do not result in ajaxcall or if you want to suppress errors. Note: normally you only need to use this.checkAction(...), this is for advanced cases.&lt;br /&gt;
&lt;br /&gt;
It will also show error unless nomessage is set to true&lt;br /&gt;
&lt;br /&gt;
  function onChangeMyMind( evt )  {&lt;br /&gt;
     if( this.checkLock() ) {&lt;br /&gt;
        // Do the action&lt;br /&gt;
     }&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
== Notifications ==&lt;br /&gt;
&lt;br /&gt;
When something happens on the server side, your game interface Javascript logic received a notification.&lt;br /&gt;
If you have not done so yet check what notification are in [[Main_game_logic:_yourgamename.game.php#Notifications]]&lt;br /&gt;
&lt;br /&gt;
Here&#039;s how you can handle these notifications on the client side.&lt;br /&gt;
&lt;br /&gt;
=== Subscribe to notifications ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;dojo.subscribe(notif_type: string, callback_obj: Object, handler: string|handler)&#039;&#039;&#039;&lt;br /&gt;
* notif_type - notification type/name send by php server&lt;br /&gt;
* callback_obj - usually this&lt;br /&gt;
* handler - if string method of callback_obj with name name is called, when notification is called, with notification object as parameter (see below)&lt;br /&gt;
&lt;br /&gt;
Your Javascript &amp;quot;setupNotifications&amp;quot; method is the place where you can subscribe to notifications from your PHP code.&lt;br /&gt;
&lt;br /&gt;
Here&#039;s how you associate one of your Javascript method to a notification &amp;quot;playDisc&amp;quot; (from Reversi example):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
   setupNotifications: function() {&lt;br /&gt;
      ...&lt;br /&gt;
      dojo.subscribe(&#039;playDisc&#039;, this, &amp;quot;notif_playDisc&amp;quot;);&lt;br /&gt;
   },&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note: the &amp;quot;playDisc&amp;quot; corresponds to the name of the notification you define it in your PHP code, in your &amp;quot;notifyAllPlayers&amp;quot; or &amp;quot;notifyPlayer&amp;quot; method.&lt;br /&gt;
&lt;br /&gt;
Then, you have to define your &amp;quot;notif_playDisc&amp;quot; method:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
   notif_playDisc: function(notif) {&lt;br /&gt;
     // Remove current possible moves (makes the board more clear)&lt;br /&gt;
     dojo.query( &#039;.possibleMove&#039; ).removeClass( &#039;possibleMove&#039; );          &lt;br /&gt;
     this.addDiscOnBoard( notif.args.x, notif.args.y, notif.args.player_id );&lt;br /&gt;
   },&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In a notification handler like our &amp;quot;notif_playDisc&amp;quot; method, you can access all notifications arguments with &amp;quot;notif.args&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&lt;br /&gt;
PHP&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    $this-&amp;gt;notifyAllPlayers( &amp;quot;apples&amp;quot;, clienttranslate(&#039;player takes ${count} apples&#039;), [ &amp;quot;count&amp;quot; =&amp;gt; 3 ] );&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
JavaScript&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    setupNotifications: function() {&lt;br /&gt;
       dojo.subscribe( &#039;apples&#039;, this, &#039;notif_apples&#039; );&lt;br /&gt;
    },&lt;br /&gt;
&lt;br /&gt;
    notif_apples: function(notif) {&lt;br /&gt;
      //You can access the &amp;quot;count&amp;quot; like this:&lt;br /&gt;
       alert(&amp;quot;count = &amp;quot; + notif.args.count);&lt;br /&gt;
    }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== The notification Object received by client ===&lt;br /&gt;
&lt;br /&gt;
When sending a notification on your PHP, the client side will receive an Object with the following attributes:&lt;br /&gt;
&lt;br /&gt;
* type - type of the notification (as passed by php function)&lt;br /&gt;
* log - the log string passed from php notification&lt;br /&gt;
* args - This is the arguments that you passed on your notification method on php&lt;br /&gt;
* bIsTableMsg - is true when you use [[Main_game_logic:_yourgamename.game.php#NotifyAllPlayers|NotifyAllPlayers]] method (false otherwise)&lt;br /&gt;
* channelorig - information about table ID (formatted as : &amp;quot;/table/t[TABLE_NUMBER]&amp;quot;)&lt;br /&gt;
* gamenameorig - name of the game&lt;br /&gt;
* move_id - ID of the move associated with the notification&lt;br /&gt;
* table_id - ID of the table (comes as string)&lt;br /&gt;
* time - UNIX GMT timestamp&lt;br /&gt;
* uid - unique identifier of the notification&lt;br /&gt;
* h - unknown&lt;br /&gt;
&lt;br /&gt;
&#039;&#039; Note that those information were inferred from observation on console log. If an Admin can confirm/correct (and remove this line), you&#039;re welcome :)&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
=== Ignoring notifications ===&lt;br /&gt;
&lt;br /&gt;
Sometimes you need to ignore some notification on client side. You don&#039;t want them to be shown in game log and you don&#039;t want them to be handled.&lt;br /&gt;
&lt;br /&gt;
The most common use case is when a player gets private information. They will receive a specific notification (such as &amp;quot;You received Ace of Heart&amp;quot;), while other players would receive more generic notification (&amp;quot;Player received a card&amp;quot;).&lt;br /&gt;
&lt;br /&gt;
In X.game.php&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        $this-&amp;gt;notifyAllPlayers(&amp;quot;dealCard&amp;quot;, clienttranslate(&#039;${player_name} received a card&#039;), [&lt;br /&gt;
            &#039;player_id&#039; =&amp;gt; $playerId,&lt;br /&gt;
            &#039;player_name&#039; =&amp;gt; $this-&amp;gt;getActivePlayerName()&lt;br /&gt;
        ]);&lt;br /&gt;
&lt;br /&gt;
        $this-&amp;gt;notifyPlayer($playerId, &amp;quot;dealCardPrivate&amp;quot;, clienttranslate(&#039;You received ${cardName}&#039;), [&lt;br /&gt;
            &amp;quot;type&amp;quot; =&amp;gt; $card[&amp;quot;type&amp;quot;],&lt;br /&gt;
            &amp;quot;cardName&amp;quot; =&amp;gt; $this-&amp;gt;getCardName($card[&amp;quot;type&amp;quot;])&lt;br /&gt;
        ]);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The problem with this approach is that the active player will receive two notifications:&lt;br /&gt;
* Player1 received a card&lt;br /&gt;
* You received Ace of Hearts&lt;br /&gt;
&lt;br /&gt;
Hence, notification ignoring.&lt;br /&gt;
&lt;br /&gt;
NOTE: You can think that it would be possible to send such notification to all players except active just by using notifyPlayer and it seems to work. The problem however is that table spectators would miss such notification and their user interface (and game log) wouldn&#039;t be updated. Since there is no way to send notification just to spectators, ignoring the notification (or &amp;quot;filtering&amp;quot;) is the only reasonable solution.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;setIgnoreNotificationCheck(notif_type: string, predicate: ((notif: Notif)=&amp;gt;boolean))&#039;&#039;&#039;&lt;br /&gt;
This method will set a check whether any of notifications of specific type should be ignored.&lt;br /&gt;
&lt;br /&gt;
The parameters are:&lt;br /&gt;
* notif_type: type of the notification &lt;br /&gt;
* predicate (notif =&amp;gt; boolean): a function that will receive notif object and will return true if this specific notification should be ignored&lt;br /&gt;
&lt;br /&gt;
Before dispatching any notification of this type, the framework will call predicate to check whether notification should be ignored, if it return true - the notification will be dispatched, i.e. logged or handled.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    this.notifqueue.setIgnoreNotificationCheck( &#039;dealCard&#039;, (notif) =&amp;gt; (notif.args.player_id == this.player_id) );&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
IMPORTANT: Remember that this notification is ignored on the client side, but was still received by the client. Therefore it shouldn&#039;t contain any private information as cheaters can get it. In other words this is not a way to hide information.&lt;br /&gt;
&lt;br /&gt;
IMPORTANT: When a game is reloaded with F5 or when opening a turn based game, old notifications are replayed as history notification. They are used just to update the game log and are stripped of all arguments except player_id, i18n and any argument present in message. If you use and other argument in your predicate you should &#039;&#039;&#039;preserve&#039;&#039;&#039; it as explained [[Main_game_logic:_yourgamename.game.php#Notify_players|here]].&lt;br /&gt;
&lt;br /&gt;
=== Synchronous notifications ===&lt;br /&gt;
&lt;br /&gt;
When several notifications are received by your game interface, these notifications are processed immediately, one after the other, in the same exact order they have been generated in your PHP game logic.&lt;br /&gt;
&lt;br /&gt;
However, sometimes, you need to give some time to the players to figure out what happened on the game before jumping to the next notification. Indeed, in many games, there are a lot of automatic actions, and the computer is going to resolve all these actions very fast if you don&#039;t tell it not to do so.&lt;br /&gt;
&lt;br /&gt;
As an example, for Reversi, when someone is playing a disc, we want to wait 500 milliseconds before doing anything else in order the opponent player can figure out what move has been played.&lt;br /&gt;
&lt;br /&gt;
Here&#039;s how we do this, right after our subscription:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    dojo.subscribe( &#039;playDisc&#039;, this, &amp;quot;notif_playDisc&amp;quot; );&lt;br /&gt;
    this.notifqueue.setSynchronous( &#039;playDisc&#039;, 500 );   // Wait 500 milliseconds after executing the playDisc handler&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
-----&lt;br /&gt;
&lt;br /&gt;
It is also possible to control the delay timing dynamically (e.g., using notification args). As an example, maybe your notification &#039;cardPlayed&#039; should pause for a different amount of time depending on the number or type of cards played.&lt;br /&gt;
&lt;br /&gt;
For this case, use &#039;&#039;&#039;setSynchronous&#039;&#039;&#039; without specifying the duration and use &#039;&#039;&#039;setSynchronousDuration&#039;&#039;&#039; within the notification callback.&lt;br /&gt;
&lt;br /&gt;
* NOTE: If you forget to invoke &#039;&#039;&#039;setSynchronousDuration&#039;&#039;&#039;, the game will remain paused forever!&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
setupNotifications: function () {&lt;br /&gt;
    dojo.subscribe( &#039;cardPlayed&#039;, this, &#039;notif_cardPlayed&#039; );&lt;br /&gt;
    this.notifqueue.setSynchronous( &#039;cardPlayed&#039; ); // wait time is dynamic&lt;br /&gt;
    ...&lt;br /&gt;
},&lt;br /&gt;
&lt;br /&gt;
notif_cardPlayed: function (notif) {&lt;br /&gt;
    // MUST call setSynchronousDuration&lt;br /&gt;
&lt;br /&gt;
    // Example 1: From notification args (PHP)&lt;br /&gt;
    this.notifqueue.setSynchronousDuration(notif.args.duration);&lt;br /&gt;
    ...&lt;br /&gt;
&lt;br /&gt;
    // Or, example 2: Match the duration to a Dojo animation&lt;br /&gt;
    var anim = dojo.fx.combine([&lt;br /&gt;
        ...&lt;br /&gt;
    ]);&lt;br /&gt;
    anim.play();&lt;br /&gt;
    this.notifqueue.setSynchronousDuration(anim.duration);&lt;br /&gt;
},&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You can also manually call this.notifqueue.setSynchronousDuration(0) once client operations are finished, but be careful that even fast replay still has a path to call it.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;WARNING: combining synchronous and ignored notifications&#039;&#039;&#039;&lt;br /&gt;
You must be careful when combining dynamic synchronous durations (as described above) with ignored notifications. If you have a conditionally ignored notification like this (see below section):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;this.notifqueue.setIgnoreNotificationCheck( &#039;myNotif&#039;, (notif) =&amp;gt; (notif.args.player_id == this.player_id) /* or any other condition */ )&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
then you CANNOT do&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;this.notifqueue.setSynchronous(&#039;myNotif&#039;);&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
as, when the ignored check passes, the notification handler, in which `this.notifqueue.setSychronousDuration` is called, is never called and so the duration is never set and interface locking results.&lt;br /&gt;
&lt;br /&gt;
The workaround is to set a &amp;quot;dummy&amp;quot; time:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;this.notifqueue.setSynchronous(&#039;myNotif&#039;, 5000);&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
whose value is irrelevant but must be large enough to cover the time before the notification handler is called. The large value never actually comes into play because the notification is either ignored, or the synchronous duration is reset to a sensible value inside the handler.&lt;br /&gt;
&lt;br /&gt;
=== Pre-defined notification types ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;tableWindow&#039;&#039;&#039; - This defines notification to display [[Game_interface_logic:_yourgamename.js#Scoring_dialogs|Scoring Dialogs]], see below.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;message&#039;&#039;&#039; - This defines notification that shows on players log and have no other effect (technically any unhandled notification will do the same but its recommended to use this keyword for consistency)&lt;br /&gt;
&lt;br /&gt;
   // You can call this on php side without doing anything on client side&lt;br /&gt;
    self::notifyAllPlayers( &#039;message&#039;, clienttranslate(&#039;hello&#039;), [] );&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;simplePause&#039;&#039;&#039; - This notification will just delay other notifications, maybe useful if you know you need some extra time for animation or something. Requires a time parameter.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    self::notifyAllPlayers( &#039;simplePause&#039;, &#039;&#039;, [ &#039;time&#039; =&amp;gt; 500] ); // time is in milliseconds&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note: the following types are RESERVED by framework, do not use:&lt;br /&gt;
&lt;br /&gt;
gameStateChange gameStateChangePrivateArg gameStateMultipleActiveUpdate newActivePlayer playerstatus yourturnack clockalert tableInfosChanged playerEliminated tableDecision  archivewaitingdelay end_archivewaitingdelay replaywaitingdelay end_replaywaitingdelay replayinitialwaitingdelay end_replayinitialwaitingdelay aiPlayerWaitingDelay replay_has_ended updateSpectatorList  wouldlikethink updateReflexionTime undoRestorePoint resetInterfaceWithAllDatas zombieModeFail zombieModeFailWarning aiError skipTurnOfPlayer zombieBack allPlayersAreZombie gameResultNeutralized playerConcedeGame showTutorial showCursor showCursorClick skipTurnOfPlayerWarning  banFromTable resultsAvailable switchToTurnbased newPrivateState infomsg&lt;br /&gt;
&lt;br /&gt;
== Tooltips ==&lt;br /&gt;
&lt;br /&gt;
=== Adding static tooltips ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.addTooltip(nodeId: string, helpStringTranslated: string, actionStringTranslated: string, delay?: number): void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Add a simple text tooltip to the DOM node.&lt;br /&gt;
&lt;br /&gt;
Specify &#039;helpStringTranslated&#039; to display some information about &amp;quot;what is this game element?&amp;quot;.&lt;br /&gt;
Specify &#039;actionStringTranslated&#039; to display some information about &amp;quot;what happens when I click on this element?&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
You must specify both of the strings. You can only use one and specify an empty string (&#039;&#039;) for the other one.&lt;br /&gt;
&lt;br /&gt;
When you pass text directly function _() must be used for the text to be marked for translation! Except for empty string.&lt;br /&gt;
&lt;br /&gt;
Parameter &amp;quot;delay&amp;quot; is optional. It is primarily used to specify a zero delay for some game element when the tooltip gives really important information for the game - but remember: no essential information must be placed in tooltips as they won&#039;t be displayed in some browsers (see [[BGA_Studio_Guidelines|Guidelines]]).&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
   this.addTooltip( &#039;cardcount&#039;, _(&#039;Number of cards in hand&#039;), &#039;&#039; );&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note: this generates static tooltip and attaches to existing dom element, if you need to generate tooltip more dynamically you have to call that method every time information about object is updated or use completely different tehnique, see dynamic tooltips below.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.addTooltipHtml(nodeId: string, html: string, delay?: number): void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Add an HTML tooltip to the DOM node (for more elaborate content such as presenting a bigger version of a card).&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.addTooltipToClass(cssClass: string, helpStringTranslated: string, actionStringTranslated: string, delay?: number ): void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Add a simple text tooltip to all the DOM nodes set with this cssClass. See more details above for this.addTooltip.&lt;br /&gt;
     this.addTooltipToClass( &#039;meeple&#039;, _(&#039;This is A Meeple&#039;), _(&#039;Click to tickle&#039;) );&lt;br /&gt;
&lt;br /&gt;
IMPORTANT: all concerned nodes must exist and have IDs to get tooltips.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.addTooltipHtmlToClass(cssClass: string, html: string, delay?: number): void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Add an HTML tooltip to to all the DOM nodes set with this cssClass (for more elaborate content such as presenting a bigger version of a card).&lt;br /&gt;
&lt;br /&gt;
IMPORTANT: all concerned nodes must exist and have IDs to get tooltips.&lt;br /&gt;
&lt;br /&gt;
=== Removing static tooltips ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.removeTooltip(nodeId: string): void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Remove a tooltip from the DOM node with given id.&lt;br /&gt;
&lt;br /&gt;
=== Advanced tooltips ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;force tooltip to open&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
If you want to force tooltip to open in reaction to some other action, i.e. click you can do this&lt;br /&gt;
&lt;br /&gt;
   this.tooltips[id].open(id)&lt;br /&gt;
&lt;br /&gt;
where id is the id of the tooltip node where tooltip was installed.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;dynamic tooltips&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
See [[BGA_Studio_Cookbook#Dynamic_tooltips]]&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;tooltips on mobile&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Tooltips is very unreliable on mobile, it is recommended to implement some other method to obtaining same information,&lt;br /&gt;
such as simple click handler in dedicated &amp;quot;Help&amp;quot; mode or provide dedicated clickable areas such as corner of card.&lt;br /&gt;
&lt;br /&gt;
== Warning messages ==&lt;br /&gt;
&lt;br /&gt;
Sometimes, there is something important that is happening in the game and you have to make sure all players get the message. Most of the time, the evolution of the game situation or the game log is enough, but sometimes you need something more visible.&lt;br /&gt;
&lt;br /&gt;
Ex: someone fulfills one of the end of the game conditions, so this is the last turn.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.showMessage(msg: string, type: string): void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
showMessage shows a message in a big rectangular area on the top of the screen of the current player, and it dissapears after few seconds (also it will be in the log in some cases).&lt;br /&gt;
&lt;br /&gt;
* &amp;quot;msg&amp;quot; is the string to display. It should be translated.&lt;br /&gt;
* &amp;quot;type&amp;quot; can be set to &amp;quot;info&amp;quot;, &amp;quot;error&amp;quot;, &amp;quot;only_to_log&amp;quot; or custom string. If set to &amp;quot;info&amp;quot;, the message will be an informative message on a white background. If set to &amp;quot;error&amp;quot;, the message will be an error message on a red background and it will be added to log. If set to &amp;quot;only_to_log&amp;quot;, the message will be added to the game log but will not popup at the top of the screen.&lt;br /&gt;
If set to custom string, it will be transparent, to use custom type define &amp;quot;head_xxx&amp;quot; in css, where xxx is the type. For example if you want yellow warning, use &amp;quot;warning&amp;quot; as type and add this to css:&lt;br /&gt;
 .head_warning {&lt;br /&gt;
    background-color: #e6c66e;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
Important: the normal way to inform players about the progression of the game is the game log. The &amp;quot;showMessage&amp;quot; is intrusive and should not be used often.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    notif_messageinfo: function(notif) {&lt;br /&gt;
	if (!g_archive_mode) {&lt;br /&gt;
        	var message = this.format_string_recursive(notif.log, notif.args);&lt;br /&gt;
		this.showMessage(_(&#039;Announcement:&#039;) + &amp;quot; &amp;quot; + message, &#039;info&#039;);		&lt;br /&gt;
         }&lt;br /&gt;
    },&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Show message could be used on the client side to prevent user wrong moves before it is send to server.&lt;br /&gt;
Example from &#039;battleship&#039;:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
onGrid: function(event) {&lt;br /&gt;
     if (checkIfPlayerTriesToFireOnThemselves(event)) {&lt;br /&gt;
        this.showMessage(_(&#039;This is your own board silly!&#039;), &#039;error&#039;);&lt;br /&gt;
        return;&lt;br /&gt;
     }&lt;br /&gt;
     ...&lt;br /&gt;
},&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.showMoveUnauthorized(): void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Shows predefined user error that move is unauthorized now&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
onPet: function(event) {&lt;br /&gt;
     if (checkPet(event)==false) {&lt;br /&gt;
        this.showMoveUnauthorized();&lt;br /&gt;
        return;&lt;br /&gt;
     }&lt;br /&gt;
     ...&lt;br /&gt;
},&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Dialogs ==&lt;br /&gt;
&lt;br /&gt;
=== Confirmation dialog ===&lt;br /&gt;
&lt;br /&gt;
When an important action with a lot of consequences is triggered by the player, you may want to propose a confirmation dialog.&lt;br /&gt;
&lt;br /&gt;
CAREFUL: the general guideline of BGA is to AVOID the use of confirmation dialogs. Confirmation dialogs slow down the game and bother players. The players know that they have to pay attention to each move when they are playing online.&lt;br /&gt;
&lt;br /&gt;
The situations where you should use a confirmation dialog are the following:&lt;br /&gt;
* It must not happen very often during a game.&lt;br /&gt;
* It must be linked to an action that can really &amp;quot;kill a game&amp;quot; if the player does not pay attention.&lt;br /&gt;
* It must be something that can be done by mistake (ex: a link on the action status bar).&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.confirmationDialog(message: string, yesHandler: (param: any) =&amp;gt; void, noHandler?: (param: any) =&amp;gt; void, param?: any): void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
* message - message will be shown to user, use _() to translate&lt;br /&gt;
* yesHandler - non-optional handler to be called on yes&lt;br /&gt;
* noHandler - optional handler to called on no&lt;br /&gt;
* param - if specified, it will be passed to both handlers&lt;br /&gt;
NOTE: this is async function, it does not return anything and you should not do anything after, you must do everything in handlers&lt;br /&gt;
&lt;br /&gt;
How to display a confirmation dialog:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    this.confirmationDialog(_(&amp;quot;Are you sure you want to bake a pie?&amp;quot;), () =&amp;gt; {&lt;br /&gt;
      this.bakeThePie();&lt;br /&gt;
    });&lt;br /&gt;
    return; // nothing should be called or done after calling this, all action must be done in the handler&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
With param and both handlers&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    this.confirmationDialog(_(&amp;quot;Are you sure you want to bake a pie?&amp;quot;), &lt;br /&gt;
           (ingredient) =&amp;gt; this.bakeThePie(ingredient), &lt;br /&gt;
           (ingredient) =&amp;gt; console.log(`cancelled baking of ${ingredient}`), &lt;br /&gt;
           &#039;apple&#039;);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Multiple choice dialog ===&lt;br /&gt;
&lt;br /&gt;
You can use this dialog to give user a choice with small amount of options&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.multipleChoiceDialog(message: string, choices: string[], callback: (choice: number) =&amp;gt; void): void&#039;&#039;&#039;&lt;br /&gt;
* message - message will be shown to user, use _() to translate&lt;br /&gt;
* choices - array of choices&lt;br /&gt;
* callback - non-optional handler to be called on choice made, the choice parameter is the INDEX of the choice from the array of choices&lt;br /&gt;
&lt;br /&gt;
NOTE: this is async function, it does not return anything and you should not do anything after, you must do everything in handlers&lt;br /&gt;
NOTE: there is no cancel handler, so make sure you gave user a choice to get out of it&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    const keys = [&amp;quot;0&amp;quot;, &amp;quot;1&amp;quot;, &amp;quot;5&amp;quot;, &amp;quot;10&amp;quot;];&lt;br /&gt;
    this.multipleChoiceDialog(_(&amp;quot;How many bugs to fix?&amp;quot;), keys, (choice) =&amp;gt; {&lt;br /&gt;
      if (choice==0) return; // cancel operation, do not call server action&lt;br /&gt;
      var bugchoice = keys[choice]; // choice will be 0,1,2,3 here&lt;br /&gt;
      this.bgaPerformAction(&amp;quot;fixBugs&amp;quot;, { number: bugchoice });&lt;br /&gt;
    });&lt;br /&gt;
    return; // must return here&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Generic Dialogs ===&lt;br /&gt;
&lt;br /&gt;
As a general rule, you shouldn&#039;t use dialogs windows.&lt;br /&gt;
&lt;br /&gt;
BGA guidelines specify that all game elements should be displayed on the main screen. Players can eventually scroll down to see game elements they don&#039;t need to see anytime, and you may eventually create anchors to move between game area section. Of course dialogs windows are very practical, but the thing is: all players know how to scroll down, and not all players know how to show up your dialog window. In addition, when the dialog shows up, players can&#039;t access the other game components.&lt;br /&gt;
&lt;br /&gt;
Sometimes although, you need to display a dialog window. Here is how you do this:&lt;br /&gt;
&lt;br /&gt;
  // Create the new dialog over the play zone. You should store the handler in a member variable to access it later&lt;br /&gt;
  this.myDlg = new ebg.popindialog();&lt;br /&gt;
  this.myDlg.create( &#039;myDialogUniqueId&#039; );&lt;br /&gt;
  this.myDlg.setTitle( _(&amp;quot;my dialog title to translate&amp;quot;) );&lt;br /&gt;
  this.myDlg.setMaxWidth( 500 ); // Optional&lt;br /&gt;
  &lt;br /&gt;
  // Create the HTML of my dialog. &lt;br /&gt;
  // The best practice here is to use [[Game_layout:_view_and_template:_yourgamename.view.php_and_yourgamename_yourgamename.tpl#Javascript_templates|Javascript templates]]&lt;br /&gt;
  var html = this.format_block( &#039;jstpl_myDialogTemplate&#039;, { &lt;br /&gt;
                arg1: myArg1,&lt;br /&gt;
                arg2: myArg2,&lt;br /&gt;
                ...&lt;br /&gt;
            } );  &lt;br /&gt;
  &lt;br /&gt;
  // Show the dialog&lt;br /&gt;
  this.myDlg.setContent( html ); // Must be set before calling show() so that the size of the content is defined before positioning the dialog&lt;br /&gt;
  this.myDlg.show();&lt;br /&gt;
  &lt;br /&gt;
  // Now that the dialog has been displayed, you can connect your method to some dialog elements&lt;br /&gt;
  // Example, if you have an &amp;quot;OK&amp;quot; button in the HTML of your dialog:&lt;br /&gt;
  dojo.connect($(&#039;my_ok_button&#039;), &#039;onclick&#039;, this, (event) =&amp;gt; {&lt;br /&gt;
                event.preventDefault();&lt;br /&gt;
                this.myDlg.destroy();&lt;br /&gt;
            });&lt;br /&gt;
&lt;br /&gt;
If necessary, you can remove the default top right corner &#039;close&#039; icon, or replace the function called when it is clicked:&lt;br /&gt;
  // Removes the default close icon&lt;br /&gt;
  this.myDlg.hideCloseIcon();&lt;br /&gt;
&lt;br /&gt;
  // Replace the function call when it&#039;s clicked&lt;br /&gt;
  this.myDlg.replaceCloseCallback((event) =&amp;gt; { ... });&lt;br /&gt;
&lt;br /&gt;
=== Scoring dialogs ===&lt;br /&gt;
&lt;br /&gt;
Sometimes at the end of a round you want to display a big table that details the points wins in each section of the game.&lt;br /&gt;
&lt;br /&gt;
Example: in Hearts game, we display at the end of each round the number of &amp;quot;heart&amp;quot; cards collected by each player, the player who collected the Queen of Spades, and the total number of points loose by each player.&lt;br /&gt;
&lt;br /&gt;
Scoring dialogs are managed entirely on &#039;&#039;&#039;PHP side&#039;&#039;&#039;, but they are described here as their effects are visible only on client side.&lt;br /&gt;
&lt;br /&gt;
Displaying a scoring dialog is quite simple and is using a special notification type: &amp;quot;tableWindow&amp;quot;:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  // on PHP side:&lt;br /&gt;
  $this-&amp;gt;notifyAllPlayers( &amp;quot;tableWindow&amp;quot;, &#039;&#039;, array(&lt;br /&gt;
            &amp;quot;id&amp;quot; =&amp;gt; &#039;finalScoring&#039;,&lt;br /&gt;
            &amp;quot;title&amp;quot; =&amp;gt; clienttranslate(&amp;quot;Title of the scoring dialog&amp;quot;),&lt;br /&gt;
            &amp;quot;table&amp;quot; =&amp;gt; $table&lt;br /&gt;
        )); &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The &amp;quot;table&amp;quot; argument is a 2 dimensional PHP array that describes the table you want to display, line by line and column by column.&lt;br /&gt;
&lt;br /&gt;
Example: display an 3x3 array of strings&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
   $table = [&lt;br /&gt;
      [ &amp;quot;one&amp;quot;, &amp;quot;two&amp;quot;, &amp;quot;three&amp;quot; ],    // This is my first line&lt;br /&gt;
      [ &amp;quot;four&amp;quot;, &amp;quot;five&amp;quot;, &amp;quot;six&amp;quot; ],    // This is my second line&lt;br /&gt;
      [ &amp;quot;seven&amp;quot;, &amp;quot;height&amp;quot;, &amp;quot;nine&amp;quot; ]    // This is my third line&lt;br /&gt;
   ];&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
As you can see above, in each &amp;quot;cell&amp;quot; of your array you can display a simple string value. But you can also display a complex value with a template and associated arguments like this:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
   $table = [&lt;br /&gt;
      [ &amp;quot;one&amp;quot;, &amp;quot;two&amp;quot;, [ &amp;quot;str&amp;quot; =&amp;gt; clienttranslate(&amp;quot;a string with an ${argument}&amp;quot;), &amp;quot;args&amp;quot; =&amp;gt; [ &#039;argument&#039; =&amp;gt; &#039;argument_value&#039; ] ] ],&lt;br /&gt;
      [ &amp;quot;four&amp;quot;, &amp;quot;five&amp;quot;, &amp;quot;six&amp;quot; ], &lt;br /&gt;
      [ &amp;quot;seven&amp;quot;, &amp;quot;height&amp;quot;, &amp;quot;nine&amp;quot; ]&lt;br /&gt;
   ];&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This is especially useful when you want to display player names with colors. Example from &amp;quot;Hearts&amp;quot;:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        $firstRow = [ &#039;&#039; ];&lt;br /&gt;
        foreach( $players as $player_id =&amp;gt; $player )    {&lt;br /&gt;
            $cell = [ &#039;str&#039; =&amp;gt; &#039;${player_name}&#039;,&lt;br /&gt;
                      &#039;args&#039; =&amp;gt; [ &#039;player_name&#039; =&amp;gt; $player[&#039;player_name&#039;] ],&lt;br /&gt;
                      &#039;type&#039; =&amp;gt; &#039;header&#039;&lt;br /&gt;
                    ];&lt;br /&gt;
            $firstRow[] = $cell;&lt;br /&gt;
        }&lt;br /&gt;
        $table[] = $firstRow;&lt;br /&gt;
        ...&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You can also use three extra attributes in the parameter array for the notification:&lt;br /&gt;
* &#039;&#039;&#039;header&#039;&#039;&#039;: the content for this parameter displays before the table (also, the html will be parsed and player names will be colored according to the current game colors). &lt;br /&gt;
* &#039;&#039;&#039;footer&#039;&#039;&#039;: the content for this parameter displays after the table (no parsing for coloring the player names)&lt;br /&gt;
* &#039;&#039;&#039;closing&#039;&#039;&#039;: if this parameter is used, a button will be displayed with this label at the bottom of the popup and will allow players to close it (more easily than by clicking the top right &#039;cross&#039; icon).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
   $this-&amp;gt;notifyAllPlayers( &amp;quot;tableWindow&amp;quot;, &#039;&#039;, [&lt;br /&gt;
            &amp;quot;id&amp;quot; =&amp;gt; &#039;finalScoring&#039;,&lt;br /&gt;
            &amp;quot;title&amp;quot; =&amp;gt; clienttranslate(&amp;quot;Title of the scoring dialog&amp;quot;),&lt;br /&gt;
            &amp;quot;table&amp;quot; =&amp;gt; $table,&lt;br /&gt;
            &amp;quot;header&amp;quot; =&amp;gt; [&#039;str&#039; =&amp;gt; clienttranslate(&#039;Table header with parameter ${number}&#039;),&lt;br /&gt;
                                 &#039;args&#039; =&amp;gt; [ &#039;number&#039; =&amp;gt; 3 ],&lt;br /&gt;
                               ],&lt;br /&gt;
            &amp;quot;footer&amp;quot; =&amp;gt; &#039;&amp;lt;div class=&amp;quot;myfoot&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&#039;,&lt;br /&gt;
            &amp;quot;closing&amp;quot; =&amp;gt; clienttranslate( &amp;quot;Closing button label&amp;quot; )&lt;br /&gt;
        ] ); &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note: currently id is not used - so you cannot access resulting div by id on js side&lt;br /&gt;
Note: any traslatable stirng have to be wrapped by clienttranslate() on top level OR it has to be recursive template. &lt;br /&gt;
&lt;br /&gt;
DO NOT DO THIS: &lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
   &amp;quot;footer&amp;quot; =&amp;gt; &#039;&amp;lt;div&amp;gt;&#039;.clienttranslate( &amp;quot;The end&amp;quot; ).&#039;&amp;lt;/div&amp;gt;&#039;, // this will not work for translations!!!&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Scoring animated display ===&lt;br /&gt;
&lt;br /&gt;
Sometimes, you may want to display a score value over an element to make the scoring easier to follow for the players (Terra Mystica final scoring for example).&lt;br /&gt;
You can do it with:&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.displayScoring(anchor_id: string, color: string, score: number | string, duration?: number, offset_x?: number, offset_y?: number): void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;anchor_id&#039;&#039;&#039;: ID of the html element to place the animated score onto (without the &#039;#&#039;) &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;color&#039;&#039;&#039;: hexadecimal RGB representation of the color (should be the color of the scoring player), but without a leading &#039;#&#039;.  For instance, &#039;ff0000&#039; for red.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;score&#039;&#039;&#039;: numeric score to display, prefixed by a &#039;+&#039; or &#039;-&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;duration&#039;&#039;&#039;: animation duration in milliseconds (optional, default is 1000)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;offset_x&#039;&#039;&#039; and &#039;&#039;&#039;offset_y&#039;&#039;&#039;: if both offset_x and offset_y are defined and not null, apply the following offset (in pixels) to the scoring animation. &lt;br /&gt;
Note that the score is centered in the anchor, so the offsets might have to be negative if you calculate the position.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Note: if you want to display successively each score, you can use &#039;&#039;this.notifqueue.setSynchronous()&#039;&#039; function.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    setupNotifications: function()   {&lt;br /&gt;
           dojo.subscribe( &#039;displayScoring&#039;, this, &amp;quot;notif_displayScoring&amp;quot; );&lt;br /&gt;
           ...&lt;br /&gt;
    }&lt;br /&gt;
...&lt;br /&gt;
&lt;br /&gt;
    notif_displayScoring: function(notif) {&lt;br /&gt;
            const duration = notif.args.duration?notif.args.duration:1000;&lt;br /&gt;
            this.notifqueue.setSynchronous(&#039;displayScoring&#039;, duration );&lt;br /&gt;
	    this.displayScoring( notif.args.target, notif.args.color, notif.args.score, duration);&lt;br /&gt;
    },&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Speech bubble ===&lt;br /&gt;
&lt;br /&gt;
For better interactivity in some games (Love Letter for example), you may use comic book style speech bubbles to express the players voices.&lt;br /&gt;
This is done with showBubble:&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.showBubble(anchor_id: string, text: string, delay?: number, duration?: number, custom_class?: string): void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
* anchor_id - where to attach the bubble&lt;br /&gt;
* text - what to put in bubble, can be html&lt;br /&gt;
* delay - delay in milliseconds (optional, default 0)&lt;br /&gt;
* duration -  duration of animation in milliseconds (optional, default 3000)&lt;br /&gt;
* custom_class - extra class to add to bubble (optional), if you need to override the default bubble style&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
   this.showBubble(&#039;meeple_2&#039;, _(&#039;Hello&#039;), 0, 1000, &#039;pink_bubble&#039;);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  notif_speechBubble(notif) {&lt;br /&gt;
    var html = this.format_string_recursive(notif.args.text, notif.args.args);&lt;br /&gt;
    this.showBubble(notif.args.target, html, notif.args.delay ?? 0, notif.args.duration ?? 1000);&lt;br /&gt;
  },&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Warning&#039;&#039;&#039;: if your bubble could overlap other active elements of the interface (buttons in particular), as it stays in place even after disappearing, you should use a custom class to give it the style &amp;quot;pointer-events: none;&amp;quot; in order to intercept click events.&lt;br /&gt;
&lt;br /&gt;
Note: If you want this visually, but want to take complete control over this bubble and its animation (for example to make it permanent) you can just use div with &#039;discussion_bubble&#039; class on it, and content of div is what will be shown.&lt;br /&gt;
&lt;br /&gt;
== Translations ==&lt;br /&gt;
&lt;br /&gt;
See [[Translations]]&lt;br /&gt;
&lt;br /&gt;
== Players panels ==&lt;br /&gt;
&lt;br /&gt;
=== Update players score ===&lt;br /&gt;
&lt;br /&gt;
The column player_score from the player table is automatically loaded into this.scoreCtrl and therefore into the stars location on the player board. This occurs sometime after the game setup() function. However this score must be updated as the game progresses using notifications.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Note: this.scoreCtrl[player_id] is object of class [[Counter]], you can use other counter API.&lt;br /&gt;
&lt;br /&gt;
Increase a player score (with a positive or negative number):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  this.scoreCtrl[ player_id ].incValue( score_delta );&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Set a player score to a specific value:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  this.scoreCtrl[ player_id ].setValue( new_score );&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Set a player score to a specific value with animation:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  this.scoreCtrl[ player_id ].toValue( new_score );&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Typical usage would be (that will process &#039;score&#039; notification):&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        setupNotifications : function() {&lt;br /&gt;
              ...&lt;br /&gt;
             dojo.subscribe(&#039;score&#039;, this, &amp;quot;notif_score&amp;quot;);&lt;br /&gt;
        },&lt;br /&gt;
        notif_score: function(notif) {&lt;br /&gt;
            this.scoreCtrl[notif.args.player_id].setValue(notif.args.player_score);&lt;br /&gt;
        },&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Adding stuff to player&#039;s panel ===&lt;br /&gt;
&lt;br /&gt;
At first, create a new &amp;quot;JS template&amp;quot; string in your template (tpl) file:&lt;br /&gt;
&lt;br /&gt;
(from Gomoku example)&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
var jstpl_player_board = &#039;\&amp;lt;div class=&amp;quot;cp_board&amp;quot;&amp;gt;\&lt;br /&gt;
    &amp;lt;div id=&amp;quot;stoneicon_p${id}&amp;quot; class=&amp;quot;gmk_stoneicon gmk_stoneicon_${color}&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&amp;lt;span id=&amp;quot;stonecount_p${id}&amp;quot;&amp;gt;0&amp;lt;/span&amp;gt;\&lt;br /&gt;
&amp;lt;/div&amp;gt;&#039;;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Then, you add this piece of code in your JS file to add this template to each player panel:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
            // Setting up player boards&lt;br /&gt;
            for( var player_id in gamedatas.players )&lt;br /&gt;
            {&lt;br /&gt;
                var player = gamedatas.players[player_id];&lt;br /&gt;
                         &lt;br /&gt;
                // Setting up players boards if needed&lt;br /&gt;
                var player_board_div = $(&#039;player_board_&#039;+player_id);&lt;br /&gt;
                dojo.place( this.format_block(&#039;jstpl_player_board&#039;, player ), player_board_div );&lt;br /&gt;
            }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
(Note: the code above is of course from your &amp;quot;setup&amp;quot; function in your Javascript).&lt;br /&gt;
&lt;br /&gt;
Very often, you have to distinguish current player and others players. In this case, you just have to create another JS template (ex: jstpl_otherplayer_board) and use it when &amp;quot;player_id&amp;quot; is different than &amp;quot;this.player_id&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Fixing Player Panel heights ===&lt;br /&gt;
&lt;br /&gt;
You may find that the player panels don&#039;t automatically resize when adding something to (or removing something from) a player panel while the display is in portrait mode (i.e. the player summary panels are at the top of the screen rather than down the right side).&lt;br /&gt;
&lt;br /&gt;
When this happens, call &amp;lt;pre&amp;gt;this.adaptPlayersPanels();&amp;lt;/pre&amp;gt; This recalculates the layout and also adjusts the position of the actionbar for you.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Player&#039;s panel disabling/enabling ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.disablePlayerPanel(player_id: number): void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Disable given player panel (the panel background become gray).&lt;br /&gt;
&lt;br /&gt;
Usually, this is used to signal that this played passes, or will be inactive during a while.&lt;br /&gt;
&lt;br /&gt;
Note that the only effect of this is visual. There are no consequences on the behaviour of the panel itself.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.enablePlayerPanel(player_id:number): void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Enable a player panel that has been disabled before.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.enableAllPlayerPanels(): void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Enable all player panels that has been disabled before.&lt;br /&gt;
&lt;br /&gt;
=== Player order ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.updatePlayerOrdering(): void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
This function makes sure that player order in player&#039;s panel matches this.gamedatas.playerorder and its normally called by framework.&lt;br /&gt;
You can call it yoursel if you change this.gamedatas.playerorder from notification.&lt;br /&gt;
Also you can override this function to change defaults  OR insert a non-player panel [[BGA_Studio_Cookbook#Inserting_non-player_panel]].&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Counters ===&lt;br /&gt;
Note: there is bga component called  &amp;quot;ebg/counter&amp;quot; this API is not using it, these methods&lt;br /&gt;
below declared right in core game. If you need animation for counters use ebg/counter&lt;br /&gt;
&lt;br /&gt;
To use this API just create a counter dom element like this (class does not really matter)&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 &amp;lt;div class=&amp;quot;counter&amp;quot; id=&amp;quot;bread&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
 &amp;lt;div class=&amp;quot;counter&amp;quot; id=&amp;quot;coin&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
The &amp;quot;bread&amp;quot; will the counter name.&lt;br /&gt;
&lt;br /&gt;
The php code should send all &amp;quot;counters&amp;quot; data from getAllDatas() method like this&lt;br /&gt;
&lt;br /&gt;
game.php&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  protected function getAllDatas() {&lt;br /&gt;
    // (the key must match counter_name)&lt;br /&gt;
    $result[&#039;counters&#039;]=[&lt;br /&gt;
        &#039;bread&#039; =&amp;gt; [ &lt;br /&gt;
         &#039;counter_name&#039; =&amp;gt; &#039;bread&#039;, &lt;br /&gt;
         &#039;counter_value&#039; =&amp;gt; 3&lt;br /&gt;
         ], &lt;br /&gt;
        &#039;coin&#039; =&amp;gt; [&lt;br /&gt;
          &#039;counter_name&#039; =&amp;gt; &#039;coin&#039;, &lt;br /&gt;
          &#039;counter_value&#039; =&amp;gt; 5&lt;br /&gt;
        ]&lt;br /&gt;
   ];&lt;br /&gt;
   return $result;&lt;br /&gt;
  }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;setCounter(counter_name: stirng, new_value: string | number): void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
updates the global this.gamedatas.counters and value of node $(counter_name)&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  notif_counter: function(notif) { &lt;br /&gt;
    this.setCounter(notif.args.counter_name, notif.args.counter_value);&lt;br /&gt;
  },&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;incCounter(counter_name: string, delta: number): void&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  notif_counter : function(notif) {&lt;br /&gt;
    this.incCounter(notif.args.counter_name, notif.args.inc);&lt;br /&gt;
  },&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;updateCounters(counters: object): void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Useful for updating game counters in the player panel (such as resources). &lt;br /&gt;
&#039;counters&#039; arg is map of counters (the key must match counter_name)&lt;br /&gt;
  {&lt;br /&gt;
    &#039;bread&#039;: { &lt;br /&gt;
         &#039;counter_name&#039; : &#039;bread&#039;, &lt;br /&gt;
         &#039;counter_value&#039; =&amp;gt; 3&lt;br /&gt;
    }, &lt;br /&gt;
    &#039;coin&#039;: { &lt;br /&gt;
         &#039;counter_name&#039; : &#039;coin&#039;, &lt;br /&gt;
         &#039;counter_value&#039; =&amp;gt; 5&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
All counters MUST be referenced in this.gamedatas.counters (means they should be send from php) and will be updated.&lt;br /&gt;
DOM objects referenced by &#039;counter_name&#039; will have their innerHTML updated with &#039;counter_value&#039;.&lt;br /&gt;
&lt;br /&gt;
Usually you call this from notification&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
                        notif_counter : function(notif) {&lt;br /&gt;
                            this.updateCounters(notif.args.counters);&lt;br /&gt;
                        },&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== BGA GUI components ==&lt;br /&gt;
&lt;br /&gt;
BGA framework provides some useful ready-to-use components for the game interface:&lt;br /&gt;
&lt;br /&gt;
[[Studio#BGA_Studio_game_components_reference]]&lt;br /&gt;
&lt;br /&gt;
Note that each time you are using an additional component, you must declare it at the top of your Javascript file in the list of modules used.&lt;br /&gt;
&lt;br /&gt;
Example if you are using &amp;quot;ebg.stock&amp;quot;:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
define([&lt;br /&gt;
    &amp;quot;dojo&amp;quot;,&amp;quot;dojo/_base/declare&amp;quot;,&lt;br /&gt;
    &amp;quot;ebg/core/gamegui&amp;quot;,&lt;br /&gt;
    &amp;quot;ebg/counter&amp;quot;,&lt;br /&gt;
    &amp;quot;ebg/stock&amp;quot;  /// &amp;lt;=== we are using ebg.stock module&lt;br /&gt;
],&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== BGA Buttons ==&lt;br /&gt;
&lt;br /&gt;
=== Basic Button ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.addActionButton(id: string, label: string, method: string | eventhandler, destination?: string, blinking?: boolean, color?: string): void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
You can use this method to add an action button in the main action status bar (or other places).&lt;br /&gt;
&lt;br /&gt;
Arguments:&lt;br /&gt;
* id: an element ID that should be unique in your HTML DOM document.&lt;br /&gt;
* label: the text of the button. Should be translatable (use _() function). Note: this can also be any html, such as &amp;quot;&amp;lt;div class=&#039;brick&#039;&amp;gt;&amp;lt;/div&amp;gt;&amp;quot;, see example below on how to make image action buttons.&lt;br /&gt;
* method: the name of your method that must be triggered when the player clicks on this button (can be name of the method on game class or handler).&lt;br /&gt;
* destination (optional): id of parent on where to add button, ONLY use in rare cases if location is not action bar. Use &#039;&#039;&#039;null&#039;&#039;&#039; as value if you need to specify other arguments.&lt;br /&gt;
* blinking (optional): if set to &#039;&#039;&#039;true&#039;&#039;&#039;, the button is going blink to catch player&#039;s attention. Please DO NOT abuse blinking button. If you need button to blink after some time passed add class &#039;blinking&#039; to the button later.&lt;br /&gt;
* color: could be &#039;&#039;&#039;blue&#039;&#039;&#039; (default), &#039;&#039;&#039;red&#039;&#039;&#039;,&#039;&#039;&#039;gray&#039;&#039;&#039; or &#039;&#039;&#039;none&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
You should only use this method in your &amp;quot;onUpdateActionButtons&amp;quot; method. Usually, you use it like this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        onUpdateActionButtons: function( stateName, args ) {                      &lt;br /&gt;
            if (this.isCurrentPlayerActive()) {            &lt;br /&gt;
                switch( stateName ) {&lt;br /&gt;
                case &#039;giveCards&#039;:&lt;br /&gt;
                    this.addActionButton( &#039;giveCards_button&#039;, _(&#039;Give selected cards&#039;), &#039;onGiveCards&#039; ); &lt;br /&gt;
                    this.addActionButton( &#039;pass_button&#039;, _(&#039;Pass&#039;), () =&amp;gt; this.bgaPerformAction(&#039;actPass&#039;) ); &lt;br /&gt;
                    break;&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        },   &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In the example above, we are adding a &amp;quot;Give selected cards&amp;quot; button in the case we are on game state &amp;quot;giveCards&amp;quot;. When player clicks on this button, it triggers our &amp;quot;onGiveCards&amp;quot; method.&lt;br /&gt;
&lt;br /&gt;
Example using blinking red button:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    this.addActionButton( &#039;button_confirm&#039;, _(&#039;Confirm?&#039;), &#039;onConfirm&#039;, null, true, &#039;red&#039;); &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If you want to call the handler with arguments, you can use arrow functions, like this:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
     this.addActionButton( &#039;commit_button&#039;, _(&#039;Confirm&#039;), () =&amp;gt; this.onConfirm(this.selectedCardId), null, false, &#039;red&#039;); &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Image Button ===&lt;br /&gt;
&lt;br /&gt;
You can use the same method, but add extra class to a button to disable the padding and style it, i.e.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
this.addActionButton( &#039;button_brick&#039;, &#039;&amp;lt;div class=&amp;quot;brick&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&#039;, ()=&amp;gt;{... on brick ...}, null, null, &#039;gray&#039;); &lt;br /&gt;
dojo.addClass(&#039;button_brick&#039;,&#039;bgaimagebutton&#039;);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
where&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
.bgaimagebutton {&lt;br /&gt;
  padding: 0px 12px;&lt;br /&gt;
  min-height: 28px;&lt;br /&gt;
  border: none;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If you use this a lot, you can define a helper function, i.e.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
 * This method can be used instead of addActionButton, to add a button which is an image (i.e. resource). Can be useful when player&lt;br /&gt;
 * need to make a choice of resources or tokens.&lt;br /&gt;
 */&lt;br /&gt;
addImageActionButton: function(id, div, handler, bcolor, tooltip) {&lt;br /&gt;
	if (typeof bcolor == &amp;quot;undefined&amp;quot;) {&lt;br /&gt;
		bcolor = &amp;quot;gray&amp;quot;;&lt;br /&gt;
	}&lt;br /&gt;
	// this will actually make a transparent button id color = gray&lt;br /&gt;
	this.addActionButton(id, div, handler, null, false, bcolor);&lt;br /&gt;
	// remove border, for images it better without&lt;br /&gt;
	dojo.style(id, &amp;quot;border&amp;quot;, &amp;quot;none&amp;quot;);&lt;br /&gt;
	// but add shadow style (box-shadow, see css)&lt;br /&gt;
	dojo.addClass(id, &amp;quot;shadow bgaimagebutton&amp;quot;);&lt;br /&gt;
	// you can also add additional styles, such as background&lt;br /&gt;
	if (tooltip) {&lt;br /&gt;
		dojo.attr(id, &amp;quot;title&amp;quot;, tooltip);&lt;br /&gt;
	}&lt;br /&gt;
	return $(id);&lt;br /&gt;
},&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Disabling Button ===&lt;br /&gt;
&lt;br /&gt;
You can disable the &#039;&#039;&#039;bgabutton&#039;&#039;&#039; by adding the css class &#039;&#039;&#039;disabled&#039;&#039;&#039; in you js. The disabled button is still visible but is grey and not clickable.&lt;br /&gt;
For example in the &#039;&#039;&#039;onUpdateActionButtons&#039;&#039;&#039; : &lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
this.addActionButton(&#039;play_button_id&#039;, _(&#039;Play 1 to 3 cards&#039;), &#039;playFunctionButton&#039;); &lt;br /&gt;
if (condition) {&lt;br /&gt;
  dojo.addClass(&#039;play_button_id&#039;, &#039;disabled&#039;);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Custom Buttons ===&lt;br /&gt;
&lt;br /&gt;
You can create a custom button, but the BGA framework provides a standard button that requires only .css classes: &#039;&#039;&#039;bgabutton&#039;&#039;&#039; and &#039;&#039;&#039;bgabutton_${color}&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Examples:&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;a href=&amp;quot;#&amp;quot; id=&amp;quot;my_button_id&amp;quot; class=&amp;quot;bgabutton bgabutton_blue&amp;quot;&amp;gt;&amp;lt;span&amp;gt;My blue button&amp;lt;/span&amp;gt;&amp;lt;/a&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;a href=&amp;quot;#&amp;quot; id=&amp;quot;my_button_id&amp;quot; class=&amp;quot;bgabutton bgabutton_red bgabutton_big&amp;quot;&amp;gt;&amp;lt;span&amp;gt;My big red button&amp;lt;/span&amp;gt;&amp;lt;/a&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note&#039;&#039;&#039;: To see it in action, check out &#039;&#039;Coloretto&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
=== Button outside of action bar ===&lt;br /&gt;
&lt;br /&gt;
Use addActionButton() method with destination argument set&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
this.addActionButton( &#039;commit_button&#039;, _(&#039;Confirm&#039;), &#039;onConfirm&#039;, &#039;player_board&#039;, true, &#039;red&#039;); &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
in example above the button will be place on object with id &#039;player_board&#039;&lt;br /&gt;
&lt;br /&gt;
== Image loading ==&lt;br /&gt;
&lt;br /&gt;
See also [[Game_art:_img_directory]].&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Be careful&#039;&#039;&#039;: by default, ALL images of your img directory are loaded on a player&#039;s browser when he loads the game. For this reason, don&#039;t let in your img directory images that are not useful, otherwise it&#039;s going to slowdown the game load.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.dontPreloadImage(image_file_name: string)&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Using dontPreloadImage, you tell the interface to not preload a specific image in your img directory.&lt;br /&gt;
&lt;br /&gt;
Example of use:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
this.dontPreloadImage( &#039;cards.png&#039; );&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This is particularly useful if for example you have 2 different themes for a game. To accelerate the loading of the game, you can specify to not preload images corresponding to the other theme.&lt;br /&gt;
&lt;br /&gt;
Another example of use: in &amp;quot;Gosu&amp;quot; game with Kamakor extension, you play with 5 sets of cards among 10 available. Cards images are organized by sets, and we only preload the images corresponding to the 5 current sets with &#039;&#039;&#039;ensureSpecificGameImageLoading( image_file_names_array )&#039;&#039;&#039;.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
// By default, do not preload anything&lt;br /&gt;
this.dontPreloadImage( &#039;cards.png&#039; );&lt;br /&gt;
this.dontPreloadImage( &#039;clan1.png&#039; );&lt;br /&gt;
this.dontPreloadImage( &#039;clan2.png&#039; );&lt;br /&gt;
this.dontPreloadImage( &#039;clan3.png&#039; );&lt;br /&gt;
this.dontPreloadImage( &#039;clan4.png&#039; );&lt;br /&gt;
this.dontPreloadImage( &#039;clan5.png&#039; );&lt;br /&gt;
this.dontPreloadImage( &#039;clan6.png&#039; );&lt;br /&gt;
this.dontPreloadImage( &#039;clan7.png&#039; );&lt;br /&gt;
this.dontPreloadImage( &#039;clan8.png&#039; );&lt;br /&gt;
this.dontPreloadImage( &#039;clan9.png&#039; );&lt;br /&gt;
this.dontPreloadImage( &#039;clan10.png&#039; );&lt;br /&gt;
var to_preload = [];&lt;br /&gt;
for( i in this.gamedatas.clans )&lt;br /&gt;
{&lt;br /&gt;
	var clan_id = this.gamedatas.clans[i];&lt;br /&gt;
	to_preload.push( &#039;clan&#039;+clan_id+&#039;.png&#039; );&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
this.ensureSpecificGameImageLoading( to_preload );&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note:&#039;&#039;&#039; You don&#039;t need to specify to not preload game box images (game_box.png, game_box75.png...) since they are not preloaded by default.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.ensureSpecificGameImageLoading(list: string[])&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
This is oppostive of dontPreloadImage - its ensure specific images is loaded. Note: only makes sense if preload list is empty, otherwise everything is loaded anyway&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;load specific images&#039;&#039;&#039;&lt;br /&gt;
All images that will be preloaded stored in g_img_preload. If you want to override it directly - there is no API, but you can do this in GAME constructor&lt;br /&gt;
&lt;br /&gt;
          g_img_preload = [&#039;tokens.png&#039;, &#039;trains.png&#039;, &#039;loc_plan.png&#039;, &#039;eng.png&#039;, &#039;eng-back.png&#039;];&lt;br /&gt;
&lt;br /&gt;
You can also set it to empty array and call ensureSpecificGameImageLoading() on specific images&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Sounds ==&lt;br /&gt;
&lt;br /&gt;
Add a custom sound and make it load with your interface:&lt;br /&gt;
&lt;br /&gt;
Add this in your template (.tpl) file:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;audio id=&amp;quot;audiosrc_&amp;lt;gamename&amp;gt;_&amp;lt;yoursoundname&amp;gt;&amp;quot; src=&amp;quot;{GAMETHEMEURL}img/&amp;lt;gamename&amp;gt;_&amp;lt;yoursoundname&amp;gt;.mp3&amp;quot; preload=&amp;quot;none&amp;quot; autobuffer&amp;gt;&amp;lt;/audio&amp;gt;&lt;br /&gt;
&amp;lt;audio id=&amp;quot;audiosrc_o_&amp;lt;gamename&amp;gt;_&amp;lt;yoursoundname&amp;gt;&amp;quot; src=&amp;quot;{GAMETHEMEURL}img/&amp;lt;gamename&amp;gt;_&amp;lt;yoursoundname&amp;gt;.ogg&amp;quot; preload=&amp;quot;none&amp;quot; autobuffer&amp;gt;&amp;lt;/audio&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note: this is a requirement to provide both a mp3 and a ogg file with the names &amp;lt;code&amp;gt;&amp;lt;gamename&amp;gt;_&amp;lt;yoursoundname&amp;gt;[.ogg][.mp3]&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Play the sound (from your .js file):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
playSound(&#039;&amp;lt;gamename&amp;gt;_&amp;lt;yoursoundname&amp;gt;&#039;);   // do not add &#039;this.&#039; - its a global function&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Disable the standard &amp;quot;move&amp;quot; sound for this move (to replace it with your custom sound):&lt;br /&gt;
&lt;br /&gt;
Add this to your notification handler:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
this.disableNextMoveSound();&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note: it only disable the sound for the next move.&lt;br /&gt;
&lt;br /&gt;
== Title bar and states ==&lt;br /&gt;
&lt;br /&gt;
=== Client states ===&lt;br /&gt;
&lt;br /&gt;
Client states is a way to simulate the state transition but without actually going&lt;br /&gt;
to server. It is usefull when you need to ask user multiple questions before you&lt;br /&gt;
send things to server&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.setClientState(newState: string, args: object)&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
     this.setClientState(&amp;quot;client_playerPicksLocation&amp;quot;, {&lt;br /&gt;
                               descriptionmyturn : _(&amp;quot;${you} must select location&amp;quot;),&lt;br /&gt;
                           });&lt;br /&gt;
&lt;br /&gt;
For more information see [[BGA_Studio_Cookbook#Multi_Step_Interactions:_Select_Worker.2FPlace_Worker_-_Using_Client_States]]&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.restoreServerGameState()&#039;&#039;&#039;&lt;br /&gt;
If you are in client state it will restore the current server state (cheap undo)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.on_client_state&#039;&#039;&#039;&lt;br /&gt;
Boolean indicating that we are in client state&lt;br /&gt;
&lt;br /&gt;
=== Title bar ===&lt;br /&gt;
If you simply want to show something in title bar you can do it directly &lt;br /&gt;
     $(&#039;pagemaintitletext&#039;).innerHTML = text;&lt;br /&gt;
&lt;br /&gt;
This however will not work with parameters and will not draw You in color,&lt;br /&gt;
if you want to do proper args rendering use method below&lt;br /&gt;
&lt;br /&gt;
;&#039;&#039;&#039;this.removeActionButtons()&#039;&#039;&#039;&lt;br /&gt;
Removes all buttons from title bar&lt;br /&gt;
&lt;br /&gt;
;&#039;&#039;&#039;this.updatePageTitle()&#039;&#039;&#039;&lt;br /&gt;
:This function allows to update the current page title and turn description according to the game state arguments. If the current game state description this.gamedatas.gamestate.descriptionmyturn is modified before calling this function it allows to update the turn description without changing state. This will handle arguments substitutions properly.&lt;br /&gt;
&lt;br /&gt;
Note: this functional also will calls this.onUpdateActionButtons, if you want different buttons then state defaults, use method in example to replace them, if it becomes too clumsy use client states (see above)&lt;br /&gt;
&lt;br /&gt;
Example from Terra Mystica:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
onClickFavorTile: function( evt ) {&lt;br /&gt;
    ...&lt;br /&gt;
    if ( ... ) {&lt;br /&gt;
        this.gamedatas.gamestate.descriptionmyturn = _(&#039;Special action: &#039;) + _(&#039;Advance 1 space	on a Cult track&#039;);&lt;br /&gt;
        this.updatePageTitle();&lt;br /&gt;
        this.removeActionButtons();&lt;br /&gt;
        this.addActionButton( ... );&lt;br /&gt;
         ...&lt;br /&gt;
        return;&lt;br /&gt;
    }&lt;br /&gt;
    ...&lt;br /&gt;
&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== User preferences ==&lt;br /&gt;
&#039;&#039;&#039;this.getGameUserPreference(pref_id)&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Return the value of a user preference. It will return the value currently selected in the select combo box, in the top-right menu.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.setGameUserPreference(pref_id, value)&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Programmatically change a user preference. It will have the same effect as if the player changed the value in the select combo box, in the top-right menu.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.onGameUserPreferenceChanged&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
A callback you can define if you want to be notified when a user changes a user preference.&lt;br /&gt;
&lt;br /&gt;
Example:&amp;lt;pre&amp;gt;&lt;br /&gt;
onGameUserPreferenceChanged: function(pref_id, pref_value) {&lt;br /&gt;
  switch (pref_id) {&lt;br /&gt;
    case 201: &lt;br /&gt;
      document.getElementsByTagName(&#039;html&#039;)[0].classList.toggle(&#039;dark-background&#039;, pref_value == 2);&lt;br /&gt;
      break;&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Other useful stuff ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;dojo.hitch&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
With dojo.hitch, you can create a callback function that will run with your game object context whatever happen.&lt;br /&gt;
&lt;br /&gt;
Typical example: display a BGA confirmation dialog with a callback function created with dojo.hitch:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        this.confirmationDialog( _(&#039;Are you sure you want to make this?&#039;), dojo.hitch( this, function() {&lt;br /&gt;
            this.bgaPerformAction(&#039;makeThis&#039;);&lt;br /&gt;
        } ) );   &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In the example above, using dojo.hitch, we ensure that the &amp;quot;this&amp;quot; object will be set when the callback is called.&lt;br /&gt;
&lt;br /&gt;
NOTE: In modern JS there are lambdas that eliminate need for that, the example above will look like this&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        this.confirmationDialog( _(&#039;Are you sure you want to make this?&#039;), () =&amp;gt; this.bgaPerformAction( &#039;makeThis&#039;) );   &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
;&#039;&#039;&#039;onScreenWidthChange()&#039;&#039;&#039;&lt;br /&gt;
:This function can be overridden in your game to manage some resizing on the client side when the browser window is resized. This function is also triggered at load time, so it can be used to adapt to the :viewport size at the start of the game too.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
; this.bRealtime&lt;br /&gt;
: Return true if the game is in realtime. Note that having a distinct behavior in realtime and turn-based should be exceptional.&lt;br /&gt;
&lt;br /&gt;
; g_replayFrom&lt;br /&gt;
: Global contains replay number in live game, it is set to undefined (i.e. not set) when it is not a replay mode, so consequentially the good check is &#039;&#039;&#039;typeof g_replayFrom != &#039;undefined&#039;&#039;&#039;&#039; which returns true if the game is in replay mode &amp;lt;i&amp;gt;during the game&amp;lt;/i&amp;gt; (the game is ongoing but the user clicked &amp;quot;replay from this move&amp;quot; in the log)&lt;br /&gt;
&lt;br /&gt;
; g_archive_mode&lt;br /&gt;
: Returns true if the game is in archive mode &amp;lt;i&amp;gt;after the game&amp;lt;/i&amp;gt; (the game has ended)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
; this.instantaneousMode&lt;br /&gt;
: Returns true during replay/archive mode if animations should be skipped. Only needed if you are doing custom animations. (The BGA-provided animation functions like &amp;lt;i&amp;gt;this.slideToObject()&amp;lt;/i&amp;gt; automatically handle instantaneous mode.)&lt;br /&gt;
: Technically, when you click &amp;quot;replay from move #20&amp;quot;, the system replays the game from the very beginning with moves 0 - 19 happening in instantaneous mode and moves 20+ happening in normal mode.&lt;br /&gt;
&lt;br /&gt;
; g_tutorialwritten&lt;br /&gt;
: Returns an object like the below if the game is in tutorial mode, or undefined otherwise. Tutorial mode is a special case of archive mode where comments have been added to a previous game to teach new players the rules.&lt;br /&gt;
    {&lt;br /&gt;
        author: &amp;quot;91577332&amp;quot;,&lt;br /&gt;
        id: &amp;quot;576&amp;quot;,&lt;br /&gt;
        mode: &amp;quot;view&amp;quot;&lt;br /&gt;
        status: &amp;quot;alpha&amp;quot;&lt;br /&gt;
        version_override: null&lt;br /&gt;
        viewer_id: &amp;quot;84554161&amp;quot;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;getBgaEnvironment(): string&#039;&#039;&#039;&lt;br /&gt;
: Returns &amp;quot;studio&amp;quot; for studio and &amp;quot;prod&amp;quot; for production environment (i.e. where games current runs). Only useful for debbugging hooks.&lt;br /&gt;
Note: alpha server is also &amp;quot;prod&amp;quot;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Category:Studio]]&lt;/div&gt;</summary>
		<author><name>Sguzzer Gunayer</name></author>
	</entry>
	<entry>
		<id>https://en.doc.boardgamearena.com/index.php?title=Game_interface_logic:_Game.js&amp;diff=22730</id>
		<title>Game interface logic: Game.js</title>
		<link rel="alternate" type="text/html" href="https://en.doc.boardgamearena.com/index.php?title=Game_interface_logic:_Game.js&amp;diff=22730"/>
		<updated>2024-09-25T16:45:37Z</updated>

		<summary type="html">&lt;p&gt;Sguzzer Gunayer: /* Creating and Destroying elements */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Studio_Framework_Navigation}}&lt;br /&gt;
&lt;br /&gt;
__TOC__&lt;br /&gt;
&lt;br /&gt;
This is the main file for your game interface. Here you will define:&lt;br /&gt;
&lt;br /&gt;
* Which actions on the page will generate calls to the server.&lt;br /&gt;
* What happens when you get a notification for a change from the server and how it will show in the browser. &lt;br /&gt;
* Setup user interface&lt;br /&gt;
&lt;br /&gt;
== File structure ==&lt;br /&gt;
&lt;br /&gt;
The details of how the file is structured are described below with comments in the code skeleton provided to you.&lt;br /&gt;
&lt;br /&gt;
Here is the basic structure:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;constructor&#039;&#039;&#039;: here you can define global variables for your whole interface.&lt;br /&gt;
* &#039;&#039;&#039;setup&#039;&#039;&#039;: this method is called when the page is refreshed, and sets up the game interface.&lt;br /&gt;
* &#039;&#039;&#039;onEnteringState&#039;&#039;&#039;: this method is called when entering a new game state. You can use it to customize the view for each game state.&lt;br /&gt;
* &#039;&#039;&#039;onLeavingState&#039;&#039;&#039;: this method is called when leaving a game state.&lt;br /&gt;
* &#039;&#039;&#039;onUpdateActionButtons&#039;&#039;&#039;: called on state changes, in order to add action buttons to the status bar. Note: in a multipleactiveplayer state, it will be called when another player has become inactive.&lt;br /&gt;
* &#039;&#039;(utility methods)&#039;&#039;: this is where you can define your utility methods.&lt;br /&gt;
* &#039;&#039;(player&#039;s actions)&#039;&#039;: this is where you can write your handlers for player actions on the interface (example: click on an item).&lt;br /&gt;
* &#039;&#039;&#039;setupNotifications&#039;&#039;&#039;: this method associates notifications with notification handlers. For each game notification, you can trigger a javascript method to handle it and update the game interface.&lt;br /&gt;
* &#039;&#039;(notification handlers)&#039;&#039;: this is where you define the notifications handlers associated with notifications in &#039;&#039;&#039;setupNotifications&#039;&#039;&#039;, above.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
More details:&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;setup(gamedatas: object)            &#039;&#039;&#039;&lt;br /&gt;
This method must set up the game user interface according to current game situation specified in parameters.&lt;br /&gt;
The method is called each time the game interface is displayed to a player, ie:&lt;br /&gt;
&lt;br /&gt;
* when the game starts&lt;br /&gt;
* when a player opens a game in the browser later &lt;br /&gt;
* when a player refreshes the game page (F5)&lt;br /&gt;
* when player does a server side Undo&lt;br /&gt;
&lt;br /&gt;
&amp;quot;gamedatas&amp;quot; argument contains all data retrieved by your &amp;quot;getAllDatas&amp;quot; PHP method and some more.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;onEnteringState(stateName: string, args: { args: any } | null): void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
This method is called each time we enter a new game state.&lt;br /&gt;
You can use this method to perform some user interface changes at this moment.&lt;br /&gt;
To access state arguments passed via calling php arg* method use args?.args.&lt;br /&gt;
Typically you would do something only for active player, using this.isCurrentPlayerActive() check.&lt;br /&gt;
It is also called (for the current game state only) when doing a browser refresh (after the setup method is called).&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Warning&#039;&#039;&#039;: for multipleactiveplayer states:&lt;br /&gt;
the active players are NOT active yet so you must use onUpdateActionButtons to perform the client side operation which depends on a player active/inactive status.&lt;br /&gt;
If you are doing initialization of some structures which do not depend on the active player, you can just replace (this.isCurrentPlayerActive()) with (!this.isSpectator) &lt;br /&gt;
for the main switch in that method.&lt;br /&gt;
&lt;br /&gt;
See more details in [[Your_game_state_machine:_states.inc.php#Difference_between_Single_active_and_Multi_active_states]]&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;onLeavingState(stateName: string): void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
This method is called each time we leave a game state.&lt;br /&gt;
You can use this method to perform some user interface changes at this point (i.e. cleanup).&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;onUpdateActionButtons(stateName: string, args: object | null): void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
In this method you can manage &amp;quot;action buttons&amp;quot; that are displayed in the action status bar and highlight active UI elements.&lt;br /&gt;
To access state arguments passed via calling php arg* method use &#039;&#039;&#039;args&#039;&#039;&#039; parameter. Note: args can be null! For &#039;&#039;&#039;game&#039;&#039;&#039; states and when you don&#039;t supply state args function - it is null.&lt;br /&gt;
This method is called when the active or multiactive player changes. In a classic &amp;quot;activePlayer&amp;quot; state this method is called before the onEnteringState state.&lt;br /&gt;
In multipleactiveplayer state it is a mess. The sequencing of calls depends on whether you get into that state from transitions OR from reloading the whole game (i.e. F5).&lt;br /&gt;
&lt;br /&gt;
See more details in [[Your_game_state_machine:_states.inc.php#Difference_between_Single_active_and_Multi_active_states]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Dojo framework ==&lt;br /&gt;
&lt;br /&gt;
BGA uses the [http://dojotoolkit.org/ Dojo Javascript framework].&lt;br /&gt;
&lt;br /&gt;
The Dojo framework allows us to do complex things more easily. The BGA framework uses Dojo extensively.&lt;br /&gt;
&lt;br /&gt;
To implement a game, you only need to use a few parts of the Dojo framework. All the Dojo methods you need are described on this page.&lt;br /&gt;
&lt;br /&gt;
== Javascript minimization (after July 2020) ==&lt;br /&gt;
&lt;br /&gt;
For performance reasons, when deploying a game the javascript code is minimized using &#039;&#039;&#039;terser&#039;&#039;&#039; (https://github.com/terser/terser). This minifier works with modern javascript syntax. From your project &amp;quot;Manage game&amp;quot; page, you can now test a minified version of your javascript on the studio (and revert to the original).&lt;br /&gt;
&lt;br /&gt;
NB: it has been reported that there is an issue with this minifier and percentage values for opacity.&lt;br /&gt;
&lt;br /&gt;
== Accessing Players Information ==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.player_id: number&#039;&#039;&#039;&lt;br /&gt;
id of the player who is looking at the game. The player may not be part of the game (i.e. spectator)&lt;br /&gt;
  if (notif.args.player_id == this.player_id) {&lt;br /&gt;
    ...&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.isSpectator: boolean&#039;&#039;&#039;&lt;br /&gt;
Flag set to true if the user at the table is a spectator (not a player).&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    if (this.isSpectator) {&lt;br /&gt;
        this.player_color = &#039;ffffff&#039;;&lt;br /&gt;
    } else {&lt;br /&gt;
        this.player_color = gamedatas.players[this.player_id].color;&lt;br /&gt;
    }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note: If you want to hide an element from spectators, you should use [[Game_interface_stylesheet:_yourgamename.css#spectatorMode|CSS &#039;spectatorMode&#039; class]].&lt;br /&gt;
&lt;br /&gt;
You may consider making a function like this, to detect if the game is in a read-only state (i.e. non-interactive):&lt;br /&gt;
  // Returns true for spectators, instant replay (during game), archive mode (after game end)&lt;br /&gt;
  isReadOnly: function () {&lt;br /&gt;
    return this.isSpectator || typeof g_replayFrom != &#039;undefined&#039; || g_archive_mode;&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.gamedatas: object&#039;&#039;&#039;&lt;br /&gt;
Contains the initial set of data to init the game, created at game start or by game refresh (F5).&lt;br /&gt;
You can update it as needed to keep an up-to-date reference of the game on the client side if you need it, however most of the time this is unnecessary.&lt;br /&gt;
&lt;br /&gt;
Note: In hotseat mode, the framework does not keep this.gamedatas of hotseat players and shares the same set as the main player to store data.&lt;br /&gt;
&lt;br /&gt;
Note: be careful when you update this data structurally, many framework functions expect data to be certain way and they will break if they see something else.&lt;br /&gt;
&lt;br /&gt;
Typical example of accessing player&#039;s info&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
for (var player_id in this.gamedatas.players) { &lt;br /&gt;
    var playerInfo = this.gamedatas.players [player_id];&lt;br /&gt;
    var c = playerInfo.color;&lt;br /&gt;
    var name = playerInfo.name;&lt;br /&gt;
    // do something &lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.isCurrentPlayerActive(): boolean&#039;&#039;&#039;&lt;br /&gt;
Returns true if the player on whose browser the code is running is currently active (it&#039;s his turn to play). Note: see remarks above about usage of this function inside onEnteringState method.&lt;br /&gt;
  if (this.isCurrentPlayerActive()) ...&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.getActivePlayerId(): number&#039;&#039;&#039;&lt;br /&gt;
Return the ID of the active player, or null if we are not in an &amp;quot;activeplayer&amp;quot; type state.&lt;br /&gt;
  if (this.player_id == this.getActivePlayerId()) ...&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.getActivePlayers(): number[]&#039;&#039;&#039;&lt;br /&gt;
Return an array with the IDs of players who are currently active (or an empty array if there are none).&lt;br /&gt;
&lt;br /&gt;
== Accessing and manipulating the DOM ==&lt;br /&gt;
&lt;br /&gt;
=== Element by Id ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;$(elementId: ElementOrId)&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
The $ function is used to get an HTML element using its &amp;quot;id&amp;quot; attribute.&lt;br /&gt;
&lt;br /&gt;
Example: modify the content of a &amp;quot;span&amp;quot; element:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
In your HTML code:&lt;br /&gt;
   &amp;lt;span id=&amp;quot;a_value_in_the_game_interface&amp;quot;&amp;gt;1234&amp;lt;/span&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In your Javascript code:&lt;br /&gt;
   $(&#039;a_value_in_the_game_interface&#039;).innerHTML = &amp;quot;9999&amp;quot;;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Note: It is safe to use if you don&#039;t know if variable is string (id of element) or element itself, i.e. &lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  foo: function(card) {&lt;br /&gt;
       card = $(card); // now its node, no need to write if (typeof card === &#039;string&#039;) ...&lt;br /&gt;
       // but its good idea to check for null here&lt;br /&gt;
       ...&lt;br /&gt;
  }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;getElementById(elementId: string)&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Note: $() is the standard method to access some HTML element with the BGA Framework. You can use &#039;&#039;&#039;getElementById&#039;&#039;&#039; but it is longer to type and less handy as it does not do some checks.&lt;br /&gt;
&lt;br /&gt;
=== Style ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;dojo.style(node: ElementOrId, styleName: string, styleValue: any): void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
With dojo.style you can modify the CSS property of any HTML element in your interface.&lt;br /&gt;
&lt;br /&gt;
Examples:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
     // Make an element disappear&lt;br /&gt;
     dojo.style( &#039;my_element&#039;, &#039;display&#039;, &#039;none&#039; );&lt;br /&gt;
&lt;br /&gt;
     // Give an element a 2px border&lt;br /&gt;
     dojo.style( &#039;my_element&#039;, &#039;borderWidth&#039;, &#039;2px&#039; );&lt;br /&gt;
&lt;br /&gt;
     // Change the background position of an element&lt;br /&gt;
     // (very practical when you are using CSS sprites to transform an element to another)&lt;br /&gt;
     dojo.style( &#039;my_element&#039;, &#039;backgroundPosition&#039;, &#039;-20px -50px&#039; );&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note: if you have to modify several CSS properties of an element, or if you have a complex CSS transformation to do, you should consider using dojo.addClass/dojo.removeClass (see below).&lt;br /&gt;
&lt;br /&gt;
You can also use object to set multiple values&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
dojo.setStyle(&amp;quot;thinger&amp;quot;, {&lt;br /&gt;
  &amp;quot;opacity&amp;quot;: 0.5,&lt;br /&gt;
  &amp;quot;border&amp;quot;: &amp;quot;3px solid black&amp;quot;,&lt;br /&gt;
  &amp;quot;height&amp;quot;: &amp;quot;300px&amp;quot;&lt;br /&gt;
});&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.addStyleToClass(cssClassName: string, styleName: string, styleValue: any):&#039;&#039;&#039; &#039;&#039;&#039;void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Same as dojo.style(), but for all the nodes set with the specified cssClassName&lt;br /&gt;
Equivalent of &lt;br /&gt;
  &lt;br /&gt;
  dojo.query(`.${aclass}`).style(styleName, styleValue)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
dojo.query(&amp;quot;#baz &amp;gt; div&amp;quot;).style({&lt;br /&gt;
  opacity:0.75,&lt;br /&gt;
  fontSize:&amp;quot;13pt&amp;quot;&lt;br /&gt;
});&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Vanilla JS style&#039;&#039;&#039;&lt;br /&gt;
  $(&#039;my_element&#039;).style.display=&#039;none&#039;; // set&lt;br /&gt;
  var display = $(&#039;my_element&#039;).style.display; // get&lt;br /&gt;
  $(&#039;my_element&#039;).style.removeProperty(&#039;display&#039;); // remove&lt;br /&gt;
&lt;br /&gt;
=== Classes ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;dojo.addClass(node: ElementOrId, classes: string): void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;dojo.removeClass(node: ElementOrId, classes: string): void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;dojo.hasClass(node: ElementOrId, aclass: string): void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;dojo.toggleClass(node: ElementOrId, aclass: string): void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
In many situations, many small CSS property updates can be replaced by a CSS class change (i.e., you add a CSS class to your element instead of applying all modifications manually).&lt;br /&gt;
&lt;br /&gt;
Advantages are:&lt;br /&gt;
* All your CSS stuff remains in your CSS file.&lt;br /&gt;
* You can add/remove a list of CSS modifications with a simple function and without error.&lt;br /&gt;
* You can test whether you applied the CSS to an element with the &#039;&#039;&#039;dojo.hasClass&#039;&#039;&#039; method.&lt;br /&gt;
&lt;br /&gt;
Example from &#039;&#039;Reversi&#039;&#039;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    // We add &amp;quot;possibleMove&amp;quot; to an element&lt;br /&gt;
    dojo.addClass( &#039;square_&#039;+x+&#039;_&#039;+y, &#039;possibleMove&#039; );&lt;br /&gt;
&lt;br /&gt;
    // In our CSS file, the class is defined as:&lt;br /&gt;
    .possibleMove {&lt;br /&gt;
      background-color: white;&lt;br /&gt;
      opacity: 0.2;&lt;br /&gt;
      filter:alpha(opacity=20); /* For IE8 and earlier */  &lt;br /&gt;
      cursor: pointer;  &lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
     // So we&#039;ve applied 4 CSS property changes in one line of code.&lt;br /&gt;
&lt;br /&gt;
     // ... and when we need to check if a square is a possible move on the client side:&lt;br /&gt;
     if( dojo.hasClass( &#039;square_&#039;+x+&#039;_&#039;+y, &#039;possibleMove&#039; ) )&lt;br /&gt;
     { ... }&lt;br /&gt;
&lt;br /&gt;
     // ... and if we want to remove all possible moves in one line of code (see &amp;quot;dojo.query&amp;quot; method):&lt;br /&gt;
     dojo.query( &#039;.possibleMove&#039; ).removeClass( &#039;possibleMove&#039; );&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Vanilla JS classList&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
This is the only exception where dojo versions are better&lt;br /&gt;
  // add class&lt;br /&gt;
  $(token_id).classList.addClass(&#039;possibleMove&#039;);&lt;br /&gt;
  // remove class&lt;br /&gt;
  $(token_id).classList.removeClass(&#039;possibleMove&#039;);&lt;br /&gt;
  // add 2 classes&lt;br /&gt;
  const myclasses = [&#039;a&#039;,&#039;b&#039;];&lt;br /&gt;
  $(token_id).classList.addClass(...myclasses);&lt;br /&gt;
  // add classes to query result&lt;br /&gt;
  document.querySelectorAll(&amp;quot;.hand .card&amp;quot;).forEach((node)=&amp;gt;node.classList.addClass(&#039;possibleMove&#039;));&lt;br /&gt;
&lt;br /&gt;
=== Attributes ===&lt;br /&gt;
&lt;br /&gt;
;dojo.attr&lt;br /&gt;
&lt;br /&gt;
With dojo.attr you can access or change the value of an attribute or property of any HTML element in your interface.&lt;br /&gt;
&lt;br /&gt;
Exemple:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
     // Get the title of a node&lt;br /&gt;
     var title = dojo.attr( id, &#039;title&#039; );&lt;br /&gt;
     // Change the height of a node&lt;br /&gt;
     dojo.attr( &#039;img_growing_tree&#039;, &#039;height&#039;, 100 );&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Vanilla JS attr&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
   $(token).id=new_id; // set attr for &amp;quot;id&amp;quot;&lt;br /&gt;
   var id = $(token).id; // get&lt;br /&gt;
&lt;br /&gt;
=== Queries ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;dojo.query(cssSelector: string): Element[]&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
With dojo.query, you can query a bunch of HTML elements with a single function, with a &amp;quot;CSS selector&amp;quot; style.&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
     // All elements with class &amp;quot;possibleMove&amp;quot;:&lt;br /&gt;
     var elements = dojo.query( &#039;.possibleMove&#039; );&lt;br /&gt;
&lt;br /&gt;
     // Count number of tokens (i.e., elements of class &amp;quot;token&amp;quot;) on the board (i.e., the element with id &amp;quot;board&amp;quot;):&lt;br /&gt;
     dojo.query( &#039;#board .token&#039; ).length;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
But what is really cool with dojo.query is that you can combine it with almost all methods above.&lt;br /&gt;
&lt;br /&gt;
Examples:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
     // Trigger a method when the mouse enter in any element with class &amp;quot;meeple&amp;quot;:&lt;br /&gt;
     dojo.query( &#039;.meeple&#039; ).connect( &#039;onmouseenter&#039;, this, &#039;myMethodToTrigger&#039; );&lt;br /&gt;
&lt;br /&gt;
     // Hide all meeples who are on the board&lt;br /&gt;
     dojo.query( &#039;#board .meeple&#039; ).style( &#039;display&#039;, &#039;none&#039; );&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Vanilla JS query&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
  var cards=document.querySelectorAll(&amp;quot;.hand .card&amp;quot;);// all cards in all hands&lt;br /&gt;
  var cards=$(&#039;hand&#039;).querySelectorAll(&amp;quot;.card&amp;quot;);// all cards in specific hand&lt;br /&gt;
  var card=document.querySelector(&amp;quot;.hand .card&amp;quot;);// first card or null if none (super handy)&lt;br /&gt;
&lt;br /&gt;
=== Creating and Destroying elements ===&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;dojo.empty(node: ElementOrId)&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Remove all children of the node element&lt;br /&gt;
   dojo.empty(&#039;my_hand&#039;);&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;dojo.destroy(node: ElementOrId)&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Remove the element&lt;br /&gt;
   dojo.destroy(&#039;my_token&#039;);&lt;br /&gt;
&lt;br /&gt;
   dojo.query(&amp;quot;.green&amp;quot;, mynode).forEach(dojo.destroy); // this remove all subnode of class green from mynode&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;dojo.create(tag: string, attributes?: obj, parent?: ElementOrId): Element&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Create element&lt;br /&gt;
&lt;br /&gt;
    dojo.create(&amp;quot;div&amp;quot;, { class: &amp;quot;yellow_arrow&amp;quot; }, parent); // this creates div with class yellow_array and places it in &amp;quot;parent&amp;quot;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.format_block(name: string, args: object): string&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
This bga function that takes global var from template file and substitute variables, typical use would be&lt;br /&gt;
&lt;br /&gt;
                var player = gamedatas.players[player_id];&lt;br /&gt;
                var div = this.format_block(&#039;jstpl_player_board&#039;, player ); // var jstpl_player_board = ... is defined in .tpl file &lt;br /&gt;
Note: result is trimmed&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.format_string(name: string, args: object): string&#039;&#039;&#039;&lt;br /&gt;
This bga function just substitute variables in a string, i.e.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
     var div = this.format_string(&#039;&amp;lt;div color=&amp;quot;${player_color}&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&#039;, {player_color: &#039;#ff0000&#039;} );&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Note: result is trimmed&lt;br /&gt;
&lt;br /&gt;
Note: this can be replaced by using backquoted string now: &lt;br /&gt;
     const player_color =  &#039;#ff0000&#039;;&lt;br /&gt;
     const div = `&amp;lt;div color=&amp;quot;${player_color}&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;`;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.format_string_recursive&#039;&#039;&#039;&lt;br /&gt;
This bga function is similar to this.format_string but is capable of processing recursive argument structures and translations. It is used to format server notifications.&lt;br /&gt;
&lt;br /&gt;
TODO: find better place for these function docs&lt;br /&gt;
&lt;br /&gt;
=== Moving elements ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;dojo.place(node: string | Element, refNode: ElementOrId, pos?: string | number): Element&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
dojo.place is the best function to insert HTML code somewhere in your game interface without breaking something. It is much better to use than the &#039;&#039;&#039;innerHTML=&#039;&#039;&#039; method if you must insert HTML tags and not only values.&lt;br /&gt;
&lt;br /&gt;
node: &lt;br /&gt;
&lt;br /&gt;
Can be a String or a DOM node. If it is a string starting with “&amp;lt;”, it is assumed to be an HTML fragment, which will be created. Otherwise it is assumed to be an id of a DOM node.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
     // Insert your HTML code as a child of a container element&lt;br /&gt;
     dojo.place( &amp;quot;&amp;lt;div class=&#039;foo&#039;&amp;gt;&amp;lt;/div&amp;gt;&amp;quot;, &amp;quot;your_container_element_id&amp;quot; );&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
pos:&lt;br /&gt;
&lt;br /&gt;
Optional argument. Can be a number or one of the following strings: “before”, “after”, “replace”, “only”, “first”, or “last”. If omitted, “last” is assumed. &lt;br /&gt;
&lt;br /&gt;
&amp;quot;replace&amp;quot;: Replace the container element with my_node element&lt;br /&gt;
&lt;br /&gt;
&amp;quot;first&amp;quot;: Places the node as a child of the reference node. The node is placed as the first child.&lt;br /&gt;
&lt;br /&gt;
&amp;quot;last&amp;quot; (default): Places the node as a child of the reference node. The node is placed as the last child.&lt;br /&gt;
&lt;br /&gt;
&amp;quot;before&amp;quot;: places the node right before the reference node.&lt;br /&gt;
&lt;br /&gt;
&amp;quot;after&amp;quot;: places the node right after the reference node.&lt;br /&gt;
&lt;br /&gt;
&amp;quot;only&amp;quot;: replaces all children of the reference node with the node.&lt;br /&gt;
&lt;br /&gt;
positive integer: This parameter can be a positive integer. In this case, the node will be placed as a child of the reference node with this number (counting from 0). If the number is more than number of children, the node will be appended to the reference node making it the last child. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
     // Replace all children of container with my_node &lt;br /&gt;
     dojo.place( $(&#039;my_node&#039;), &amp;quot;your_container_element_id&amp;quot;, &amp;quot;only&amp;quot; );&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
See also full doc on dojo.place: [https://dojotoolkit.org/reference-guide/1.7/dojo/place.html]&lt;br /&gt;
&lt;br /&gt;
Usually, when you want to insert some piece of HTML in your game interface, you should use &amp;quot;[[Game_layout:_view_and_template:_yourgamename.view.php_and_yourgamename_yourgamename.tpl#Javascript_templates|Javascript templates]]&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
But you can also relocate elements like that. Note: it won&#039;t animate if you do that.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.placeOnObject(mobile_obj: ElementOrId, target_obj: ElementOrId): void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
places mobile_obj on target_obj, set the absolute positions and centers the mobile_obj on target_obj,&lt;br /&gt;
effect is immediate&lt;br /&gt;
&lt;br /&gt;
This is not really an animation, but placeOnObject is frequently used before starting an animation.&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  // (We just created an object &amp;quot;my_new_token&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
  // Place the new token on current player board&lt;br /&gt;
  this.placeOnObject( &amp;quot;my_new_token&amp;quot;, &amp;quot;overall_player_board_&amp;quot;+this.player_id );&lt;br /&gt;
  &lt;br /&gt;
  // Then slide it to its position on the board&lt;br /&gt;
  this.slideToObject( &amp;quot;my_new_token&amp;quot;, &amp;quot;a_place_on_board&amp;quot; ).play();&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.placeOnObjectPos(mobile_obj: ElementOrId, target_obj: ElementOrId, target_x: number, target_y: number): void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
This method works exactly like placeOnObject, except than you can specify some (x,y) coordinates (in px). This way, the center of &amp;quot;mobile_obj&amp;quot; will be placed to the specified x,y position relatively to the center of &amp;quot;target_obj&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Note: the placement works differently from this.slideToObjectPos&#039;&#039;, since coordinates are calculated based on the center of objects.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.attachToNewParent(mobile_obj: ElementOrId, target_obj: ElementOrId): void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
With this method, you change the HTML parent of &amp;quot;mobile_obj&amp;quot; element without moving it. &lt;br /&gt;
&amp;quot;target_obj&amp;quot; is the new parent of this element. The beauty of &lt;br /&gt;
attachToNewParent is that the mobile_obj element DOES NOT MOVE during this process.&lt;br /&gt;
&lt;br /&gt;
What happens is that the method calculate a relative position of mobile_obj to make sure it does not move after the HTML parent changes.&lt;br /&gt;
&lt;br /&gt;
Why using this method?&lt;br /&gt;
&lt;br /&gt;
Changing the HTML parent of an element can be useful for the following reasons:&lt;br /&gt;
* When the HTML parent moves, all its child are moving with them. If some game elements is no more linked with a parent HTML object, you may want to attach it to another place.&lt;br /&gt;
* The z_order (vertical order of display) depends on the position in the DOM, so you may need to change the parent of some game elements when they are moving in your game area.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;CAREFUL&#039;&#039;&#039;: this function destroys original object and places a clone onto a new parent, this will break all references to this HTML element (ex: dojo.connect).&lt;br /&gt;
If you need version that does not destroy the object but the same otherwise see [[BGA_Studio_Cookbook#Attach_to_new_parent_without_destroying_the_object]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Animations ==&lt;br /&gt;
&lt;br /&gt;
===Dojo Animations===&lt;br /&gt;
&lt;br /&gt;
BGA animations is based on Dojo Animation ([http://dojotoolkit.org/documentation/tutorials/1.8/animation/ see tutorial here]).&lt;br /&gt;
&lt;br /&gt;
However, most of the time, you can just use methods below, which are built on top of Dojo Animation.&lt;br /&gt;
&lt;br /&gt;
Note: one interesting method from Dojo that could be useful from time to time is &amp;quot;Dojo.Animation&amp;quot;. It allows you to make any CSS property &amp;quot;slide&amp;quot; from one value to another.&lt;br /&gt;
&lt;br /&gt;
Note 2: the slideTo methods are not compatible with CSS transform (scale, zoom, rotate...). If possible, avoid using CSS transform on nodes that are being slided. Eventually, the only possible solution to make these 2 compatible is to disable all CSS transform properties, use slideToObjectPos/placeOnObjectPos, and then apply them again.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Sliding===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.slideToObject(mobile_obj: ElementOrId, target_obj: ElementOrId, duration?: number, delay?: number): Animation&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
You can use slideToObject to &amp;quot;slide&amp;quot; an element to a target position.&lt;br /&gt;
&lt;br /&gt;
Sliding element on the game area is the recommended and the most used way to animate your game interface. Using slides allow players to figure out what is happening on the game, as if they were playing with the real boardgame.&lt;br /&gt;
&lt;br /&gt;
The parameters are:&lt;br /&gt;
* mobile_obj: the ID of the object to move. This object must be &amp;quot;relative&amp;quot; or &amp;quot;absolute&amp;quot; positioned.&lt;br /&gt;
* target_obj: the ID of the target object. This object must be &amp;quot;relative&amp;quot; or &amp;quot;absolute&amp;quot; positioned. Note that it is not mandatory that mobile_obj and target_obj have the same size. If their size are different, the system slides the center of mobile_obj to the center of target_obj.&lt;br /&gt;
* duration: (optional) defines the duration in millisecond of the slide. The default is 500 milliseconds.&lt;br /&gt;
* delay: (optional). If you defines a delay, the slide will start only after this delay. This is particularly useful when you want to slide several object from the same position to the same position: you can give a 0ms delay to the first object, a 100ms delay to the second one, a 200ms delay to the third one, ... this way they won&#039;t be superposed during the slide.&lt;br /&gt;
&lt;br /&gt;
BE CAREFUL: The method returns an dojo.fx animation, so you can combine it with other animation if you want to. It means that you have to call the &amp;quot;play()&amp;quot; method, otherwise the animation WON&#039;T START.&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
   this.slideToObject( &amp;quot;some_token&amp;quot;, &amp;quot;some_place_on_board&amp;quot; ).play();&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.slideToObjectPos(mobile_obj: ElementOrId, target_obj: ElementOrId, target_x: number, target_y: number, duration?: number, delay?: number): Animation&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
This method does exactly the same as &amp;quot;slideToObject&amp;quot;, except than you can specify some (x,y) coordinates. This way, &amp;quot;mobile_obj&amp;quot; will slide to the specified x,y position relatively to &amp;quot;target_obj&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
Example: slide a token to some place on the board, 10 pixels from the top:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
   this.slideToObjectPos( &amp;quot;some_token&amp;quot;, &amp;quot;some_place_on_board&amp;quot;, 0, 10 ).play();&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.slideTemporaryObject(mobile_obj_html: string, parent: ElementOrId, from: ElementOrId, to: ElementOrId, duration?: number, delay?: number): Animation&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
This method is useful when you want to slide a temporary HTML object from one place to another. As this object does not exists before the animation and won&#039;t remain after, it could be complex to create this object (with dojo.place), to place it at its origin (with placeOnObject) to slide it (with slideToObject) and to make it disappear at the end.&lt;br /&gt;
&lt;br /&gt;
slideTemporaryObject does all of this for you:&lt;br /&gt;
* mobile_obj_html is a piece of HTML code that represent the object to slide.&lt;br /&gt;
* parent is the ID of an HTML element of your interface that will be the parent of this temporary HTML object.&lt;br /&gt;
* from is the ID of the origin of the slide.&lt;br /&gt;
* to is the ID of the target of the slide.&lt;br /&gt;
* duration/delay works exactly like in &amp;quot;slideToObject&amp;quot;&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
this.slideTemporaryObject( &#039;&amp;lt;div class=&amp;quot;token_icon&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&#039;, &#039;tokens&#039;, &#039;my_origin_div&#039;, &#039;my_target_div&#039; ).play();&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Destroy===&lt;br /&gt;
&#039;&#039;&#039;this.slideToObjectAndDestroy(mobile_obj: ElementOrId, target_obj: ElementOrId, duration?: number, delay?: number): void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
This method is a handy shortcut to slide an existing HTML object to some place then destroy it upon arrival. It can be used for example to move a victory token or a card from the board to the player panel to show that the player earns it, then destroy it when we don&#039;t need to keep it visible on the player panel.&lt;br /&gt;
&lt;br /&gt;
It works the same as this.slideToObject and takes the same arguments, but it starts the animation. &lt;br /&gt;
&lt;br /&gt;
CAREFUL: Make sure nothing is creating the same object at the same time the animation is running, because this will cause some random disappearing effects&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
this.slideToObjectAndDestroy( &amp;quot;some_token&amp;quot;, &amp;quot;some_place_on_board&amp;quot;, 1000, 0 );&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.fadeOutAndDestroy( node: string | Element, duration?: number, delay?: number):&#039;&#039;&#039; &#039;&#039;&#039;void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
This function fade out the target node, then destroy it. Its starts the animation.&lt;br /&gt;
* duration/delay works exactly like in &amp;quot;slideToObject&amp;quot;&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
   this.fadeOutAndDestroy( &amp;quot;a_card_that_must_disappear&amp;quot; );&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
CAREFUL: the HTML node still exists until during few milliseconds, until the fadeOut has been completed.&lt;br /&gt;
Make sure nothing is creating same object at the same time as animation is running, because you will be some random dissapearing effects&lt;br /&gt;
&lt;br /&gt;
===Rotating elements===&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
This example combines &amp;quot;Dojo.Animation&amp;quot; method and a CSS property transform that allow you to rotate the element.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
// node is Element we rotating&lt;br /&gt;
		    var animation = new dojo.Animation({&lt;br /&gt;
			    curve: [fromDegree, toDegree],&lt;br /&gt;
			    onAnimate: (v) =&amp;gt; {&lt;br /&gt;
				    node.style.transform = &#039;rotate(&#039; + v + &#039;deg)&#039;;&lt;br /&gt;
			    } &lt;br /&gt;
		    });&lt;br /&gt;
		    &lt;br /&gt;
		    animation.play();  &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
BGA has its own interface to rotate&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.rotateTo(node: string | Element, degree: number): void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
It starts the animation, and stored the rotation degree in the class, so next time you rotate object - it is additive.&lt;br /&gt;
There is no animation hooks in this one, if you need to change any parameters use dojo animation above.&lt;br /&gt;
&lt;br /&gt;
There is also &#039;&#039;&#039;rotateInstantTo&#039;&#039;&#039; with same signature which does not animate&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Animation Callbacks===&lt;br /&gt;
&lt;br /&gt;
If you wish to run some code only after an animation has completed you can do this by linking a callback method to &#039;onEnd&#039;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
var animation_id = this.slideToObject( mobile_obj, target_obj, 500 );&lt;br /&gt;
dojo.connect(animation_id, &#039;onEnd&#039;, () =&amp;gt; {&lt;br /&gt;
   // do something here&lt;br /&gt;
});&lt;br /&gt;
animation_id.play();&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If you wish to call a second animation after the first (rather than general code) then you can use a dojo animation chain (see tutorial referenced above).&lt;br /&gt;
&lt;br /&gt;
== Players input ==&lt;br /&gt;
&lt;br /&gt;
=== Connecting ===&lt;br /&gt;
&#039;&#039;&#039;dojo.connect(element: Element, event: string, context: object, method: eventHandler): any&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;dojo.connect(element: Element, event: string, hander: eventHandler): any&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Used to associate a player event with one of your notification methods.&lt;br /&gt;
&lt;br /&gt;
Example: associate a click on an element (&amp;quot;my_element&amp;quot;) with one of our methods (&amp;quot;onClickOnMyElement&amp;quot;):&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
      dojo.connect( $(&#039;my_element&#039;), &#039;onclick&#039;, this, &#039;onClickOnMyElement&#039; );&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Same idea but base on query (i.e. all element of &#039;pet&#039; class)&lt;br /&gt;
      dojo.query(&amp;quot;.pet&amp;quot;).connect(&#039;onclick&#039;, this, &#039;onPet&#039;);&lt;br /&gt;
&lt;br /&gt;
Note: if you need to disconnect the handler you have to store handler returned from this method, i.e.&lt;br /&gt;
   &lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    var handler = dojo.connect(...);&lt;br /&gt;
    ...&lt;br /&gt;
    dojo.disconnect(handler);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If you don&#039;t store the handler - you have to destroy the object to disconnect it&lt;br /&gt;
&lt;br /&gt;
Typical function that implements the input handler will look like this&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
onPet: function(event) {&lt;br /&gt;
    var id = event.currentTarget.id;&lt;br /&gt;
    console.log(&#039;onPet &#039; + id);&lt;br /&gt;
    dojo.stopEvent(event);&lt;br /&gt;
    if (this.gamedatas.gamestate.name == &#039;playerTurnPet&#039;) {&lt;br /&gt;
          this.bgaPerformAction(&#039;actPlayPet&#039;, {card: id});&lt;br /&gt;
    } else {&lt;br /&gt;
          this.showMoveUnauthorized();&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.connect(element: ElementOrId, event: string, method: eventHandler): void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Used to associate a player event with one of your notification methods.&lt;br /&gt;
&lt;br /&gt;
      this.connect( $(&#039;my_element&#039;), &#039;onclick&#039;, &#039;onClickOnMyElement&#039; );&lt;br /&gt;
&lt;br /&gt;
Or you can use an in-place handler&lt;br /&gt;
&lt;br /&gt;
      this.connect( $(&#039;my_element&#039;), &#039;onclick&#039;, (e) =&amp;gt; { console.log(&#039;boo&#039;); } );&lt;br /&gt;
&lt;br /&gt;
Note that this function stores the connection handler. That is the only real difference between &#039;&#039;&#039;this.connect&#039;&#039;&#039; and &#039;&#039;&#039;dojo.connect&#039;&#039;&#039;. If you plan to destroy the element you connected, you &#039;&#039;&#039;must&#039;&#039;&#039; call this.disconnect() to prevent memory leaks.&lt;br /&gt;
This function is mainly for permanent objects - if you just want to connect the temp object you should probably not use this method but use dojo.connect which won&#039;t require any clean-up.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.connectClass(cssClassName: string, event: string, method: eventHandler): void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Same as connect(), but for all the nodes set with the specified cssClassName.&lt;br /&gt;
&lt;br /&gt;
	this.connectClass(&#039;pet&#039;, &#039;onclick&#039;, &#039;onPet&#039;);&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.disconnect(element: ElementOrId, event: string): void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Disconnect event handler (previously registered with this.connect or this.connectClass).&lt;br /&gt;
&lt;br /&gt;
   this.disconnect( $(&#039;my_element&#039;), &#039;onclick&#039;);&lt;br /&gt;
&lt;br /&gt;
Note: dynamic connect/disconnect is for advanced cases ONLY, you should always connect elements statically if possible, i.e. in setup() method.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.disconnectAll(): void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Disconnect all previously registed event handlers (registered via this.connect or this.connectClass)&lt;br /&gt;
&lt;br /&gt;
  this.disconnectAll();&lt;br /&gt;
&lt;br /&gt;
=== Actions ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.bgaPerformAction(action: string, args?: object, options: object = { lock: true, checkAction: true }): Promise&amp;lt;void&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Triggers an action on the backend. This is a combination of checkAction and ajaxcall, returning a Promise which resoves when ajaxcall ends.&lt;br /&gt;
&lt;br /&gt;
This method must be used to send a player input to the game server. &#039;&#039;&#039;It should not be triggered programmatically&#039;&#039;&#039;, especially not in loops, in callbacks, in notifications, or in onEnteringState/onUpdateActionButtons/onLeavingState, in order not to create race conditions or break replay game and tutorial features. It should be used only in reaction to a user action in the interface.&lt;br /&gt;
&lt;br /&gt;
* action: name of the action, as it is written in &amp;quot;possibleactions&amp;quot; of the current state.&lt;br /&gt;
* args: an object containing the call parameters to send to the action&lt;br /&gt;
* options: options to tweak the call with some defaults. Default is &amp;lt;code&amp;gt;{ lock: true, checkAction: true }&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Example of a standard call without args:&lt;br /&gt;
  this.bgaPerformAction(&#039;pass&#039;);&lt;br /&gt;
&lt;br /&gt;
Example of a standard call with action args:&lt;br /&gt;
  this.bgaPerformAction(&#039;actPlayCard&#039;, { id: this.selectedCardId });&lt;br /&gt;
&lt;br /&gt;
Example of a call without checking action (because player is inactive in a multiactive state):&lt;br /&gt;
&lt;br /&gt;
 this.bgaPerformAction(&#039;actChangeMind&#039;, {}, { checkAction: false });&lt;br /&gt;
&lt;br /&gt;
Example of a call without lock (because of a special action not directly related to the game flow):&lt;br /&gt;
&lt;br /&gt;
 this.bgaPerformAction(&#039;actSetAutoBid&#039;, { alwaysBidUntil: 500 }, { lock: false, checkAction: false });&lt;br /&gt;
&lt;br /&gt;
Example of call with reaction to exception:&lt;br /&gt;
  this.bgaPerformAction(&#039;actPlayCard&#039;, { id: this.selectedCardId }).catch(()=&amp;gt;{ this.selectedCardId = undefined; });&lt;br /&gt;
&lt;br /&gt;
Example of call with reaction to success:&lt;br /&gt;
  this.bgaPerformAction(&#039;actPlayCard&#039;, { id: this.selectedCardId }).then(()=&amp;gt;{ this.unselectAll(); });&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.ajaxcall(url, parameters, obj_callback, callback, callback_anycase?, ajax_method?: string)&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Note: bgaPerformAction is a simpler way to use ajax calls, ajaxcall stays in the doc for legacy reasons only and should not be used in new projects.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Same warning as &#039;&#039;&#039;this.bgaPerformAction&#039;&#039;&#039; about using on user action only.&lt;br /&gt;
&lt;br /&gt;
* url: the url of the action to perform. For a game, it must be: &amp;quot;/&amp;lt;mygame&amp;gt;/&amp;lt;mygame&amp;gt;/myAction.html&amp;quot;&lt;br /&gt;
* parameters: an array of parameter to send to the game server. &lt;br /&gt;
** Note that &amp;quot;lock: true&amp;quot; must always be specified in this list of parameters in order the interface can be locked during the server call. Cannot use lock: false - to not lock it has to be undefined.&lt;br /&gt;
** Note: Restricted parameter names (please don&#039;t use them):&lt;br /&gt;
*** &amp;quot;action&amp;quot;&lt;br /&gt;
*** &amp;quot;module&amp;quot;&lt;br /&gt;
*** &amp;quot;class&amp;quot;&lt;br /&gt;
* obj_callback: must be set to &amp;quot;this&amp;quot;.&lt;br /&gt;
* callback (non-optional but rarely used): a function to trigger when the server returns result and everything went fine (not used, as all data handling is done via notifications).&lt;br /&gt;
* callback_anycase: (optional) a function to trigger when the server returns ok OR error.  If no error this function is called with parameter value false. If an error occurred, the first parameter will be set to true, the second will contain the error message sent by the PHP back-end, and the third will contain an error code.&lt;br /&gt;
* ajax_method: (optional and rarely used) if you need to send large amounts of data (over 2048 bytes), you can set this parameter to &#039;post&#039; (all lower-case) to send a POST request as opposed to the default GET. This works, but was not officially documented, so only use if you really need to.&lt;br /&gt;
&lt;br /&gt;
Usage:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
this.ajaxcall( &#039;/mygame/mygame/actMyAction.html&#039;, { lock: true, &lt;br /&gt;
   arg1: myarg1, &lt;br /&gt;
   arg2: myarg2&lt;br /&gt;
}, this, (result)=&amp;gt;{} );&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.checkAction(action: string, nomessage?: boolean): boolean &#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Check if player can do the specified action by taking into account:&lt;br /&gt;
* if interface is locked it will return false and show message &amp;quot;An action is already in progress&amp;quot;,  unless nomessage set to true &lt;br /&gt;
* if player is not active it will return false and show message &amp;quot;This is not your turn&amp;quot;, unless nomessage set to true &lt;br /&gt;
* if action is not in list in possible actions (defined by &amp;quot;possibleaction&amp;quot; in current game state) it will return false and show &amp;quot;This move is not authorized now&amp;quot; error (unconditionally).&lt;br /&gt;
* otherwise returns true&lt;br /&gt;
Example:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  function onClickOnGameElement( evt )  {&lt;br /&gt;
     if( this.checkAction( &amp;quot;actMyAction&amp;quot; ) ) {&lt;br /&gt;
        // Do the action&lt;br /&gt;
     }&lt;br /&gt;
  }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.checkPossibleActions(action: string): boolean&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
* this is independent of the player being active, so can be used instead of this.checkAction(). This is particularly useful for multiplayer states when the player is not active in a &#039;player may like to change their mind&#039; scenario. Unlike this.checkAction, this function does NOT take interface locking into account &lt;br /&gt;
&lt;br /&gt;
* if action is not in list in possible actions (defined by &amp;quot;possibleaction&amp;quot; in current game state) it will return false and show &amp;quot;This move is not authorized now&amp;quot; error (unconditionally).&lt;br /&gt;
* otherwise returns true&lt;br /&gt;
&lt;br /&gt;
  function onChangeMyMind( evt )  {&lt;br /&gt;
     if( this.checkPossibleActions( &amp;quot;actMyAction&amp;quot; ) ) {&lt;br /&gt;
        // Do the action&lt;br /&gt;
     }&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.checkLock(nomessage?: boolean): boolean&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
When using &amp;quot;lock: true&amp;quot; in ajax call you can use this function to check if interface is in lock state (it will be locked during server call and notification processing).&lt;br /&gt;
This check can be used to block some other interactions which do not result in ajaxcall or if you want to suppress errors. Note: normally you only need to use this.checkAction(...), this is for advanced cases.&lt;br /&gt;
&lt;br /&gt;
It will also show error unless nomessage is set to true&lt;br /&gt;
&lt;br /&gt;
  function onChangeMyMind( evt )  {&lt;br /&gt;
     if( this.checkLock() ) {&lt;br /&gt;
        // Do the action&lt;br /&gt;
     }&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
== Notifications ==&lt;br /&gt;
&lt;br /&gt;
When something happens on the server side, your game interface Javascript logic received a notification.&lt;br /&gt;
If you have not done so yet check what notification are in [[Main_game_logic:_yourgamename.game.php#Notifications]]&lt;br /&gt;
&lt;br /&gt;
Here&#039;s how you can handle these notifications on the client side.&lt;br /&gt;
&lt;br /&gt;
=== Subscribe to notifications ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;dojo.subscribe(notif_type: string, callback_obj: Object, handler: string|handler)&#039;&#039;&#039;&lt;br /&gt;
* notif_type - notification type/name send by php server&lt;br /&gt;
* callback_obj - usually this&lt;br /&gt;
* handler - if string method of callback_obj with name name is called, when notification is called, with notification object as parameter (see below)&lt;br /&gt;
&lt;br /&gt;
Your Javascript &amp;quot;setupNotifications&amp;quot; method is the place where you can subscribe to notifications from your PHP code.&lt;br /&gt;
&lt;br /&gt;
Here&#039;s how you associate one of your Javascript method to a notification &amp;quot;playDisc&amp;quot; (from Reversi example):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
   setupNotifications: function() {&lt;br /&gt;
      ...&lt;br /&gt;
      dojo.subscribe(&#039;playDisc&#039;, this, &amp;quot;notif_playDisc&amp;quot;);&lt;br /&gt;
   },&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note: the &amp;quot;playDisc&amp;quot; corresponds to the name of the notification you define it in your PHP code, in your &amp;quot;notifyAllPlayers&amp;quot; or &amp;quot;notifyPlayer&amp;quot; method.&lt;br /&gt;
&lt;br /&gt;
Then, you have to define your &amp;quot;notif_playDisc&amp;quot; method:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
   notif_playDisc: function(notif) {&lt;br /&gt;
     // Remove current possible moves (makes the board more clear)&lt;br /&gt;
     dojo.query( &#039;.possibleMove&#039; ).removeClass( &#039;possibleMove&#039; );          &lt;br /&gt;
     this.addDiscOnBoard( notif.args.x, notif.args.y, notif.args.player_id );&lt;br /&gt;
   },&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In a notification handler like our &amp;quot;notif_playDisc&amp;quot; method, you can access all notifications arguments with &amp;quot;notif.args&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&lt;br /&gt;
PHP&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    $this-&amp;gt;notifyAllPlayers( &amp;quot;apples&amp;quot;, clienttranslate(&#039;player takes ${count} apples&#039;), [ &amp;quot;count&amp;quot; =&amp;gt; 3 ] );&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
JavaScript&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    setupNotifications: function() {&lt;br /&gt;
       dojo.subscribe( &#039;apples&#039;, this, &#039;notif_apples&#039; );&lt;br /&gt;
    },&lt;br /&gt;
&lt;br /&gt;
    notif_apples: function(notif) {&lt;br /&gt;
      //You can access the &amp;quot;count&amp;quot; like this:&lt;br /&gt;
       alert(&amp;quot;count = &amp;quot; + notif.args.count);&lt;br /&gt;
    }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== The notification Object received by client ===&lt;br /&gt;
&lt;br /&gt;
When sending a notification on your PHP, the client side will receive an Object with the following attributes:&lt;br /&gt;
&lt;br /&gt;
* type - type of the notification (as passed by php function)&lt;br /&gt;
* log - the log string passed from php notification&lt;br /&gt;
* args - This is the arguments that you passed on your notification method on php&lt;br /&gt;
* bIsTableMsg - is true when you use [[Main_game_logic:_yourgamename.game.php#NotifyAllPlayers|NotifyAllPlayers]] method (false otherwise)&lt;br /&gt;
* channelorig - information about table ID (formatted as : &amp;quot;/table/t[TABLE_NUMBER]&amp;quot;)&lt;br /&gt;
* gamenameorig - name of the game&lt;br /&gt;
* move_id - ID of the move associated with the notification&lt;br /&gt;
* table_id - ID of the table (comes as string)&lt;br /&gt;
* time - UNIX GMT timestamp&lt;br /&gt;
* uid - unique identifier of the notification&lt;br /&gt;
* h - unknown&lt;br /&gt;
&lt;br /&gt;
&#039;&#039; Note that those information were inferred from observation on console log. If an Admin can confirm/correct (and remove this line), you&#039;re welcome :)&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
=== Ignoring notifications ===&lt;br /&gt;
&lt;br /&gt;
Sometimes you need to ignore some notification on client side. You don&#039;t want them to be shown in game log and you don&#039;t want them to be handled.&lt;br /&gt;
&lt;br /&gt;
The most common use case is when a player gets private information. They will receive a specific notification (such as &amp;quot;You received Ace of Heart&amp;quot;), while other players would receive more generic notification (&amp;quot;Player received a card&amp;quot;).&lt;br /&gt;
&lt;br /&gt;
In X.game.php&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        $this-&amp;gt;notifyAllPlayers(&amp;quot;dealCard&amp;quot;, clienttranslate(&#039;${player_name} received a card&#039;), [&lt;br /&gt;
            &#039;player_id&#039; =&amp;gt; $playerId,&lt;br /&gt;
            &#039;player_name&#039; =&amp;gt; $this-&amp;gt;getActivePlayerName()&lt;br /&gt;
        ]);&lt;br /&gt;
&lt;br /&gt;
        $this-&amp;gt;notifyPlayer($playerId, &amp;quot;dealCardPrivate&amp;quot;, clienttranslate(&#039;You received ${cardName}&#039;), [&lt;br /&gt;
            &amp;quot;type&amp;quot; =&amp;gt; $card[&amp;quot;type&amp;quot;],&lt;br /&gt;
            &amp;quot;cardName&amp;quot; =&amp;gt; $this-&amp;gt;getCardName($card[&amp;quot;type&amp;quot;])&lt;br /&gt;
        ]);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The problem with this approach is that the active player will receive two notifications:&lt;br /&gt;
* Player1 received a card&lt;br /&gt;
* You received Ace of Hearts&lt;br /&gt;
&lt;br /&gt;
Hence, notification ignoring.&lt;br /&gt;
&lt;br /&gt;
NOTE: You can think that it would be possible to send such notification to all players except active just by using notifyPlayer and it seems to work. The problem however is that table spectators would miss such notification and their user interface (and game log) wouldn&#039;t be updated. Since there is no way to send notification just to spectators, ignoring the notification (or &amp;quot;filtering&amp;quot;) is the only reasonable solution.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;setIgnoreNotificationCheck(notif_type: string, predicate: ((notif: Notif)=&amp;gt;boolean))&#039;&#039;&#039;&lt;br /&gt;
This method will set a check whether any of notifications of specific type should be ignored.&lt;br /&gt;
&lt;br /&gt;
The parameters are:&lt;br /&gt;
* notif_type: type of the notification &lt;br /&gt;
* predicate (notif =&amp;gt; boolean): a function that will receive notif object and will return true if this specific notification should be ignored&lt;br /&gt;
&lt;br /&gt;
Before dispatching any notification of this type, the framework will call predicate to check whether notification should be ignored, if it return true - the notification will be dispatched, i.e. logged or handled.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    this.notifqueue.setIgnoreNotificationCheck( &#039;dealCard&#039;, (notif) =&amp;gt; (notif.args.player_id == this.player_id) );&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
IMPORTANT: Remember that this notification is ignored on the client side, but was still received by the client. Therefore it shouldn&#039;t contain any private information as cheaters can get it. In other words this is not a way to hide information.&lt;br /&gt;
&lt;br /&gt;
IMPORTANT: When a game is reloaded with F5 or when opening a turn based game, old notifications are replayed as history notification. They are used just to update the game log and are stripped of all arguments except player_id, i18n and any argument present in message. If you use and other argument in your predicate you should &#039;&#039;&#039;preserve&#039;&#039;&#039; it as explained [[Main_game_logic:_yourgamename.game.php#Notify_players|here]].&lt;br /&gt;
&lt;br /&gt;
=== Synchronous notifications ===&lt;br /&gt;
&lt;br /&gt;
When several notifications are received by your game interface, these notifications are processed immediately, one after the other, in the same exact order they have been generated in your PHP game logic.&lt;br /&gt;
&lt;br /&gt;
However, sometimes, you need to give some time to the players to figure out what happened on the game before jumping to the next notification. Indeed, in many games, there are a lot of automatic actions, and the computer is going to resolve all these actions very fast if you don&#039;t tell it not to do so.&lt;br /&gt;
&lt;br /&gt;
As an example, for Reversi, when someone is playing a disc, we want to wait 500 milliseconds before doing anything else in order the opponent player can figure out what move has been played.&lt;br /&gt;
&lt;br /&gt;
Here&#039;s how we do this, right after our subscription:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    dojo.subscribe( &#039;playDisc&#039;, this, &amp;quot;notif_playDisc&amp;quot; );&lt;br /&gt;
    this.notifqueue.setSynchronous( &#039;playDisc&#039;, 500 );   // Wait 500 milliseconds after executing the playDisc handler&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
-----&lt;br /&gt;
&lt;br /&gt;
It is also possible to control the delay timing dynamically (e.g., using notification args). As an example, maybe your notification &#039;cardPlayed&#039; should pause for a different amount of time depending on the number or type of cards played.&lt;br /&gt;
&lt;br /&gt;
For this case, use &#039;&#039;&#039;setSynchronous&#039;&#039;&#039; without specifying the duration and use &#039;&#039;&#039;setSynchronousDuration&#039;&#039;&#039; within the notification callback.&lt;br /&gt;
&lt;br /&gt;
* NOTE: If you forget to invoke &#039;&#039;&#039;setSynchronousDuration&#039;&#039;&#039;, the game will remain paused forever!&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
setupNotifications: function () {&lt;br /&gt;
    dojo.subscribe( &#039;cardPlayed&#039;, this, &#039;notif_cardPlayed&#039; );&lt;br /&gt;
    this.notifqueue.setSynchronous( &#039;cardPlayed&#039; ); // wait time is dynamic&lt;br /&gt;
    ...&lt;br /&gt;
},&lt;br /&gt;
&lt;br /&gt;
notif_cardPlayed: function (notif) {&lt;br /&gt;
    // MUST call setSynchronousDuration&lt;br /&gt;
&lt;br /&gt;
    // Example 1: From notification args (PHP)&lt;br /&gt;
    this.notifqueue.setSynchronousDuration(notif.args.duration);&lt;br /&gt;
    ...&lt;br /&gt;
&lt;br /&gt;
    // Or, example 2: Match the duration to a Dojo animation&lt;br /&gt;
    var anim = dojo.fx.combine([&lt;br /&gt;
        ...&lt;br /&gt;
    ]);&lt;br /&gt;
    anim.play();&lt;br /&gt;
    this.notifqueue.setSynchronousDuration(anim.duration);&lt;br /&gt;
},&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You can also manually call this.notifqueue.setSynchronousDuration(0) once client operations are finished, but be careful that even fast replay still has a path to call it.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;WARNING: combining synchronous and ignored notifications&#039;&#039;&#039;&lt;br /&gt;
You must be careful when combining dynamic synchronous durations (as described above) with ignored notifications. If you have a conditionally ignored notification like this (see below section):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;this.notifqueue.setIgnoreNotificationCheck( &#039;myNotif&#039;, (notif) =&amp;gt; (notif.args.player_id == this.player_id) /* or any other condition */ )&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
then you CANNOT do&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;this.notifqueue.setSynchronous(&#039;myNotif&#039;);&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
as, when the ignored check passes, the notification handler, in which `this.notifqueue.setSychronousDuration` is called, is never called and so the duration is never set and interface locking results.&lt;br /&gt;
&lt;br /&gt;
The workaround is to set a &amp;quot;dummy&amp;quot; time:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;this.notifqueue.setSynchronous(&#039;myNotif&#039;, 5000);&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
whose value is irrelevant but must be large enough to cover the time before the notification handler is called. The large value never actually comes into play because the notification is either ignored, or the synchronous duration is reset to a sensible value inside the handler.&lt;br /&gt;
&lt;br /&gt;
=== Pre-defined notification types ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;tableWindow&#039;&#039;&#039; - This defines notification to display [[Game_interface_logic:_yourgamename.js#Scoring_dialogs|Scoring Dialogs]], see below.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;message&#039;&#039;&#039; - This defines notification that shows on players log and have no other effect (technically any unhandled notification will do the same but its recommended to use this keyword for consistency)&lt;br /&gt;
&lt;br /&gt;
   // You can call this on php side without doing anything on client side&lt;br /&gt;
    self::notifyAllPlayers( &#039;message&#039;, clienttranslate(&#039;hello&#039;), [] );&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;simplePause&#039;&#039;&#039; - This notification will just delay other notifications, maybe useful if you know you need some extra time for animation or something. Requires a time parameter.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    self::notifyAllPlayers( &#039;simplePause&#039;, &#039;&#039;, [ &#039;time&#039; =&amp;gt; 500] ); // time is in milliseconds&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note: the following types are RESERVED by framework, do not use:&lt;br /&gt;
&lt;br /&gt;
gameStateChange gameStateChangePrivateArg gameStateMultipleActiveUpdate newActivePlayer playerstatus yourturnack clockalert tableInfosChanged playerEliminated tableDecision  archivewaitingdelay end_archivewaitingdelay replaywaitingdelay end_replaywaitingdelay replayinitialwaitingdelay end_replayinitialwaitingdelay aiPlayerWaitingDelay replay_has_ended updateSpectatorList  wouldlikethink updateReflexionTime undoRestorePoint resetInterfaceWithAllDatas zombieModeFail zombieModeFailWarning aiError skipTurnOfPlayer zombieBack allPlayersAreZombie gameResultNeutralized playerConcedeGame showTutorial showCursor showCursorClick skipTurnOfPlayerWarning  banFromTable resultsAvailable switchToTurnbased newPrivateState infomsg&lt;br /&gt;
&lt;br /&gt;
== Tooltips ==&lt;br /&gt;
&lt;br /&gt;
=== Adding static tooltips ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.addTooltip(nodeId: string, helpStringTranslated: string, actionStringTranslated: string, delay?: number): void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Add a simple text tooltip to the DOM node.&lt;br /&gt;
&lt;br /&gt;
Specify &#039;helpStringTranslated&#039; to display some information about &amp;quot;what is this game element?&amp;quot;.&lt;br /&gt;
Specify &#039;actionStringTranslated&#039; to display some information about &amp;quot;what happens when I click on this element?&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
You must specify both of the strings. You can only use one and specify an empty string (&#039;&#039;) for the other one.&lt;br /&gt;
&lt;br /&gt;
When you pass text directly function _() must be used for the text to be marked for translation! Except for empty string.&lt;br /&gt;
&lt;br /&gt;
Parameter &amp;quot;delay&amp;quot; is optional. It is primarily used to specify a zero delay for some game element when the tooltip gives really important information for the game - but remember: no essential information must be placed in tooltips as they won&#039;t be displayed in some browsers (see [[BGA_Studio_Guidelines|Guidelines]]).&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
   this.addTooltip( &#039;cardcount&#039;, _(&#039;Number of cards in hand&#039;), &#039;&#039; );&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note: this generates static tooltip and attaches to existing dom element, if you need to generate tooltip more dynamically you have to call that method every time information about object is updated or use completely different tehnique, see dynamic tooltips below.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.addTooltipHtml(nodeId: string, html: string, delay?: number): void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Add an HTML tooltip to the DOM node (for more elaborate content such as presenting a bigger version of a card).&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.addTooltipToClass(cssClass: string, helpStringTranslated: string, actionStringTranslated: string, delay?: number ): void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Add a simple text tooltip to all the DOM nodes set with this cssClass. See more details above for this.addTooltip.&lt;br /&gt;
     this.addTooltipToClass( &#039;meeple&#039;, _(&#039;This is A Meeple&#039;), _(&#039;Click to tickle&#039;) );&lt;br /&gt;
&lt;br /&gt;
IMPORTANT: all concerned nodes must exist and have IDs to get tooltips.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.addTooltipHtmlToClass(cssClass: string, html: string, delay?: number): void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Add an HTML tooltip to to all the DOM nodes set with this cssClass (for more elaborate content such as presenting a bigger version of a card).&lt;br /&gt;
&lt;br /&gt;
IMPORTANT: all concerned nodes must exist and have IDs to get tooltips.&lt;br /&gt;
&lt;br /&gt;
=== Removing static tooltips ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.removeTooltip(nodeId: string): void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Remove a tooltip from the DOM node with given id.&lt;br /&gt;
&lt;br /&gt;
=== Advanced tooltips ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;force tooltip to open&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
If you want to force tooltip to open in reaction to some other action, i.e. click you can do this&lt;br /&gt;
&lt;br /&gt;
   this.tooltips[id].open(id)&lt;br /&gt;
&lt;br /&gt;
where id is the id of the tooltip node where tooltip was installed.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;dynamic tooltips&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
See [[BGA_Studio_Cookbook#Dynamic_tooltips]]&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;tooltips on mobile&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Tooltips is very unreliable on mobile, it is recommended to implement some other method to obtaining same information,&lt;br /&gt;
such as simple click handler in dedicated &amp;quot;Help&amp;quot; mode or provide dedicated clickable areas such as corner of card.&lt;br /&gt;
&lt;br /&gt;
== Warning messages ==&lt;br /&gt;
&lt;br /&gt;
Sometimes, there is something important that is happening in the game and you have to make sure all players get the message. Most of the time, the evolution of the game situation or the game log is enough, but sometimes you need something more visible.&lt;br /&gt;
&lt;br /&gt;
Ex: someone fulfills one of the end of the game conditions, so this is the last turn.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.showMessage(msg: string, type: string): void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
showMessage shows a message in a big rectangular area on the top of the screen of the current player, and it dissapears after few seconds (also it will be in the log in some cases).&lt;br /&gt;
&lt;br /&gt;
* &amp;quot;msg&amp;quot; is the string to display. It should be translated.&lt;br /&gt;
* &amp;quot;type&amp;quot; can be set to &amp;quot;info&amp;quot;, &amp;quot;error&amp;quot;, &amp;quot;only_to_log&amp;quot; or custom string. If set to &amp;quot;info&amp;quot;, the message will be an informative message on a white background. If set to &amp;quot;error&amp;quot;, the message will be an error message on a red background and it will be added to log. If set to &amp;quot;only_to_log&amp;quot;, the message will be added to the game log but will not popup at the top of the screen.&lt;br /&gt;
If set to custom string, it will be transparent, to use custom type define &amp;quot;head_xxx&amp;quot; in css, where xxx is the type. For example if you want yellow warning, use &amp;quot;warning&amp;quot; as type and add this to css:&lt;br /&gt;
 .head_warning {&lt;br /&gt;
    background-color: #e6c66e;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
Important: the normal way to inform players about the progression of the game is the game log. The &amp;quot;showMessage&amp;quot; is intrusive and should not be used often.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    notif_messageinfo: function(notif) {&lt;br /&gt;
	if (!g_archive_mode) {&lt;br /&gt;
        	var message = this.format_string_recursive(notif.log, notif.args);&lt;br /&gt;
		this.showMessage(_(&#039;Announcement:&#039;) + &amp;quot; &amp;quot; + message, &#039;info&#039;);		&lt;br /&gt;
         }&lt;br /&gt;
    },&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Show message could be used on the client side to prevent user wrong moves before it is send to server.&lt;br /&gt;
Example from &#039;battleship&#039;:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
onGrid: function(event) {&lt;br /&gt;
     if (checkIfPlayerTriesToFireOnThemselves(event)) {&lt;br /&gt;
        this.showMessage(_(&#039;This is your own board silly!&#039;), &#039;error&#039;);&lt;br /&gt;
        return;&lt;br /&gt;
     }&lt;br /&gt;
     ...&lt;br /&gt;
},&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.showMoveUnauthorized(): void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Shows predefined user error that move is unauthorized now&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
onPet: function(event) {&lt;br /&gt;
     if (checkPet(event)==false) {&lt;br /&gt;
        this.showMoveUnauthorized();&lt;br /&gt;
        return;&lt;br /&gt;
     }&lt;br /&gt;
     ...&lt;br /&gt;
},&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Dialogs ==&lt;br /&gt;
&lt;br /&gt;
=== Confirmation dialog ===&lt;br /&gt;
&lt;br /&gt;
When an important action with a lot of consequences is triggered by the player, you may want to propose a confirmation dialog.&lt;br /&gt;
&lt;br /&gt;
CAREFUL: the general guideline of BGA is to AVOID the use of confirmation dialogs. Confirmation dialogs slow down the game and bother players. The players know that they have to pay attention to each move when they are playing online.&lt;br /&gt;
&lt;br /&gt;
The situations where you should use a confirmation dialog are the following:&lt;br /&gt;
* It must not happen very often during a game.&lt;br /&gt;
* It must be linked to an action that can really &amp;quot;kill a game&amp;quot; if the player does not pay attention.&lt;br /&gt;
* It must be something that can be done by mistake (ex: a link on the action status bar).&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.confirmationDialog(message: string, yesHandler: (param: any) =&amp;gt; void, noHandler?: (param: any) =&amp;gt; void, param?: any): void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
* message - message will be shown to user, use _() to translate&lt;br /&gt;
* yesHandler - non-optional handler to be called on yes&lt;br /&gt;
* noHandler - optional handler to called on no&lt;br /&gt;
* param - if specified, it will be passed to both handlers&lt;br /&gt;
NOTE: this is async function, it does not return anything and you should not do anything after, you must do everything in handlers&lt;br /&gt;
&lt;br /&gt;
How to display a confirmation dialog:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    this.confirmationDialog(_(&amp;quot;Are you sure you want to bake a pie?&amp;quot;), () =&amp;gt; {&lt;br /&gt;
      this.bakeThePie();&lt;br /&gt;
    });&lt;br /&gt;
    return; // nothing should be called or done after calling this, all action must be done in the handler&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
With param and both handlers&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    this.confirmationDialog(_(&amp;quot;Are you sure you want to bake a pie?&amp;quot;), &lt;br /&gt;
           (ingredient) =&amp;gt; this.bakeThePie(ingredient), &lt;br /&gt;
           (ingredient) =&amp;gt; console.log(`cancelled baking of ${ingredient}`), &lt;br /&gt;
           &#039;apple&#039;);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Multiple choice dialog ===&lt;br /&gt;
&lt;br /&gt;
You can use this dialog to give user a choice with small amount of options&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.multipleChoiceDialog(message: string, choices: string[], callback: (choice: number) =&amp;gt; void): void&#039;&#039;&#039;&lt;br /&gt;
* message - message will be shown to user, use _() to translate&lt;br /&gt;
* choices - array of choices&lt;br /&gt;
* callback - non-optional handler to be called on choice made, the choice parameter is the INDEX of the choice from the array of choices&lt;br /&gt;
&lt;br /&gt;
NOTE: this is async function, it does not return anything and you should not do anything after, you must do everything in handlers&lt;br /&gt;
NOTE: there is no cancel handler, so make sure you gave user a choice to get out of it&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    const keys = [&amp;quot;0&amp;quot;, &amp;quot;1&amp;quot;, &amp;quot;5&amp;quot;, &amp;quot;10&amp;quot;];&lt;br /&gt;
    this.multipleChoiceDialog(_(&amp;quot;How many bugs to fix?&amp;quot;), keys, (choice) =&amp;gt; {&lt;br /&gt;
      if (choice==0) return; // cancel operation, do not call server action&lt;br /&gt;
      var bugchoice = keys[choice]; // choice will be 0,1,2,3 here&lt;br /&gt;
      this.bgaPerformAction(&amp;quot;fixBugs&amp;quot;, { number: bugchoice });&lt;br /&gt;
    });&lt;br /&gt;
    return; // must return here&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Generic Dialogs ===&lt;br /&gt;
&lt;br /&gt;
As a general rule, you shouldn&#039;t use dialogs windows.&lt;br /&gt;
&lt;br /&gt;
BGA guidelines specify that all game elements should be displayed on the main screen. Players can eventually scroll down to see game elements they don&#039;t need to see anytime, and you may eventually create anchors to move between game area section. Of course dialogs windows are very practical, but the thing is: all players know how to scroll down, and not all players know how to show up your dialog window. In addition, when the dialog shows up, players can&#039;t access the other game components.&lt;br /&gt;
&lt;br /&gt;
Sometimes although, you need to display a dialog window. Here is how you do this:&lt;br /&gt;
&lt;br /&gt;
  // Create the new dialog over the play zone. You should store the handler in a member variable to access it later&lt;br /&gt;
  this.myDlg = new ebg.popindialog();&lt;br /&gt;
  this.myDlg.create( &#039;myDialogUniqueId&#039; );&lt;br /&gt;
  this.myDlg.setTitle( _(&amp;quot;my dialog title to translate&amp;quot;) );&lt;br /&gt;
  this.myDlg.setMaxWidth( 500 ); // Optional&lt;br /&gt;
  &lt;br /&gt;
  // Create the HTML of my dialog. &lt;br /&gt;
  // The best practice here is to use [[Game_layout:_view_and_template:_yourgamename.view.php_and_yourgamename_yourgamename.tpl#Javascript_templates|Javascript templates]]&lt;br /&gt;
  var html = this.format_block( &#039;jstpl_myDialogTemplate&#039;, { &lt;br /&gt;
                arg1: myArg1,&lt;br /&gt;
                arg2: myArg2,&lt;br /&gt;
                ...&lt;br /&gt;
            } );  &lt;br /&gt;
  &lt;br /&gt;
  // Show the dialog&lt;br /&gt;
  this.myDlg.setContent( html ); // Must be set before calling show() so that the size of the content is defined before positioning the dialog&lt;br /&gt;
  this.myDlg.show();&lt;br /&gt;
  &lt;br /&gt;
  // Now that the dialog has been displayed, you can connect your method to some dialog elements&lt;br /&gt;
  // Example, if you have an &amp;quot;OK&amp;quot; button in the HTML of your dialog:&lt;br /&gt;
  dojo.connect($(&#039;my_ok_button&#039;), &#039;onclick&#039;, this, (event) =&amp;gt; {&lt;br /&gt;
                event.preventDefault();&lt;br /&gt;
                this.myDlg.destroy();&lt;br /&gt;
            });&lt;br /&gt;
&lt;br /&gt;
If necessary, you can remove the default top right corner &#039;close&#039; icon, or replace the function called when it is clicked:&lt;br /&gt;
  // Removes the default close icon&lt;br /&gt;
  this.myDlg.hideCloseIcon();&lt;br /&gt;
&lt;br /&gt;
  // Replace the function call when it&#039;s clicked&lt;br /&gt;
  this.myDlg.replaceCloseCallback((event) =&amp;gt; { ... });&lt;br /&gt;
&lt;br /&gt;
=== Scoring dialogs ===&lt;br /&gt;
&lt;br /&gt;
Sometimes at the end of a round you want to display a big table that details the points wins in each section of the game.&lt;br /&gt;
&lt;br /&gt;
Example: in Hearts game, we display at the end of each round the number of &amp;quot;heart&amp;quot; cards collected by each player, the player who collected the Queen of Spades, and the total number of points loose by each player.&lt;br /&gt;
&lt;br /&gt;
Scoring dialogs are managed entirely on &#039;&#039;&#039;PHP side&#039;&#039;&#039;, but they are described here as their effects are visible only on client side.&lt;br /&gt;
&lt;br /&gt;
Displaying a scoring dialog is quite simple and is using a special notification type: &amp;quot;tableWindow&amp;quot;:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  // on PHP side:&lt;br /&gt;
  $this-&amp;gt;notifyAllPlayers( &amp;quot;tableWindow&amp;quot;, &#039;&#039;, array(&lt;br /&gt;
            &amp;quot;id&amp;quot; =&amp;gt; &#039;finalScoring&#039;,&lt;br /&gt;
            &amp;quot;title&amp;quot; =&amp;gt; clienttranslate(&amp;quot;Title of the scoring dialog&amp;quot;),&lt;br /&gt;
            &amp;quot;table&amp;quot; =&amp;gt; $table&lt;br /&gt;
        )); &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The &amp;quot;table&amp;quot; argument is a 2 dimensional PHP array that describes the table you want to display, line by line and column by column.&lt;br /&gt;
&lt;br /&gt;
Example: display an 3x3 array of strings&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
   $table = [&lt;br /&gt;
      [ &amp;quot;one&amp;quot;, &amp;quot;two&amp;quot;, &amp;quot;three&amp;quot; ],    // This is my first line&lt;br /&gt;
      [ &amp;quot;four&amp;quot;, &amp;quot;five&amp;quot;, &amp;quot;six&amp;quot; ],    // This is my second line&lt;br /&gt;
      [ &amp;quot;seven&amp;quot;, &amp;quot;height&amp;quot;, &amp;quot;nine&amp;quot; ]    // This is my third line&lt;br /&gt;
   ];&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
As you can see above, in each &amp;quot;cell&amp;quot; of your array you can display a simple string value. But you can also display a complex value with a template and associated arguments like this:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
   $table = [&lt;br /&gt;
      [ &amp;quot;one&amp;quot;, &amp;quot;two&amp;quot;, [ &amp;quot;str&amp;quot; =&amp;gt; clienttranslate(&amp;quot;a string with an ${argument}&amp;quot;), &amp;quot;args&amp;quot; =&amp;gt; [ &#039;argument&#039; =&amp;gt; &#039;argument_value&#039; ] ] ],&lt;br /&gt;
      [ &amp;quot;four&amp;quot;, &amp;quot;five&amp;quot;, &amp;quot;six&amp;quot; ], &lt;br /&gt;
      [ &amp;quot;seven&amp;quot;, &amp;quot;height&amp;quot;, &amp;quot;nine&amp;quot; ]&lt;br /&gt;
   ];&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This is especially useful when you want to display player names with colors. Example from &amp;quot;Hearts&amp;quot;:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        $firstRow = [ &#039;&#039; ];&lt;br /&gt;
        foreach( $players as $player_id =&amp;gt; $player )    {&lt;br /&gt;
            $cell = [ &#039;str&#039; =&amp;gt; &#039;${player_name}&#039;,&lt;br /&gt;
                      &#039;args&#039; =&amp;gt; [ &#039;player_name&#039; =&amp;gt; $player[&#039;player_name&#039;] ],&lt;br /&gt;
                      &#039;type&#039; =&amp;gt; &#039;header&#039;&lt;br /&gt;
                    ];&lt;br /&gt;
            $firstRow[] = $cell;&lt;br /&gt;
        }&lt;br /&gt;
        $table[] = $firstRow;&lt;br /&gt;
        ...&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You can also use three extra attributes in the parameter array for the notification:&lt;br /&gt;
* &#039;&#039;&#039;header&#039;&#039;&#039;: the content for this parameter displays before the table (also, the html will be parsed and player names will be colored according to the current game colors). &lt;br /&gt;
* &#039;&#039;&#039;footer&#039;&#039;&#039;: the content for this parameter displays after the table (no parsing for coloring the player names)&lt;br /&gt;
* &#039;&#039;&#039;closing&#039;&#039;&#039;: if this parameter is used, a button will be displayed with this label at the bottom of the popup and will allow players to close it (more easily than by clicking the top right &#039;cross&#039; icon).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
   $this-&amp;gt;notifyAllPlayers( &amp;quot;tableWindow&amp;quot;, &#039;&#039;, [&lt;br /&gt;
            &amp;quot;id&amp;quot; =&amp;gt; &#039;finalScoring&#039;,&lt;br /&gt;
            &amp;quot;title&amp;quot; =&amp;gt; clienttranslate(&amp;quot;Title of the scoring dialog&amp;quot;),&lt;br /&gt;
            &amp;quot;table&amp;quot; =&amp;gt; $table,&lt;br /&gt;
            &amp;quot;header&amp;quot; =&amp;gt; [&#039;str&#039; =&amp;gt; clienttranslate(&#039;Table header with parameter ${number}&#039;),&lt;br /&gt;
                                 &#039;args&#039; =&amp;gt; [ &#039;number&#039; =&amp;gt; 3 ],&lt;br /&gt;
                               ],&lt;br /&gt;
            &amp;quot;footer&amp;quot; =&amp;gt; &#039;&amp;lt;div class=&amp;quot;myfoot&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&#039;,&lt;br /&gt;
            &amp;quot;closing&amp;quot; =&amp;gt; clienttranslate( &amp;quot;Closing button label&amp;quot; )&lt;br /&gt;
        ] ); &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note: currently id is not used - so you cannot access resulting div by id on js side&lt;br /&gt;
Note: any traslatable stirng have to be wrapped by clienttranslate() on top level OR it has to be recursive template. &lt;br /&gt;
&lt;br /&gt;
DO NOT DO THIS: &lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
   &amp;quot;footer&amp;quot; =&amp;gt; &#039;&amp;lt;div&amp;gt;&#039;.clienttranslate( &amp;quot;The end&amp;quot; ).&#039;&amp;lt;/div&amp;gt;&#039;, // this will not work for translations!!!&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Scoring animated display ===&lt;br /&gt;
&lt;br /&gt;
Sometimes, you may want to display a score value over an element to make the scoring easier to follow for the players (Terra Mystica final scoring for example).&lt;br /&gt;
You can do it with:&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.displayScoring(anchor_id: string, color: string, score: number | string, duration?: number, offset_x?: number, offset_y?: number): void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;anchor_id&#039;&#039;&#039;: ID of the html element to place the animated score onto (without the &#039;#&#039;) &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;color&#039;&#039;&#039;: hexadecimal RGB representation of the color (should be the color of the scoring player), but without a leading &#039;#&#039;.  For instance, &#039;ff0000&#039; for red.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;score&#039;&#039;&#039;: numeric score to display, prefixed by a &#039;+&#039; or &#039;-&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;duration&#039;&#039;&#039;: animation duration in milliseconds (optional, default is 1000)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;offset_x&#039;&#039;&#039; and &#039;&#039;&#039;offset_y&#039;&#039;&#039;: if both offset_x and offset_y are defined and not null, apply the following offset (in pixels) to the scoring animation. &lt;br /&gt;
Note that the score is centered in the anchor, so the offsets might have to be negative if you calculate the position.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Note: if you want to display successively each score, you can use &#039;&#039;this.notifqueue.setSynchronous()&#039;&#039; function.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    setupNotifications: function()   {&lt;br /&gt;
           dojo.subscribe( &#039;displayScoring&#039;, this, &amp;quot;notif_displayScoring&amp;quot; );&lt;br /&gt;
           ...&lt;br /&gt;
    }&lt;br /&gt;
...&lt;br /&gt;
&lt;br /&gt;
    notif_displayScoring: function(notif) {&lt;br /&gt;
            const duration = notif.args.duration?notif.args.duration:1000;&lt;br /&gt;
            this.notifqueue.setSynchronous(&#039;displayScoring&#039;, duration );&lt;br /&gt;
	    this.displayScoring( notif.args.target, notif.args.color, notif.args.score, duration);&lt;br /&gt;
    },&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Speech bubble ===&lt;br /&gt;
&lt;br /&gt;
For better interactivity in some games (Love Letter for example), you may use comic book style speech bubbles to express the players voices.&lt;br /&gt;
This is done with showBubble:&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.showBubble(anchor_id: string, text: string, delay?: number, duration?: number, custom_class?: string): void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
* anchor_id - where to attach the bubble&lt;br /&gt;
* text - what to put in bubble, can be html&lt;br /&gt;
* delay - delay in milliseconds (optional, default 0)&lt;br /&gt;
* duration -  duration of animation in milliseconds (optional, default 3000)&lt;br /&gt;
* custom_class - extra class to add to bubble (optional), if you need to override the default bubble style&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
   this.showBubble(&#039;meeple_2&#039;, _(&#039;Hello&#039;), 0, 1000, &#039;pink_bubble&#039;);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  notif_speechBubble(notif) {&lt;br /&gt;
    var html = this.format_string_recursive(notif.args.text, notif.args.args);&lt;br /&gt;
    this.showBubble(notif.args.target, html, notif.args.delay ?? 0, notif.args.duration ?? 1000);&lt;br /&gt;
  },&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Warning&#039;&#039;&#039;: if your bubble could overlap other active elements of the interface (buttons in particular), as it stays in place even after disappearing, you should use a custom class to give it the style &amp;quot;pointer-events: none;&amp;quot; in order to intercept click events.&lt;br /&gt;
&lt;br /&gt;
Note: If you want this visually, but want to take complete control over this bubble and its animation (for example to make it permanent) you can just use div with &#039;discussion_bubble&#039; class on it, and content of div is what will be shown.&lt;br /&gt;
&lt;br /&gt;
== Translations ==&lt;br /&gt;
&lt;br /&gt;
See [[Translations]]&lt;br /&gt;
&lt;br /&gt;
== Players panels ==&lt;br /&gt;
&lt;br /&gt;
=== Update players score ===&lt;br /&gt;
&lt;br /&gt;
The column player_score from the player table is automatically loaded into this.scoreCtrl and therefore into the stars location on the player board. This occurs sometime after the game setup() function. However this score must be updated as the game progresses using notifications.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Note: this.scoreCtrl[player_id] is object of class [[Counter]], you can use other counter API.&lt;br /&gt;
&lt;br /&gt;
Increase a player score (with a positive or negative number):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  this.scoreCtrl[ player_id ].incValue( score_delta );&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Set a player score to a specific value:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  this.scoreCtrl[ player_id ].setValue( new_score );&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Set a player score to a specific value with animation:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  this.scoreCtrl[ player_id ].toValue( new_score );&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Typical usage would be (that will process &#039;score&#039; notification):&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        setupNotifications : function() {&lt;br /&gt;
              ...&lt;br /&gt;
             dojo.subscribe(&#039;score&#039;, this, &amp;quot;notif_score&amp;quot;);&lt;br /&gt;
        },&lt;br /&gt;
        notif_score: function(notif) {&lt;br /&gt;
            this.scoreCtrl[notif.args.player_id].setValue(notif.args.player_score);&lt;br /&gt;
        },&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Adding stuff to player&#039;s panel ===&lt;br /&gt;
&lt;br /&gt;
At first, create a new &amp;quot;JS template&amp;quot; string in your template (tpl) file:&lt;br /&gt;
&lt;br /&gt;
(from Gomoku example)&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
var jstpl_player_board = &#039;\&amp;lt;div class=&amp;quot;cp_board&amp;quot;&amp;gt;\&lt;br /&gt;
    &amp;lt;div id=&amp;quot;stoneicon_p${id}&amp;quot; class=&amp;quot;gmk_stoneicon gmk_stoneicon_${color}&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&amp;lt;span id=&amp;quot;stonecount_p${id}&amp;quot;&amp;gt;0&amp;lt;/span&amp;gt;\&lt;br /&gt;
&amp;lt;/div&amp;gt;&#039;;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Then, you add this piece of code in your JS file to add this template to each player panel:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
            // Setting up player boards&lt;br /&gt;
            for( var player_id in gamedatas.players )&lt;br /&gt;
            {&lt;br /&gt;
                var player = gamedatas.players[player_id];&lt;br /&gt;
                         &lt;br /&gt;
                // Setting up players boards if needed&lt;br /&gt;
                var player_board_div = $(&#039;player_board_&#039;+player_id);&lt;br /&gt;
                dojo.place( this.format_block(&#039;jstpl_player_board&#039;, player ), player_board_div );&lt;br /&gt;
            }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
(Note: the code above is of course from your &amp;quot;setup&amp;quot; function in your Javascript).&lt;br /&gt;
&lt;br /&gt;
Very often, you have to distinguish current player and others players. In this case, you just have to create another JS template (ex: jstpl_otherplayer_board) and use it when &amp;quot;player_id&amp;quot; is different than &amp;quot;this.player_id&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Fixing Player Panel heights ===&lt;br /&gt;
&lt;br /&gt;
You may find that the player panels don&#039;t automatically resize when adding something to (or removing something from) a player panel while the display is in portrait mode (i.e. the player summary panels are at the top of the screen rather than down the right side).&lt;br /&gt;
&lt;br /&gt;
When this happens, call &amp;lt;pre&amp;gt;this.adaptPlayersPanels();&amp;lt;/pre&amp;gt; This recalculates the layout and also adjusts the position of the actionbar for you.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Player&#039;s panel disabling/enabling ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.disablePlayerPanel(player_id: number): void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Disable given player panel (the panel background become gray).&lt;br /&gt;
&lt;br /&gt;
Usually, this is used to signal that this played passes, or will be inactive during a while.&lt;br /&gt;
&lt;br /&gt;
Note that the only effect of this is visual. There are no consequences on the behaviour of the panel itself.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.enablePlayerPanel(player_id:number): void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Enable a player panel that has been disabled before.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.enableAllPlayerPanels(): void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Enable all player panels that has been disabled before.&lt;br /&gt;
&lt;br /&gt;
=== Player order ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.updatePlayerOrdering(): void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
This function makes sure that player order in player&#039;s panel matches this.gamedatas.playerorder and its normally called by framework.&lt;br /&gt;
You can call it yoursel if you change this.gamedatas.playerorder from notification.&lt;br /&gt;
Also you can override this function to change defaults  OR insert a non-player panel [[BGA_Studio_Cookbook#Inserting_non-player_panel]].&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Counters ===&lt;br /&gt;
Note: there is bga component called  &amp;quot;ebg/counter&amp;quot; this API is not using it, these methods&lt;br /&gt;
below declared right in core game. If you need animation for counters use ebg/counter&lt;br /&gt;
&lt;br /&gt;
To use this API just create a counter dom element like this (class does not really matter)&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 &amp;lt;div class=&amp;quot;counter&amp;quot; id=&amp;quot;bread&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
 &amp;lt;div class=&amp;quot;counter&amp;quot; id=&amp;quot;coin&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
The &amp;quot;bread&amp;quot; will the counter name.&lt;br /&gt;
&lt;br /&gt;
The php code should send all &amp;quot;counters&amp;quot; data from getAllDatas() method like this&lt;br /&gt;
&lt;br /&gt;
game.php&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  protected function getAllDatas() {&lt;br /&gt;
    // (the key must match counter_name)&lt;br /&gt;
    $result[&#039;counters&#039;]=[&lt;br /&gt;
        &#039;bread&#039; =&amp;gt; [ &lt;br /&gt;
         &#039;counter_name&#039; =&amp;gt; &#039;bread&#039;, &lt;br /&gt;
         &#039;counter_value&#039; =&amp;gt; 3&lt;br /&gt;
         ], &lt;br /&gt;
        &#039;coin&#039; =&amp;gt; [&lt;br /&gt;
          &#039;counter_name&#039; =&amp;gt; &#039;coin&#039;, &lt;br /&gt;
          &#039;counter_value&#039; =&amp;gt; 5&lt;br /&gt;
        ]&lt;br /&gt;
   ];&lt;br /&gt;
   return $result;&lt;br /&gt;
  }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;setCounter(counter_name: stirng, new_value: string | number): void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
updates the global this.gamedatas.counters and value of node $(counter_name)&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  notif_counter: function(notif) { &lt;br /&gt;
    this.setCounter(notif.args.counter_name, notif.args.counter_value);&lt;br /&gt;
  },&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;incCounter(counter_name: string, delta: number): void&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  notif_counter : function(notif) {&lt;br /&gt;
    this.incCounter(notif.args.counter_name, notif.args.inc);&lt;br /&gt;
  },&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;updateCounters(counters: object): void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Useful for updating game counters in the player panel (such as resources). &lt;br /&gt;
&#039;counters&#039; arg is map of counters (the key must match counter_name)&lt;br /&gt;
  {&lt;br /&gt;
    &#039;bread&#039;: { &lt;br /&gt;
         &#039;counter_name&#039; : &#039;bread&#039;, &lt;br /&gt;
         &#039;counter_value&#039; =&amp;gt; 3&lt;br /&gt;
    }, &lt;br /&gt;
    &#039;coin&#039;: { &lt;br /&gt;
         &#039;counter_name&#039; : &#039;coin&#039;, &lt;br /&gt;
         &#039;counter_value&#039; =&amp;gt; 5&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
All counters MUST be referenced in this.gamedatas.counters (means they should be send from php) and will be updated.&lt;br /&gt;
DOM objects referenced by &#039;counter_name&#039; will have their innerHTML updated with &#039;counter_value&#039;.&lt;br /&gt;
&lt;br /&gt;
Usually you call this from notification&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
                        notif_counter : function(notif) {&lt;br /&gt;
                            this.updateCounters(notif.args.counters);&lt;br /&gt;
                        },&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== BGA GUI components ==&lt;br /&gt;
&lt;br /&gt;
BGA framework provides some useful ready-to-use components for the game interface:&lt;br /&gt;
&lt;br /&gt;
[[Studio#BGA_Studio_game_components_reference]]&lt;br /&gt;
&lt;br /&gt;
Note that each time you are using an additional component, you must declare it at the top of your Javascript file in the list of modules used.&lt;br /&gt;
&lt;br /&gt;
Example if you are using &amp;quot;ebg.stock&amp;quot;:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
define([&lt;br /&gt;
    &amp;quot;dojo&amp;quot;,&amp;quot;dojo/_base/declare&amp;quot;,&lt;br /&gt;
    &amp;quot;ebg/core/gamegui&amp;quot;,&lt;br /&gt;
    &amp;quot;ebg/counter&amp;quot;,&lt;br /&gt;
    &amp;quot;ebg/stock&amp;quot;  /// &amp;lt;=== we are using ebg.stock module&lt;br /&gt;
],&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== BGA Buttons ==&lt;br /&gt;
&lt;br /&gt;
=== Basic Button ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.addActionButton(id: string, label: string, method: string | eventhandler, destination?: string, blinking?: boolean, color?: string): void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
You can use this method to add an action button in the main action status bar (or other places).&lt;br /&gt;
&lt;br /&gt;
Arguments:&lt;br /&gt;
* id: an element ID that should be unique in your HTML DOM document.&lt;br /&gt;
* label: the text of the button. Should be translatable (use _() function). Note: this can also be any html, such as &amp;quot;&amp;lt;div class=&#039;brick&#039;&amp;gt;&amp;lt;/div&amp;gt;&amp;quot;, see example below on how to make image action buttons.&lt;br /&gt;
* method: the name of your method that must be triggered when the player clicks on this button (can be name of the method on game class or handler).&lt;br /&gt;
* destination (optional): id of parent on where to add button, ONLY use in rare cases if location is not action bar. Use &#039;&#039;&#039;null&#039;&#039;&#039; as value if you need to specify other arguments.&lt;br /&gt;
* blinking (optional): if set to &#039;&#039;&#039;true&#039;&#039;&#039;, the button is going blink to catch player&#039;s attention. Please DO NOT abuse blinking button. If you need button to blink after some time passed add class &#039;blinking&#039; to the button later.&lt;br /&gt;
* color: could be &#039;&#039;&#039;blue&#039;&#039;&#039; (default), &#039;&#039;&#039;red&#039;&#039;&#039;,&#039;&#039;&#039;gray&#039;&#039;&#039; or &#039;&#039;&#039;none&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
You should only use this method in your &amp;quot;onUpdateActionButtons&amp;quot; method. Usually, you use it like this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        onUpdateActionButtons: function( stateName, args ) {                      &lt;br /&gt;
            if (this.isCurrentPlayerActive()) {            &lt;br /&gt;
                switch( stateName ) {&lt;br /&gt;
                case &#039;giveCards&#039;:&lt;br /&gt;
                    this.addActionButton( &#039;giveCards_button&#039;, _(&#039;Give selected cards&#039;), &#039;onGiveCards&#039; ); &lt;br /&gt;
                    this.addActionButton( &#039;pass_button&#039;, _(&#039;Pass&#039;), () =&amp;gt; this.bgaPerformAction(&#039;actPass&#039;) ); &lt;br /&gt;
                    break;&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        },   &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In the example above, we are adding a &amp;quot;Give selected cards&amp;quot; button in the case we are on game state &amp;quot;giveCards&amp;quot;. When player clicks on this button, it triggers our &amp;quot;onGiveCards&amp;quot; method.&lt;br /&gt;
&lt;br /&gt;
Example using blinking red button:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    this.addActionButton( &#039;button_confirm&#039;, _(&#039;Confirm?&#039;), &#039;onConfirm&#039;, null, true, &#039;red&#039;); &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If you want to call the handler with arguments, you can use arrow functions, like this:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
     this.addActionButton( &#039;commit_button&#039;, _(&#039;Confirm&#039;), () =&amp;gt; this.onConfirm(this.selectedCardId), null, false, &#039;red&#039;); &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Image Button ===&lt;br /&gt;
&lt;br /&gt;
You can use the same method, but add extra class to a button to disable the padding and style it, i.e.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
this.addActionButton( &#039;button_brick&#039;, &#039;&amp;lt;div class=&amp;quot;brick&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&#039;, ()=&amp;gt;{... on brick ...}, null, null, &#039;gray&#039;); &lt;br /&gt;
dojo.addClass(&#039;button_brick&#039;,&#039;bgaimagebutton&#039;);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
where&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
.bgaimagebutton {&lt;br /&gt;
  padding: 0px 12px;&lt;br /&gt;
  min-height: 28px;&lt;br /&gt;
  border: none;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If you use this a lot, you can define a helper function, i.e.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
 * This method can be used instead of addActionButton, to add a button which is an image (i.e. resource). Can be useful when player&lt;br /&gt;
 * need to make a choice of resources or tokens.&lt;br /&gt;
 */&lt;br /&gt;
addImageActionButton: function(id, div, handler, bcolor, tooltip) {&lt;br /&gt;
	if (typeof bcolor == &amp;quot;undefined&amp;quot;) {&lt;br /&gt;
		bcolor = &amp;quot;gray&amp;quot;;&lt;br /&gt;
	}&lt;br /&gt;
	// this will actually make a transparent button id color = gray&lt;br /&gt;
	this.addActionButton(id, div, handler, null, false, bcolor);&lt;br /&gt;
	// remove border, for images it better without&lt;br /&gt;
	dojo.style(id, &amp;quot;border&amp;quot;, &amp;quot;none&amp;quot;);&lt;br /&gt;
	// but add shadow style (box-shadow, see css)&lt;br /&gt;
	dojo.addClass(id, &amp;quot;shadow bgaimagebutton&amp;quot;);&lt;br /&gt;
	// you can also add additional styles, such as background&lt;br /&gt;
	if (tooltip) {&lt;br /&gt;
		dojo.attr(id, &amp;quot;title&amp;quot;, tooltip);&lt;br /&gt;
	}&lt;br /&gt;
	return $(id);&lt;br /&gt;
},&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Disabling Button ===&lt;br /&gt;
&lt;br /&gt;
You can disable the &#039;&#039;&#039;bgabutton&#039;&#039;&#039; by adding the css class &#039;&#039;&#039;disabled&#039;&#039;&#039; in you js. The disabled button is still visible but is grey and not clickable.&lt;br /&gt;
For example in the &#039;&#039;&#039;onUpdateActionButtons&#039;&#039;&#039; : &lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
this.addActionButton(&#039;play_button_id&#039;, _(&#039;Play 1 to 3 cards&#039;), &#039;playFunctionButton&#039;); &lt;br /&gt;
if (condition) {&lt;br /&gt;
  dojo.addClass(&#039;play_button_id&#039;, &#039;disabled&#039;);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Custom Buttons ===&lt;br /&gt;
&lt;br /&gt;
You can create a custom button, but the BGA framework provides a standard button that requires only .css classes: &#039;&#039;&#039;bgabutton&#039;&#039;&#039; and &#039;&#039;&#039;bgabutton_${color}&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Examples:&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;a href=&amp;quot;#&amp;quot; id=&amp;quot;my_button_id&amp;quot; class=&amp;quot;bgabutton bgabutton_blue&amp;quot;&amp;gt;&amp;lt;span&amp;gt;My blue button&amp;lt;/span&amp;gt;&amp;lt;/a&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;a href=&amp;quot;#&amp;quot; id=&amp;quot;my_button_id&amp;quot; class=&amp;quot;bgabutton bgabutton_red bgabutton_big&amp;quot;&amp;gt;&amp;lt;span&amp;gt;My big red button&amp;lt;/span&amp;gt;&amp;lt;/a&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note&#039;&#039;&#039;: To see it in action, check out &#039;&#039;Coloretto&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
=== Button outside of action bar ===&lt;br /&gt;
&lt;br /&gt;
Use addActionButton() method with destination argument set&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
this.addActionButton( &#039;commit_button&#039;, _(&#039;Confirm&#039;), &#039;onConfirm&#039;, &#039;player_board&#039;, true, &#039;red&#039;); &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
in example above the button will be place on object with id &#039;player_board&#039;&lt;br /&gt;
&lt;br /&gt;
== Image loading ==&lt;br /&gt;
&lt;br /&gt;
See also [[Game_art:_img_directory]].&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Be careful&#039;&#039;&#039;: by default, ALL images of your img directory are loaded on a player&#039;s browser when he loads the game. For this reason, don&#039;t let in your img directory images that are not useful, otherwise it&#039;s going to slowdown the game load.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.dontPreloadImage(image_file_name: string)&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Using dontPreloadImage, you tell the interface to not preload a specific image in your img directory.&lt;br /&gt;
&lt;br /&gt;
Example of use:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
this.dontPreloadImage( &#039;cards.png&#039; );&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This is particularly useful if for example you have 2 different themes for a game. To accelerate the loading of the game, you can specify to not preload images corresponding to the other theme.&lt;br /&gt;
&lt;br /&gt;
Another example of use: in &amp;quot;Gosu&amp;quot; game with Kamakor extension, you play with 5 sets of cards among 10 available. Cards images are organized by sets, and we only preload the images corresponding to the 5 current sets with &#039;&#039;&#039;ensureSpecificGameImageLoading( image_file_names_array )&#039;&#039;&#039;.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
// By default, do not preload anything&lt;br /&gt;
this.dontPreloadImage( &#039;cards.png&#039; );&lt;br /&gt;
this.dontPreloadImage( &#039;clan1.png&#039; );&lt;br /&gt;
this.dontPreloadImage( &#039;clan2.png&#039; );&lt;br /&gt;
this.dontPreloadImage( &#039;clan3.png&#039; );&lt;br /&gt;
this.dontPreloadImage( &#039;clan4.png&#039; );&lt;br /&gt;
this.dontPreloadImage( &#039;clan5.png&#039; );&lt;br /&gt;
this.dontPreloadImage( &#039;clan6.png&#039; );&lt;br /&gt;
this.dontPreloadImage( &#039;clan7.png&#039; );&lt;br /&gt;
this.dontPreloadImage( &#039;clan8.png&#039; );&lt;br /&gt;
this.dontPreloadImage( &#039;clan9.png&#039; );&lt;br /&gt;
this.dontPreloadImage( &#039;clan10.png&#039; );&lt;br /&gt;
var to_preload = [];&lt;br /&gt;
for( i in this.gamedatas.clans )&lt;br /&gt;
{&lt;br /&gt;
	var clan_id = this.gamedatas.clans[i];&lt;br /&gt;
	to_preload.push( &#039;clan&#039;+clan_id+&#039;.png&#039; );&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
this.ensureSpecificGameImageLoading( to_preload );&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note:&#039;&#039;&#039; You don&#039;t need to specify to not preload game box images (game_box.png, game_box75.png...) since they are not preloaded by default.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.ensureSpecificGameImageLoading(list: string[])&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
This is oppostive of dontPreloadImage - its ensure specific images is loaded. Note: only makes sense if preload list is empty, otherwise everything is loaded anyway&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;load specific images&#039;&#039;&#039;&lt;br /&gt;
All images that will be preloaded stored in g_img_preload. If you want to override it directly - there is no API, but you can do this in GAME constructor&lt;br /&gt;
&lt;br /&gt;
          g_img_preload = [&#039;tokens.png&#039;, &#039;trains.png&#039;, &#039;loc_plan.png&#039;, &#039;eng.png&#039;, &#039;eng-back.png&#039;];&lt;br /&gt;
&lt;br /&gt;
You can also set it to empty array and call ensureSpecificGameImageLoading() on specific images&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Sounds ==&lt;br /&gt;
&lt;br /&gt;
Add a custom sound and make it load with your interface:&lt;br /&gt;
&lt;br /&gt;
Add this in your template (.tpl) file:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;audio id=&amp;quot;audiosrc_&amp;lt;gamename&amp;gt;_&amp;lt;yoursoundname&amp;gt;&amp;quot; src=&amp;quot;{GAMETHEMEURL}img/&amp;lt;gamename&amp;gt;_&amp;lt;yoursoundname&amp;gt;.mp3&amp;quot; preload=&amp;quot;none&amp;quot; autobuffer&amp;gt;&amp;lt;/audio&amp;gt;&lt;br /&gt;
&amp;lt;audio id=&amp;quot;audiosrc_o_&amp;lt;gamename&amp;gt;_&amp;lt;yoursoundname&amp;gt;&amp;quot; src=&amp;quot;{GAMETHEMEURL}img/&amp;lt;gamename&amp;gt;_&amp;lt;yoursoundname&amp;gt;.ogg&amp;quot; preload=&amp;quot;none&amp;quot; autobuffer&amp;gt;&amp;lt;/audio&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note: this is a requirement to provide both a mp3 and a ogg file with the names &amp;lt;code&amp;gt;&amp;lt;gamename&amp;gt;_&amp;lt;yoursoundname&amp;gt;[.ogg][.mp3]&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Play the sound (from your .js file):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
playSound(&#039;&amp;lt;gamename&amp;gt;_&amp;lt;yoursoundname&amp;gt;&#039;);   // do not add &#039;this.&#039; - its a global function&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Disable the standard &amp;quot;move&amp;quot; sound for this move (to replace it with your custom sound):&lt;br /&gt;
&lt;br /&gt;
Add this to your notification handler:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
this.disableNextMoveSound();&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note: it only disable the sound for the next move.&lt;br /&gt;
&lt;br /&gt;
== Title bar and states ==&lt;br /&gt;
&lt;br /&gt;
=== Client states ===&lt;br /&gt;
&lt;br /&gt;
Client states is a way to simulate the state transition but without actually going&lt;br /&gt;
to server. It is usefull when you need to ask user multiple questions before you&lt;br /&gt;
send things to server&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.setClientState(newState: string, args: object)&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
     this.setClientState(&amp;quot;client_playerPicksLocation&amp;quot;, {&lt;br /&gt;
                               descriptionmyturn : _(&amp;quot;${you} must select location&amp;quot;),&lt;br /&gt;
                           });&lt;br /&gt;
&lt;br /&gt;
For more information see [[BGA_Studio_Cookbook#Multi_Step_Interactions:_Select_Worker.2FPlace_Worker_-_Using_Client_States]]&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.restoreServerGameState()&#039;&#039;&#039;&lt;br /&gt;
If you are in client state it will restore the current server state (cheap undo)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.on_client_state&#039;&#039;&#039;&lt;br /&gt;
Boolean indicating that we are in client state&lt;br /&gt;
&lt;br /&gt;
=== Title bar ===&lt;br /&gt;
If you simply want to show something in title bar you can do it directly &lt;br /&gt;
     $(&#039;pagemaintitletext&#039;).innerHTML = text;&lt;br /&gt;
&lt;br /&gt;
This however will not work with parameters and will not draw You in color,&lt;br /&gt;
if you want to do proper args rendering use method below&lt;br /&gt;
&lt;br /&gt;
;&#039;&#039;&#039;this.removeActionButtons()&#039;&#039;&#039;&lt;br /&gt;
Removes all buttons from title bar&lt;br /&gt;
&lt;br /&gt;
;&#039;&#039;&#039;this.updatePageTitle()&#039;&#039;&#039;&lt;br /&gt;
:This function allows to update the current page title and turn description according to the game state arguments. If the current game state description this.gamedatas.gamestate.descriptionmyturn is modified before calling this function it allows to update the turn description without changing state. This will handle arguments substitutions properly.&lt;br /&gt;
&lt;br /&gt;
Note: this functional also will calls this.onUpdateActionButtons, if you want different buttons then state defaults, use method in example to replace them, if it becomes too clumsy use client states (see above)&lt;br /&gt;
&lt;br /&gt;
Example from Terra Mystica:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
onClickFavorTile: function( evt ) {&lt;br /&gt;
    ...&lt;br /&gt;
    if ( ... ) {&lt;br /&gt;
        this.gamedatas.gamestate.descriptionmyturn = _(&#039;Special action: &#039;) + _(&#039;Advance 1 space	on a Cult track&#039;);&lt;br /&gt;
        this.updatePageTitle();&lt;br /&gt;
        this.removeActionButtons();&lt;br /&gt;
        this.addActionButton( ... );&lt;br /&gt;
         ...&lt;br /&gt;
        return;&lt;br /&gt;
    }&lt;br /&gt;
    ...&lt;br /&gt;
&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== User preferences ==&lt;br /&gt;
&#039;&#039;&#039;this.getGameUserPreference(pref_id)&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Return the value of a user preference. It will return the value currently selected in the select combo box, in the top-right menu.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.setGameUserPreference(pref_id, value)&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Programmatically change a user preference. It will have the same effect as if the player changed the value in the select combo box, in the top-right menu.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.onGameUserPreferenceChanged&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
A callback you can define if you want to be notified when a user changes a user preference.&lt;br /&gt;
&lt;br /&gt;
Example:&amp;lt;pre&amp;gt;&lt;br /&gt;
onGameUserPreferenceChanged: function(pref_id, pref_value) {&lt;br /&gt;
  switch (pref_id) {&lt;br /&gt;
    case 201: &lt;br /&gt;
      document.getElementsByTagName(&#039;html&#039;)[0].classList.toggle(&#039;dark-background&#039;, pref_value == 2);&lt;br /&gt;
      break;&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Other useful stuff ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;dojo.hitch&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
With dojo.hitch, you can create a callback function that will run with your game object context whatever happen.&lt;br /&gt;
&lt;br /&gt;
Typical example: display a BGA confirmation dialog with a callback function created with dojo.hitch:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        this.confirmationDialog( _(&#039;Are you sure you want to make this?&#039;), dojo.hitch( this, function() {&lt;br /&gt;
            this.bgaPerformAction(&#039;makeThis&#039;);&lt;br /&gt;
        } ) );   &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In the example above, using dojo.hitch, we ensure that the &amp;quot;this&amp;quot; object will be set when the callback is called.&lt;br /&gt;
&lt;br /&gt;
NOTE: In modern JS there are lambdas that eliminate need for that, the example above will look like this&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        this.confirmationDialog( _(&#039;Are you sure you want to make this?&#039;), () =&amp;gt; this.bgaPerformAction( &#039;makeThis&#039;) );   &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
;&#039;&#039;&#039;onScreenWidthChange()&#039;&#039;&#039;&lt;br /&gt;
:This function can be overridden in your game to manage some resizing on the client side when the browser window is resized. This function is also triggered at load time, so it can be used to adapt to the :viewport size at the start of the game too.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
; this.bRealtime&lt;br /&gt;
: Return true if the game is in realtime. Note that having a distinct behavior in realtime and turn-based should be exceptional.&lt;br /&gt;
&lt;br /&gt;
; g_replayFrom&lt;br /&gt;
: Global contains replay number in live game, it is set to undefined (i.e. not set) when it is not a replay mode, so consequentially the good check is &#039;&#039;&#039;typeof g_replayFrom != &#039;undefined&#039;&#039;&#039;&#039; which returns true if the game is in replay mode &amp;lt;i&amp;gt;during the game&amp;lt;/i&amp;gt; (the game is ongoing but the user clicked &amp;quot;replay from this move&amp;quot; in the log)&lt;br /&gt;
&lt;br /&gt;
; g_archive_mode&lt;br /&gt;
: Returns true if the game is in archive mode &amp;lt;i&amp;gt;after the game&amp;lt;/i&amp;gt; (the game has ended)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
; this.instantaneousMode&lt;br /&gt;
: Returns true during replay/archive mode if animations should be skipped. Only needed if you are doing custom animations. (The BGA-provided animation functions like &amp;lt;i&amp;gt;this.slideToObject()&amp;lt;/i&amp;gt; automatically handle instantaneous mode.)&lt;br /&gt;
: Technically, when you click &amp;quot;replay from move #20&amp;quot;, the system replays the game from the very beginning with moves 0 - 19 happening in instantaneous mode and moves 20+ happening in normal mode.&lt;br /&gt;
&lt;br /&gt;
; g_tutorialwritten&lt;br /&gt;
: Returns an object like the below if the game is in tutorial mode, or undefined otherwise. Tutorial mode is a special case of archive mode where comments have been added to a previous game to teach new players the rules.&lt;br /&gt;
    {&lt;br /&gt;
        author: &amp;quot;91577332&amp;quot;,&lt;br /&gt;
        id: &amp;quot;576&amp;quot;,&lt;br /&gt;
        mode: &amp;quot;view&amp;quot;&lt;br /&gt;
        status: &amp;quot;alpha&amp;quot;&lt;br /&gt;
        version_override: null&lt;br /&gt;
        viewer_id: &amp;quot;84554161&amp;quot;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;getBgaEnvironment(): string&#039;&#039;&#039;&lt;br /&gt;
: Returns &amp;quot;studio&amp;quot; for studio and &amp;quot;prod&amp;quot; for production environment (i.e. where games current runs). Only useful for debbugging hooks.&lt;br /&gt;
Note: alpha server is also &amp;quot;prod&amp;quot;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Category:Studio]]&lt;/div&gt;</summary>
		<author><name>Sguzzer Gunayer</name></author>
	</entry>
	<entry>
		<id>https://en.doc.boardgamearena.com/index.php?title=Game_interface_logic:_Game.js&amp;diff=22729</id>
		<title>Game interface logic: Game.js</title>
		<link rel="alternate" type="text/html" href="https://en.doc.boardgamearena.com/index.php?title=Game_interface_logic:_Game.js&amp;diff=22729"/>
		<updated>2024-09-25T16:38:45Z</updated>

		<summary type="html">&lt;p&gt;Sguzzer Gunayer: /* Element by Id */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Studio_Framework_Navigation}}&lt;br /&gt;
&lt;br /&gt;
__TOC__&lt;br /&gt;
&lt;br /&gt;
This is the main file for your game interface. Here you will define:&lt;br /&gt;
&lt;br /&gt;
* Which actions on the page will generate calls to the server.&lt;br /&gt;
* What happens when you get a notification for a change from the server and how it will show in the browser. &lt;br /&gt;
* Setup user interface&lt;br /&gt;
&lt;br /&gt;
== File structure ==&lt;br /&gt;
&lt;br /&gt;
The details of how the file is structured are described below with comments in the code skeleton provided to you.&lt;br /&gt;
&lt;br /&gt;
Here is the basic structure:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;constructor&#039;&#039;&#039;: here you can define global variables for your whole interface.&lt;br /&gt;
* &#039;&#039;&#039;setup&#039;&#039;&#039;: this method is called when the page is refreshed, and sets up the game interface.&lt;br /&gt;
* &#039;&#039;&#039;onEnteringState&#039;&#039;&#039;: this method is called when entering a new game state. You can use it to customize the view for each game state.&lt;br /&gt;
* &#039;&#039;&#039;onLeavingState&#039;&#039;&#039;: this method is called when leaving a game state.&lt;br /&gt;
* &#039;&#039;&#039;onUpdateActionButtons&#039;&#039;&#039;: called on state changes, in order to add action buttons to the status bar. Note: in a multipleactiveplayer state, it will be called when another player has become inactive.&lt;br /&gt;
* &#039;&#039;(utility methods)&#039;&#039;: this is where you can define your utility methods.&lt;br /&gt;
* &#039;&#039;(player&#039;s actions)&#039;&#039;: this is where you can write your handlers for player actions on the interface (example: click on an item).&lt;br /&gt;
* &#039;&#039;&#039;setupNotifications&#039;&#039;&#039;: this method associates notifications with notification handlers. For each game notification, you can trigger a javascript method to handle it and update the game interface.&lt;br /&gt;
* &#039;&#039;(notification handlers)&#039;&#039;: this is where you define the notifications handlers associated with notifications in &#039;&#039;&#039;setupNotifications&#039;&#039;&#039;, above.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
More details:&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;setup(gamedatas: object)            &#039;&#039;&#039;&lt;br /&gt;
This method must set up the game user interface according to current game situation specified in parameters.&lt;br /&gt;
The method is called each time the game interface is displayed to a player, ie:&lt;br /&gt;
&lt;br /&gt;
* when the game starts&lt;br /&gt;
* when a player opens a game in the browser later &lt;br /&gt;
* when a player refreshes the game page (F5)&lt;br /&gt;
* when player does a server side Undo&lt;br /&gt;
&lt;br /&gt;
&amp;quot;gamedatas&amp;quot; argument contains all data retrieved by your &amp;quot;getAllDatas&amp;quot; PHP method and some more.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;onEnteringState(stateName: string, args: { args: any } | null): void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
This method is called each time we enter a new game state.&lt;br /&gt;
You can use this method to perform some user interface changes at this moment.&lt;br /&gt;
To access state arguments passed via calling php arg* method use args?.args.&lt;br /&gt;
Typically you would do something only for active player, using this.isCurrentPlayerActive() check.&lt;br /&gt;
It is also called (for the current game state only) when doing a browser refresh (after the setup method is called).&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Warning&#039;&#039;&#039;: for multipleactiveplayer states:&lt;br /&gt;
the active players are NOT active yet so you must use onUpdateActionButtons to perform the client side operation which depends on a player active/inactive status.&lt;br /&gt;
If you are doing initialization of some structures which do not depend on the active player, you can just replace (this.isCurrentPlayerActive()) with (!this.isSpectator) &lt;br /&gt;
for the main switch in that method.&lt;br /&gt;
&lt;br /&gt;
See more details in [[Your_game_state_machine:_states.inc.php#Difference_between_Single_active_and_Multi_active_states]]&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;onLeavingState(stateName: string): void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
This method is called each time we leave a game state.&lt;br /&gt;
You can use this method to perform some user interface changes at this point (i.e. cleanup).&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;onUpdateActionButtons(stateName: string, args: object | null): void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
In this method you can manage &amp;quot;action buttons&amp;quot; that are displayed in the action status bar and highlight active UI elements.&lt;br /&gt;
To access state arguments passed via calling php arg* method use &#039;&#039;&#039;args&#039;&#039;&#039; parameter. Note: args can be null! For &#039;&#039;&#039;game&#039;&#039;&#039; states and when you don&#039;t supply state args function - it is null.&lt;br /&gt;
This method is called when the active or multiactive player changes. In a classic &amp;quot;activePlayer&amp;quot; state this method is called before the onEnteringState state.&lt;br /&gt;
In multipleactiveplayer state it is a mess. The sequencing of calls depends on whether you get into that state from transitions OR from reloading the whole game (i.e. F5).&lt;br /&gt;
&lt;br /&gt;
See more details in [[Your_game_state_machine:_states.inc.php#Difference_between_Single_active_and_Multi_active_states]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Dojo framework ==&lt;br /&gt;
&lt;br /&gt;
BGA uses the [http://dojotoolkit.org/ Dojo Javascript framework].&lt;br /&gt;
&lt;br /&gt;
The Dojo framework allows us to do complex things more easily. The BGA framework uses Dojo extensively.&lt;br /&gt;
&lt;br /&gt;
To implement a game, you only need to use a few parts of the Dojo framework. All the Dojo methods you need are described on this page.&lt;br /&gt;
&lt;br /&gt;
== Javascript minimization (after July 2020) ==&lt;br /&gt;
&lt;br /&gt;
For performance reasons, when deploying a game the javascript code is minimized using &#039;&#039;&#039;terser&#039;&#039;&#039; (https://github.com/terser/terser). This minifier works with modern javascript syntax. From your project &amp;quot;Manage game&amp;quot; page, you can now test a minified version of your javascript on the studio (and revert to the original).&lt;br /&gt;
&lt;br /&gt;
NB: it has been reported that there is an issue with this minifier and percentage values for opacity.&lt;br /&gt;
&lt;br /&gt;
== Accessing Players Information ==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.player_id: number&#039;&#039;&#039;&lt;br /&gt;
id of the player who is looking at the game. The player may not be part of the game (i.e. spectator)&lt;br /&gt;
  if (notif.args.player_id == this.player_id) {&lt;br /&gt;
    ...&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.isSpectator: boolean&#039;&#039;&#039;&lt;br /&gt;
Flag set to true if the user at the table is a spectator (not a player).&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    if (this.isSpectator) {&lt;br /&gt;
        this.player_color = &#039;ffffff&#039;;&lt;br /&gt;
    } else {&lt;br /&gt;
        this.player_color = gamedatas.players[this.player_id].color;&lt;br /&gt;
    }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note: If you want to hide an element from spectators, you should use [[Game_interface_stylesheet:_yourgamename.css#spectatorMode|CSS &#039;spectatorMode&#039; class]].&lt;br /&gt;
&lt;br /&gt;
You may consider making a function like this, to detect if the game is in a read-only state (i.e. non-interactive):&lt;br /&gt;
  // Returns true for spectators, instant replay (during game), archive mode (after game end)&lt;br /&gt;
  isReadOnly: function () {&lt;br /&gt;
    return this.isSpectator || typeof g_replayFrom != &#039;undefined&#039; || g_archive_mode;&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.gamedatas: object&#039;&#039;&#039;&lt;br /&gt;
Contains the initial set of data to init the game, created at game start or by game refresh (F5).&lt;br /&gt;
You can update it as needed to keep an up-to-date reference of the game on the client side if you need it, however most of the time this is unnecessary.&lt;br /&gt;
&lt;br /&gt;
Note: In hotseat mode, the framework does not keep this.gamedatas of hotseat players and shares the same set as the main player to store data.&lt;br /&gt;
&lt;br /&gt;
Note: be careful when you update this data structurally, many framework functions expect data to be certain way and they will break if they see something else.&lt;br /&gt;
&lt;br /&gt;
Typical example of accessing player&#039;s info&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
for (var player_id in this.gamedatas.players) { &lt;br /&gt;
    var playerInfo = this.gamedatas.players [player_id];&lt;br /&gt;
    var c = playerInfo.color;&lt;br /&gt;
    var name = playerInfo.name;&lt;br /&gt;
    // do something &lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.isCurrentPlayerActive(): boolean&#039;&#039;&#039;&lt;br /&gt;
Returns true if the player on whose browser the code is running is currently active (it&#039;s his turn to play). Note: see remarks above about usage of this function inside onEnteringState method.&lt;br /&gt;
  if (this.isCurrentPlayerActive()) ...&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.getActivePlayerId(): number&#039;&#039;&#039;&lt;br /&gt;
Return the ID of the active player, or null if we are not in an &amp;quot;activeplayer&amp;quot; type state.&lt;br /&gt;
  if (this.player_id == this.getActivePlayerId()) ...&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.getActivePlayers(): number[]&#039;&#039;&#039;&lt;br /&gt;
Return an array with the IDs of players who are currently active (or an empty array if there are none).&lt;br /&gt;
&lt;br /&gt;
== Accessing and manipulating the DOM ==&lt;br /&gt;
&lt;br /&gt;
=== Element by Id ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;$(elementId: ElementOrId)&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
The $ function is used to get an HTML element using its &amp;quot;id&amp;quot; attribute.&lt;br /&gt;
&lt;br /&gt;
Example: modify the content of a &amp;quot;span&amp;quot; element:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
In your HTML code:&lt;br /&gt;
   &amp;lt;span id=&amp;quot;a_value_in_the_game_interface&amp;quot;&amp;gt;1234&amp;lt;/span&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In your Javascript code:&lt;br /&gt;
   $(&#039;a_value_in_the_game_interface&#039;).innerHTML = &amp;quot;9999&amp;quot;;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Note: It is safe to use if you don&#039;t know if variable is string (id of element) or element itself, i.e. &lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  foo: function(card) {&lt;br /&gt;
       card = $(card); // now its node, no need to write if (typeof card === &#039;string&#039;) ...&lt;br /&gt;
       // but its good idea to check for null here&lt;br /&gt;
       ...&lt;br /&gt;
  }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;getElementById(elementId: string)&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Note: $() is the standard method to access some HTML element with the BGA Framework. You can use &#039;&#039;&#039;getElementById&#039;&#039;&#039; but it is longer to type and less handy as it does not do some checks.&lt;br /&gt;
&lt;br /&gt;
=== Style ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;dojo.style(node: ElementOrId, styleName: string, styleValue: any): void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
With dojo.style you can modify the CSS property of any HTML element in your interface.&lt;br /&gt;
&lt;br /&gt;
Examples:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
     // Make an element disappear&lt;br /&gt;
     dojo.style( &#039;my_element&#039;, &#039;display&#039;, &#039;none&#039; );&lt;br /&gt;
&lt;br /&gt;
     // Give an element a 2px border&lt;br /&gt;
     dojo.style( &#039;my_element&#039;, &#039;borderWidth&#039;, &#039;2px&#039; );&lt;br /&gt;
&lt;br /&gt;
     // Change the background position of an element&lt;br /&gt;
     // (very practical when you are using CSS sprites to transform an element to another)&lt;br /&gt;
     dojo.style( &#039;my_element&#039;, &#039;backgroundPosition&#039;, &#039;-20px -50px&#039; );&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note: if you have to modify several CSS properties of an element, or if you have a complex CSS transformation to do, you should consider using dojo.addClass/dojo.removeClass (see below).&lt;br /&gt;
&lt;br /&gt;
You can also use object to set multiple values&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
dojo.setStyle(&amp;quot;thinger&amp;quot;, {&lt;br /&gt;
  &amp;quot;opacity&amp;quot;: 0.5,&lt;br /&gt;
  &amp;quot;border&amp;quot;: &amp;quot;3px solid black&amp;quot;,&lt;br /&gt;
  &amp;quot;height&amp;quot;: &amp;quot;300px&amp;quot;&lt;br /&gt;
});&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.addStyleToClass(cssClassName: string, styleName: string, styleValue: any):&#039;&#039;&#039; &#039;&#039;&#039;void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Same as dojo.style(), but for all the nodes set with the specified cssClassName&lt;br /&gt;
Equivalent of &lt;br /&gt;
  &lt;br /&gt;
  dojo.query(`.${aclass}`).style(styleName, styleValue)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
dojo.query(&amp;quot;#baz &amp;gt; div&amp;quot;).style({&lt;br /&gt;
  opacity:0.75,&lt;br /&gt;
  fontSize:&amp;quot;13pt&amp;quot;&lt;br /&gt;
});&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Vanilla JS style&#039;&#039;&#039;&lt;br /&gt;
  $(&#039;my_element&#039;).style.display=&#039;none&#039;; // set&lt;br /&gt;
  var display = $(&#039;my_element&#039;).style.display; // get&lt;br /&gt;
  $(&#039;my_element&#039;).style.removeProperty(&#039;display&#039;); // remove&lt;br /&gt;
&lt;br /&gt;
=== Classes ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;dojo.addClass(node: ElementOrId, classes: string): void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;dojo.removeClass(node: ElementOrId, classes: string): void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;dojo.hasClass(node: ElementOrId, aclass: string): void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;dojo.toggleClass(node: ElementOrId, aclass: string): void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
In many situations, many small CSS property updates can be replaced by a CSS class change (i.e., you add a CSS class to your element instead of applying all modifications manually).&lt;br /&gt;
&lt;br /&gt;
Advantages are:&lt;br /&gt;
* All your CSS stuff remains in your CSS file.&lt;br /&gt;
* You can add/remove a list of CSS modifications with a simple function and without error.&lt;br /&gt;
* You can test whether you applied the CSS to an element with the &#039;&#039;&#039;dojo.hasClass&#039;&#039;&#039; method.&lt;br /&gt;
&lt;br /&gt;
Example from &#039;&#039;Reversi&#039;&#039;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    // We add &amp;quot;possibleMove&amp;quot; to an element&lt;br /&gt;
    dojo.addClass( &#039;square_&#039;+x+&#039;_&#039;+y, &#039;possibleMove&#039; );&lt;br /&gt;
&lt;br /&gt;
    // In our CSS file, the class is defined as:&lt;br /&gt;
    .possibleMove {&lt;br /&gt;
      background-color: white;&lt;br /&gt;
      opacity: 0.2;&lt;br /&gt;
      filter:alpha(opacity=20); /* For IE8 and earlier */  &lt;br /&gt;
      cursor: pointer;  &lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
     // So we&#039;ve applied 4 CSS property changes in one line of code.&lt;br /&gt;
&lt;br /&gt;
     // ... and when we need to check if a square is a possible move on the client side:&lt;br /&gt;
     if( dojo.hasClass( &#039;square_&#039;+x+&#039;_&#039;+y, &#039;possibleMove&#039; ) )&lt;br /&gt;
     { ... }&lt;br /&gt;
&lt;br /&gt;
     // ... and if we want to remove all possible moves in one line of code (see &amp;quot;dojo.query&amp;quot; method):&lt;br /&gt;
     dojo.query( &#039;.possibleMove&#039; ).removeClass( &#039;possibleMove&#039; );&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Vanilla JS classList&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
This is the only exception where dojo versions are better&lt;br /&gt;
  // add class&lt;br /&gt;
  $(token_id).classList.addClass(&#039;possibleMove&#039;);&lt;br /&gt;
  // remove class&lt;br /&gt;
  $(token_id).classList.removeClass(&#039;possibleMove&#039;);&lt;br /&gt;
  // add 2 classes&lt;br /&gt;
  const myclasses = [&#039;a&#039;,&#039;b&#039;];&lt;br /&gt;
  $(token_id).classList.addClass(...myclasses);&lt;br /&gt;
  // add classes to query result&lt;br /&gt;
  document.querySelectorAll(&amp;quot;.hand .card&amp;quot;).forEach((node)=&amp;gt;node.classList.addClass(&#039;possibleMove&#039;));&lt;br /&gt;
&lt;br /&gt;
=== Attributes ===&lt;br /&gt;
&lt;br /&gt;
;dojo.attr&lt;br /&gt;
&lt;br /&gt;
With dojo.attr you can access or change the value of an attribute or property of any HTML element in your interface.&lt;br /&gt;
&lt;br /&gt;
Exemple:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
     // Get the title of a node&lt;br /&gt;
     var title = dojo.attr( id, &#039;title&#039; );&lt;br /&gt;
     // Change the height of a node&lt;br /&gt;
     dojo.attr( &#039;img_growing_tree&#039;, &#039;height&#039;, 100 );&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Vanilla JS attr&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
   $(token).id=new_id; // set attr for &amp;quot;id&amp;quot;&lt;br /&gt;
   var id = $(token).id; // get&lt;br /&gt;
&lt;br /&gt;
=== Queries ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;dojo.query(cssSelector: string): Element[]&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
With dojo.query, you can query a bunch of HTML elements with a single function, with a &amp;quot;CSS selector&amp;quot; style.&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
     // All elements with class &amp;quot;possibleMove&amp;quot;:&lt;br /&gt;
     var elements = dojo.query( &#039;.possibleMove&#039; );&lt;br /&gt;
&lt;br /&gt;
     // Count number of tokens (i.e., elements of class &amp;quot;token&amp;quot;) on the board (i.e., the element with id &amp;quot;board&amp;quot;):&lt;br /&gt;
     dojo.query( &#039;#board .token&#039; ).length;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
But what is really cool with dojo.query is that you can combine it with almost all methods above.&lt;br /&gt;
&lt;br /&gt;
Examples:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
     // Trigger a method when the mouse enter in any element with class &amp;quot;meeple&amp;quot;:&lt;br /&gt;
     dojo.query( &#039;.meeple&#039; ).connect( &#039;onmouseenter&#039;, this, &#039;myMethodToTrigger&#039; );&lt;br /&gt;
&lt;br /&gt;
     // Hide all meeples who are on the board&lt;br /&gt;
     dojo.query( &#039;#board .meeple&#039; ).style( &#039;display&#039;, &#039;none&#039; );&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Vanilla JS query&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
  var cards=document.querySelectorAll(&amp;quot;.hand .card&amp;quot;);// all cards in all hands&lt;br /&gt;
  var cards=$(&#039;hand&#039;).querySelectorAll(&amp;quot;.card&amp;quot;);// all cards in specific hand&lt;br /&gt;
  var card=document.querySelector(&amp;quot;.hand .card&amp;quot;);// first card or null if none (super handy)&lt;br /&gt;
&lt;br /&gt;
=== Creating and Destroying elements ===&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;dojo.empty(node: ElementOrId)&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Remove all children of the node element&lt;br /&gt;
   dojo.empty(&#039;my_hand&#039;);&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;dojo.destroy(node: ElementOrId)&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Remove the element&lt;br /&gt;
   dojo.destroy(&#039;my_token&#039;);&lt;br /&gt;
&lt;br /&gt;
   dojo.query(&amp;quot;.green&amp;quot;, mynode).forEach(dojo.destroy); // this remove all subnode of class green from mynode&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;dojo.create(tag: string, attributes?: obj, parent?: ElementOrId): Element&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Create element&lt;br /&gt;
&lt;br /&gt;
    dojo.create(&amp;quot;div&amp;quot;, { class: &amp;quot;yellow_arrow&amp;quot; }, parent); // this creates div with class yellow_array and places it in &amp;quot;parent&amp;quot;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.format_block(name: string, args: object): string&#039;&#039;&#039;&lt;br /&gt;
This bga function that takes global var from template file and substitute variables, typical use would be&lt;br /&gt;
&lt;br /&gt;
                var player = gamedatas.players[player_id];&lt;br /&gt;
                var div = this.format_block(&#039;jstpl_player_board&#039;, player ); // var jstpl_player_board = ... is defined in .tpl file &lt;br /&gt;
Note: result is trimmed&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.format_string(name: string, args: object): string&#039;&#039;&#039;&lt;br /&gt;
This bga function just substitute variables in a string, i.e.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
     var div = this.format_string(&#039;&amp;lt;div color=&amp;quot;${player_color}&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&#039;, {player_color: &#039;#ff0000&#039;} );&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Note: result is trimmed&lt;br /&gt;
&lt;br /&gt;
Note: this can be replaced by using backquoted string now: &lt;br /&gt;
     const player_color =  &#039;#ff0000&#039;;&lt;br /&gt;
     const div = `&amp;lt;div color=&amp;quot;${player_color}&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;`;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.format_string_recursive&#039;&#039;&#039;&lt;br /&gt;
This bga function is similar to this.format_string but is capable of processing recursive argument structures and translations. It is used to format server notifications.&lt;br /&gt;
&lt;br /&gt;
TODO: find better place for these function docs&lt;br /&gt;
&lt;br /&gt;
=== Moving elements ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;dojo.place(node: string | Element, refNode: ElementOrId, pos?: string | number): Element&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
dojo.place is the best function to insert HTML code somewhere in your game interface without breaking something. It is much better to use than the &#039;&#039;&#039;innerHTML=&#039;&#039;&#039; method if you must insert HTML tags and not only values.&lt;br /&gt;
&lt;br /&gt;
node: &lt;br /&gt;
&lt;br /&gt;
Can be a String or a DOM node. If it is a string starting with “&amp;lt;”, it is assumed to be an HTML fragment, which will be created. Otherwise it is assumed to be an id of a DOM node.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
     // Insert your HTML code as a child of a container element&lt;br /&gt;
     dojo.place( &amp;quot;&amp;lt;div class=&#039;foo&#039;&amp;gt;&amp;lt;/div&amp;gt;&amp;quot;, &amp;quot;your_container_element_id&amp;quot; );&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
pos:&lt;br /&gt;
&lt;br /&gt;
Optional argument. Can be a number or one of the following strings: “before”, “after”, “replace”, “only”, “first”, or “last”. If omitted, “last” is assumed. &lt;br /&gt;
&lt;br /&gt;
&amp;quot;replace&amp;quot;: Replace the container element with my_node element&lt;br /&gt;
&lt;br /&gt;
&amp;quot;first&amp;quot;: Places the node as a child of the reference node. The node is placed as the first child.&lt;br /&gt;
&lt;br /&gt;
&amp;quot;last&amp;quot; (default): Places the node as a child of the reference node. The node is placed as the last child.&lt;br /&gt;
&lt;br /&gt;
&amp;quot;before&amp;quot;: places the node right before the reference node.&lt;br /&gt;
&lt;br /&gt;
&amp;quot;after&amp;quot;: places the node right after the reference node.&lt;br /&gt;
&lt;br /&gt;
&amp;quot;only&amp;quot;: replaces all children of the reference node with the node.&lt;br /&gt;
&lt;br /&gt;
positive integer: This parameter can be a positive integer. In this case, the node will be placed as a child of the reference node with this number (counting from 0). If the number is more than number of children, the node will be appended to the reference node making it the last child. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
     // Replace all children of container with my_node &lt;br /&gt;
     dojo.place( $(&#039;my_node&#039;), &amp;quot;your_container_element_id&amp;quot;, &amp;quot;only&amp;quot; );&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
See also full doc on dojo.place: [https://dojotoolkit.org/reference-guide/1.7/dojo/place.html]&lt;br /&gt;
&lt;br /&gt;
Usually, when you want to insert some piece of HTML in your game interface, you should use &amp;quot;[[Game_layout:_view_and_template:_yourgamename.view.php_and_yourgamename_yourgamename.tpl#Javascript_templates|Javascript templates]]&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
But you can also relocate elements like that. Note: it won&#039;t animate if you do that.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.placeOnObject(mobile_obj: ElementOrId, target_obj: ElementOrId): void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
places mobile_obj on target_obj, set the absolute positions and centers the mobile_obj on target_obj,&lt;br /&gt;
effect is immediate&lt;br /&gt;
&lt;br /&gt;
This is not really an animation, but placeOnObject is frequently used before starting an animation.&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  // (We just created an object &amp;quot;my_new_token&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
  // Place the new token on current player board&lt;br /&gt;
  this.placeOnObject( &amp;quot;my_new_token&amp;quot;, &amp;quot;overall_player_board_&amp;quot;+this.player_id );&lt;br /&gt;
  &lt;br /&gt;
  // Then slide it to its position on the board&lt;br /&gt;
  this.slideToObject( &amp;quot;my_new_token&amp;quot;, &amp;quot;a_place_on_board&amp;quot; ).play();&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.placeOnObjectPos(mobile_obj: ElementOrId, target_obj: ElementOrId, target_x: number, target_y: number): void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
This method works exactly like placeOnObject, except than you can specify some (x,y) coordinates (in px). This way, the center of &amp;quot;mobile_obj&amp;quot; will be placed to the specified x,y position relatively to the center of &amp;quot;target_obj&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Note: the placement works differently from this.slideToObjectPos&#039;&#039;, since coordinates are calculated based on the center of objects.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.attachToNewParent(mobile_obj: ElementOrId, target_obj: ElementOrId): void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
With this method, you change the HTML parent of &amp;quot;mobile_obj&amp;quot; element without moving it. &lt;br /&gt;
&amp;quot;target_obj&amp;quot; is the new parent of this element. The beauty of &lt;br /&gt;
attachToNewParent is that the mobile_obj element DOES NOT MOVE during this process.&lt;br /&gt;
&lt;br /&gt;
What happens is that the method calculate a relative position of mobile_obj to make sure it does not move after the HTML parent changes.&lt;br /&gt;
&lt;br /&gt;
Why using this method?&lt;br /&gt;
&lt;br /&gt;
Changing the HTML parent of an element can be useful for the following reasons:&lt;br /&gt;
* When the HTML parent moves, all its child are moving with them. If some game elements is no more linked with a parent HTML object, you may want to attach it to another place.&lt;br /&gt;
* The z_order (vertical order of display) depends on the position in the DOM, so you may need to change the parent of some game elements when they are moving in your game area.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;CAREFUL&#039;&#039;&#039;: this function destroys original object and places a clone onto a new parent, this will break all references to this HTML element (ex: dojo.connect).&lt;br /&gt;
If you need version that does not destroy the object but the same otherwise see [[BGA_Studio_Cookbook#Attach_to_new_parent_without_destroying_the_object]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Animations ==&lt;br /&gt;
&lt;br /&gt;
===Dojo Animations===&lt;br /&gt;
&lt;br /&gt;
BGA animations is based on Dojo Animation ([http://dojotoolkit.org/documentation/tutorials/1.8/animation/ see tutorial here]).&lt;br /&gt;
&lt;br /&gt;
However, most of the time, you can just use methods below, which are built on top of Dojo Animation.&lt;br /&gt;
&lt;br /&gt;
Note: one interesting method from Dojo that could be useful from time to time is &amp;quot;Dojo.Animation&amp;quot;. It allows you to make any CSS property &amp;quot;slide&amp;quot; from one value to another.&lt;br /&gt;
&lt;br /&gt;
Note 2: the slideTo methods are not compatible with CSS transform (scale, zoom, rotate...). If possible, avoid using CSS transform on nodes that are being slided. Eventually, the only possible solution to make these 2 compatible is to disable all CSS transform properties, use slideToObjectPos/placeOnObjectPos, and then apply them again.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Sliding===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.slideToObject(mobile_obj: ElementOrId, target_obj: ElementOrId, duration?: number, delay?: number): Animation&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
You can use slideToObject to &amp;quot;slide&amp;quot; an element to a target position.&lt;br /&gt;
&lt;br /&gt;
Sliding element on the game area is the recommended and the most used way to animate your game interface. Using slides allow players to figure out what is happening on the game, as if they were playing with the real boardgame.&lt;br /&gt;
&lt;br /&gt;
The parameters are:&lt;br /&gt;
* mobile_obj: the ID of the object to move. This object must be &amp;quot;relative&amp;quot; or &amp;quot;absolute&amp;quot; positioned.&lt;br /&gt;
* target_obj: the ID of the target object. This object must be &amp;quot;relative&amp;quot; or &amp;quot;absolute&amp;quot; positioned. Note that it is not mandatory that mobile_obj and target_obj have the same size. If their size are different, the system slides the center of mobile_obj to the center of target_obj.&lt;br /&gt;
* duration: (optional) defines the duration in millisecond of the slide. The default is 500 milliseconds.&lt;br /&gt;
* delay: (optional). If you defines a delay, the slide will start only after this delay. This is particularly useful when you want to slide several object from the same position to the same position: you can give a 0ms delay to the first object, a 100ms delay to the second one, a 200ms delay to the third one, ... this way they won&#039;t be superposed during the slide.&lt;br /&gt;
&lt;br /&gt;
BE CAREFUL: The method returns an dojo.fx animation, so you can combine it with other animation if you want to. It means that you have to call the &amp;quot;play()&amp;quot; method, otherwise the animation WON&#039;T START.&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
   this.slideToObject( &amp;quot;some_token&amp;quot;, &amp;quot;some_place_on_board&amp;quot; ).play();&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.slideToObjectPos(mobile_obj: ElementOrId, target_obj: ElementOrId, target_x: number, target_y: number, duration?: number, delay?: number): Animation&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
This method does exactly the same as &amp;quot;slideToObject&amp;quot;, except than you can specify some (x,y) coordinates. This way, &amp;quot;mobile_obj&amp;quot; will slide to the specified x,y position relatively to &amp;quot;target_obj&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
Example: slide a token to some place on the board, 10 pixels from the top:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
   this.slideToObjectPos( &amp;quot;some_token&amp;quot;, &amp;quot;some_place_on_board&amp;quot;, 0, 10 ).play();&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.slideTemporaryObject(mobile_obj_html: string, parent: ElementOrId, from: ElementOrId, to: ElementOrId, duration?: number, delay?: number): Animation&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
This method is useful when you want to slide a temporary HTML object from one place to another. As this object does not exists before the animation and won&#039;t remain after, it could be complex to create this object (with dojo.place), to place it at its origin (with placeOnObject) to slide it (with slideToObject) and to make it disappear at the end.&lt;br /&gt;
&lt;br /&gt;
slideTemporaryObject does all of this for you:&lt;br /&gt;
* mobile_obj_html is a piece of HTML code that represent the object to slide.&lt;br /&gt;
* parent is the ID of an HTML element of your interface that will be the parent of this temporary HTML object.&lt;br /&gt;
* from is the ID of the origin of the slide.&lt;br /&gt;
* to is the ID of the target of the slide.&lt;br /&gt;
* duration/delay works exactly like in &amp;quot;slideToObject&amp;quot;&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
this.slideTemporaryObject( &#039;&amp;lt;div class=&amp;quot;token_icon&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&#039;, &#039;tokens&#039;, &#039;my_origin_div&#039;, &#039;my_target_div&#039; ).play();&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Destroy===&lt;br /&gt;
&#039;&#039;&#039;this.slideToObjectAndDestroy(mobile_obj: ElementOrId, target_obj: ElementOrId, duration?: number, delay?: number): void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
This method is a handy shortcut to slide an existing HTML object to some place then destroy it upon arrival. It can be used for example to move a victory token or a card from the board to the player panel to show that the player earns it, then destroy it when we don&#039;t need to keep it visible on the player panel.&lt;br /&gt;
&lt;br /&gt;
It works the same as this.slideToObject and takes the same arguments, but it starts the animation. &lt;br /&gt;
&lt;br /&gt;
CAREFUL: Make sure nothing is creating the same object at the same time the animation is running, because this will cause some random disappearing effects&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
this.slideToObjectAndDestroy( &amp;quot;some_token&amp;quot;, &amp;quot;some_place_on_board&amp;quot;, 1000, 0 );&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.fadeOutAndDestroy( node: string | Element, duration?: number, delay?: number):&#039;&#039;&#039; &#039;&#039;&#039;void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
This function fade out the target node, then destroy it. Its starts the animation.&lt;br /&gt;
* duration/delay works exactly like in &amp;quot;slideToObject&amp;quot;&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
   this.fadeOutAndDestroy( &amp;quot;a_card_that_must_disappear&amp;quot; );&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
CAREFUL: the HTML node still exists until during few milliseconds, until the fadeOut has been completed.&lt;br /&gt;
Make sure nothing is creating same object at the same time as animation is running, because you will be some random dissapearing effects&lt;br /&gt;
&lt;br /&gt;
===Rotating elements===&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
This example combines &amp;quot;Dojo.Animation&amp;quot; method and a CSS property transform that allow you to rotate the element.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
// node is Element we rotating&lt;br /&gt;
		    var animation = new dojo.Animation({&lt;br /&gt;
			    curve: [fromDegree, toDegree],&lt;br /&gt;
			    onAnimate: (v) =&amp;gt; {&lt;br /&gt;
				    node.style.transform = &#039;rotate(&#039; + v + &#039;deg)&#039;;&lt;br /&gt;
			    } &lt;br /&gt;
		    });&lt;br /&gt;
		    &lt;br /&gt;
		    animation.play();  &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
BGA has its own interface to rotate&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.rotateTo(node: string | Element, degree: number): void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
It starts the animation, and stored the rotation degree in the class, so next time you rotate object - it is additive.&lt;br /&gt;
There is no animation hooks in this one, if you need to change any parameters use dojo animation above.&lt;br /&gt;
&lt;br /&gt;
There is also &#039;&#039;&#039;rotateInstantTo&#039;&#039;&#039; with same signature which does not animate&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Animation Callbacks===&lt;br /&gt;
&lt;br /&gt;
If you wish to run some code only after an animation has completed you can do this by linking a callback method to &#039;onEnd&#039;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
var animation_id = this.slideToObject( mobile_obj, target_obj, 500 );&lt;br /&gt;
dojo.connect(animation_id, &#039;onEnd&#039;, () =&amp;gt; {&lt;br /&gt;
   // do something here&lt;br /&gt;
});&lt;br /&gt;
animation_id.play();&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If you wish to call a second animation after the first (rather than general code) then you can use a dojo animation chain (see tutorial referenced above).&lt;br /&gt;
&lt;br /&gt;
== Players input ==&lt;br /&gt;
&lt;br /&gt;
=== Connecting ===&lt;br /&gt;
&#039;&#039;&#039;dojo.connect(element: Element, event: string, context: object, method: eventHandler): any&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;dojo.connect(element: Element, event: string, hander: eventHandler): any&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Used to associate a player event with one of your notification methods.&lt;br /&gt;
&lt;br /&gt;
Example: associate a click on an element (&amp;quot;my_element&amp;quot;) with one of our methods (&amp;quot;onClickOnMyElement&amp;quot;):&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
      dojo.connect( $(&#039;my_element&#039;), &#039;onclick&#039;, this, &#039;onClickOnMyElement&#039; );&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Same idea but base on query (i.e. all element of &#039;pet&#039; class)&lt;br /&gt;
      dojo.query(&amp;quot;.pet&amp;quot;).connect(&#039;onclick&#039;, this, &#039;onPet&#039;);&lt;br /&gt;
&lt;br /&gt;
Note: if you need to disconnect the handler you have to store handler returned from this method, i.e.&lt;br /&gt;
   &lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    var handler = dojo.connect(...);&lt;br /&gt;
    ...&lt;br /&gt;
    dojo.disconnect(handler);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If you don&#039;t store the handler - you have to destroy the object to disconnect it&lt;br /&gt;
&lt;br /&gt;
Typical function that implements the input handler will look like this&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
onPet: function(event) {&lt;br /&gt;
    var id = event.currentTarget.id;&lt;br /&gt;
    console.log(&#039;onPet &#039; + id);&lt;br /&gt;
    dojo.stopEvent(event);&lt;br /&gt;
    if (this.gamedatas.gamestate.name == &#039;playerTurnPet&#039;) {&lt;br /&gt;
          this.bgaPerformAction(&#039;actPlayPet&#039;, {card: id});&lt;br /&gt;
    } else {&lt;br /&gt;
          this.showMoveUnauthorized();&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.connect(element: ElementOrId, event: string, method: eventHandler): void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Used to associate a player event with one of your notification methods.&lt;br /&gt;
&lt;br /&gt;
      this.connect( $(&#039;my_element&#039;), &#039;onclick&#039;, &#039;onClickOnMyElement&#039; );&lt;br /&gt;
&lt;br /&gt;
Or you can use an in-place handler&lt;br /&gt;
&lt;br /&gt;
      this.connect( $(&#039;my_element&#039;), &#039;onclick&#039;, (e) =&amp;gt; { console.log(&#039;boo&#039;); } );&lt;br /&gt;
&lt;br /&gt;
Note that this function stores the connection handler. That is the only real difference between &#039;&#039;&#039;this.connect&#039;&#039;&#039; and &#039;&#039;&#039;dojo.connect&#039;&#039;&#039;. If you plan to destroy the element you connected, you &#039;&#039;&#039;must&#039;&#039;&#039; call this.disconnect() to prevent memory leaks.&lt;br /&gt;
This function is mainly for permanent objects - if you just want to connect the temp object you should probably not use this method but use dojo.connect which won&#039;t require any clean-up.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.connectClass(cssClassName: string, event: string, method: eventHandler): void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Same as connect(), but for all the nodes set with the specified cssClassName.&lt;br /&gt;
&lt;br /&gt;
	this.connectClass(&#039;pet&#039;, &#039;onclick&#039;, &#039;onPet&#039;);&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.disconnect(element: ElementOrId, event: string): void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Disconnect event handler (previously registered with this.connect or this.connectClass).&lt;br /&gt;
&lt;br /&gt;
   this.disconnect( $(&#039;my_element&#039;), &#039;onclick&#039;);&lt;br /&gt;
&lt;br /&gt;
Note: dynamic connect/disconnect is for advanced cases ONLY, you should always connect elements statically if possible, i.e. in setup() method.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.disconnectAll(): void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Disconnect all previously registed event handlers (registered via this.connect or this.connectClass)&lt;br /&gt;
&lt;br /&gt;
  this.disconnectAll();&lt;br /&gt;
&lt;br /&gt;
=== Actions ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.bgaPerformAction(action: string, args?: object, options: object = { lock: true, checkAction: true }): Promise&amp;lt;void&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Triggers an action on the backend. This is a combination of checkAction and ajaxcall, returning a Promise which resoves when ajaxcall ends.&lt;br /&gt;
&lt;br /&gt;
This method must be used to send a player input to the game server. &#039;&#039;&#039;It should not be triggered programmatically&#039;&#039;&#039;, especially not in loops, in callbacks, in notifications, or in onEnteringState/onUpdateActionButtons/onLeavingState, in order not to create race conditions or break replay game and tutorial features. It should be used only in reaction to a user action in the interface.&lt;br /&gt;
&lt;br /&gt;
* action: name of the action, as it is written in &amp;quot;possibleactions&amp;quot; of the current state.&lt;br /&gt;
* args: an object containing the call parameters to send to the action&lt;br /&gt;
* options: options to tweak the call with some defaults. Default is &amp;lt;code&amp;gt;{ lock: true, checkAction: true }&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Example of a standard call without args:&lt;br /&gt;
  this.bgaPerformAction(&#039;pass&#039;);&lt;br /&gt;
&lt;br /&gt;
Example of a standard call with action args:&lt;br /&gt;
  this.bgaPerformAction(&#039;actPlayCard&#039;, { id: this.selectedCardId });&lt;br /&gt;
&lt;br /&gt;
Example of a call without checking action (because player is inactive in a multiactive state):&lt;br /&gt;
&lt;br /&gt;
 this.bgaPerformAction(&#039;actChangeMind&#039;, {}, { checkAction: false });&lt;br /&gt;
&lt;br /&gt;
Example of a call without lock (because of a special action not directly related to the game flow):&lt;br /&gt;
&lt;br /&gt;
 this.bgaPerformAction(&#039;actSetAutoBid&#039;, { alwaysBidUntil: 500 }, { lock: false, checkAction: false });&lt;br /&gt;
&lt;br /&gt;
Example of call with reaction to exception:&lt;br /&gt;
  this.bgaPerformAction(&#039;actPlayCard&#039;, { id: this.selectedCardId }).catch(()=&amp;gt;{ this.selectedCardId = undefined; });&lt;br /&gt;
&lt;br /&gt;
Example of call with reaction to success:&lt;br /&gt;
  this.bgaPerformAction(&#039;actPlayCard&#039;, { id: this.selectedCardId }).then(()=&amp;gt;{ this.unselectAll(); });&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.ajaxcall(url, parameters, obj_callback, callback, callback_anycase?, ajax_method?: string)&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Note: bgaPerformAction is a simpler way to use ajax calls, ajaxcall stays in the doc for legacy reasons only and should not be used in new projects.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Same warning as &#039;&#039;&#039;this.bgaPerformAction&#039;&#039;&#039; about using on user action only.&lt;br /&gt;
&lt;br /&gt;
* url: the url of the action to perform. For a game, it must be: &amp;quot;/&amp;lt;mygame&amp;gt;/&amp;lt;mygame&amp;gt;/myAction.html&amp;quot;&lt;br /&gt;
* parameters: an array of parameter to send to the game server. &lt;br /&gt;
** Note that &amp;quot;lock: true&amp;quot; must always be specified in this list of parameters in order the interface can be locked during the server call. Cannot use lock: false - to not lock it has to be undefined.&lt;br /&gt;
** Note: Restricted parameter names (please don&#039;t use them):&lt;br /&gt;
*** &amp;quot;action&amp;quot;&lt;br /&gt;
*** &amp;quot;module&amp;quot;&lt;br /&gt;
*** &amp;quot;class&amp;quot;&lt;br /&gt;
* obj_callback: must be set to &amp;quot;this&amp;quot;.&lt;br /&gt;
* callback (non-optional but rarely used): a function to trigger when the server returns result and everything went fine (not used, as all data handling is done via notifications).&lt;br /&gt;
* callback_anycase: (optional) a function to trigger when the server returns ok OR error.  If no error this function is called with parameter value false. If an error occurred, the first parameter will be set to true, the second will contain the error message sent by the PHP back-end, and the third will contain an error code.&lt;br /&gt;
* ajax_method: (optional and rarely used) if you need to send large amounts of data (over 2048 bytes), you can set this parameter to &#039;post&#039; (all lower-case) to send a POST request as opposed to the default GET. This works, but was not officially documented, so only use if you really need to.&lt;br /&gt;
&lt;br /&gt;
Usage:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
this.ajaxcall( &#039;/mygame/mygame/actMyAction.html&#039;, { lock: true, &lt;br /&gt;
   arg1: myarg1, &lt;br /&gt;
   arg2: myarg2&lt;br /&gt;
}, this, (result)=&amp;gt;{} );&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.checkAction(action: string, nomessage?: boolean): boolean &#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Check if player can do the specified action by taking into account:&lt;br /&gt;
* if interface is locked it will return false and show message &amp;quot;An action is already in progress&amp;quot;,  unless nomessage set to true &lt;br /&gt;
* if player is not active it will return false and show message &amp;quot;This is not your turn&amp;quot;, unless nomessage set to true &lt;br /&gt;
* if action is not in list in possible actions (defined by &amp;quot;possibleaction&amp;quot; in current game state) it will return false and show &amp;quot;This move is not authorized now&amp;quot; error (unconditionally).&lt;br /&gt;
* otherwise returns true&lt;br /&gt;
Example:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  function onClickOnGameElement( evt )  {&lt;br /&gt;
     if( this.checkAction( &amp;quot;actMyAction&amp;quot; ) ) {&lt;br /&gt;
        // Do the action&lt;br /&gt;
     }&lt;br /&gt;
  }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.checkPossibleActions(action: string): boolean&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
* this is independent of the player being active, so can be used instead of this.checkAction(). This is particularly useful for multiplayer states when the player is not active in a &#039;player may like to change their mind&#039; scenario. Unlike this.checkAction, this function does NOT take interface locking into account &lt;br /&gt;
&lt;br /&gt;
* if action is not in list in possible actions (defined by &amp;quot;possibleaction&amp;quot; in current game state) it will return false and show &amp;quot;This move is not authorized now&amp;quot; error (unconditionally).&lt;br /&gt;
* otherwise returns true&lt;br /&gt;
&lt;br /&gt;
  function onChangeMyMind( evt )  {&lt;br /&gt;
     if( this.checkPossibleActions( &amp;quot;actMyAction&amp;quot; ) ) {&lt;br /&gt;
        // Do the action&lt;br /&gt;
     }&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.checkLock(nomessage?: boolean): boolean&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
When using &amp;quot;lock: true&amp;quot; in ajax call you can use this function to check if interface is in lock state (it will be locked during server call and notification processing).&lt;br /&gt;
This check can be used to block some other interactions which do not result in ajaxcall or if you want to suppress errors. Note: normally you only need to use this.checkAction(...), this is for advanced cases.&lt;br /&gt;
&lt;br /&gt;
It will also show error unless nomessage is set to true&lt;br /&gt;
&lt;br /&gt;
  function onChangeMyMind( evt )  {&lt;br /&gt;
     if( this.checkLock() ) {&lt;br /&gt;
        // Do the action&lt;br /&gt;
     }&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
== Notifications ==&lt;br /&gt;
&lt;br /&gt;
When something happens on the server side, your game interface Javascript logic received a notification.&lt;br /&gt;
If you have not done so yet check what notification are in [[Main_game_logic:_yourgamename.game.php#Notifications]]&lt;br /&gt;
&lt;br /&gt;
Here&#039;s how you can handle these notifications on the client side.&lt;br /&gt;
&lt;br /&gt;
=== Subscribe to notifications ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;dojo.subscribe(notif_type: string, callback_obj: Object, handler: string|handler)&#039;&#039;&#039;&lt;br /&gt;
* notif_type - notification type/name send by php server&lt;br /&gt;
* callback_obj - usually this&lt;br /&gt;
* handler - if string method of callback_obj with name name is called, when notification is called, with notification object as parameter (see below)&lt;br /&gt;
&lt;br /&gt;
Your Javascript &amp;quot;setupNotifications&amp;quot; method is the place where you can subscribe to notifications from your PHP code.&lt;br /&gt;
&lt;br /&gt;
Here&#039;s how you associate one of your Javascript method to a notification &amp;quot;playDisc&amp;quot; (from Reversi example):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
   setupNotifications: function() {&lt;br /&gt;
      ...&lt;br /&gt;
      dojo.subscribe(&#039;playDisc&#039;, this, &amp;quot;notif_playDisc&amp;quot;);&lt;br /&gt;
   },&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note: the &amp;quot;playDisc&amp;quot; corresponds to the name of the notification you define it in your PHP code, in your &amp;quot;notifyAllPlayers&amp;quot; or &amp;quot;notifyPlayer&amp;quot; method.&lt;br /&gt;
&lt;br /&gt;
Then, you have to define your &amp;quot;notif_playDisc&amp;quot; method:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
   notif_playDisc: function(notif) {&lt;br /&gt;
     // Remove current possible moves (makes the board more clear)&lt;br /&gt;
     dojo.query( &#039;.possibleMove&#039; ).removeClass( &#039;possibleMove&#039; );          &lt;br /&gt;
     this.addDiscOnBoard( notif.args.x, notif.args.y, notif.args.player_id );&lt;br /&gt;
   },&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In a notification handler like our &amp;quot;notif_playDisc&amp;quot; method, you can access all notifications arguments with &amp;quot;notif.args&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&lt;br /&gt;
PHP&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    $this-&amp;gt;notifyAllPlayers( &amp;quot;apples&amp;quot;, clienttranslate(&#039;player takes ${count} apples&#039;), [ &amp;quot;count&amp;quot; =&amp;gt; 3 ] );&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
JavaScript&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    setupNotifications: function() {&lt;br /&gt;
       dojo.subscribe( &#039;apples&#039;, this, &#039;notif_apples&#039; );&lt;br /&gt;
    },&lt;br /&gt;
&lt;br /&gt;
    notif_apples: function(notif) {&lt;br /&gt;
      //You can access the &amp;quot;count&amp;quot; like this:&lt;br /&gt;
       alert(&amp;quot;count = &amp;quot; + notif.args.count);&lt;br /&gt;
    }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== The notification Object received by client ===&lt;br /&gt;
&lt;br /&gt;
When sending a notification on your PHP, the client side will receive an Object with the following attributes:&lt;br /&gt;
&lt;br /&gt;
* type - type of the notification (as passed by php function)&lt;br /&gt;
* log - the log string passed from php notification&lt;br /&gt;
* args - This is the arguments that you passed on your notification method on php&lt;br /&gt;
* bIsTableMsg - is true when you use [[Main_game_logic:_yourgamename.game.php#NotifyAllPlayers|NotifyAllPlayers]] method (false otherwise)&lt;br /&gt;
* channelorig - information about table ID (formatted as : &amp;quot;/table/t[TABLE_NUMBER]&amp;quot;)&lt;br /&gt;
* gamenameorig - name of the game&lt;br /&gt;
* move_id - ID of the move associated with the notification&lt;br /&gt;
* table_id - ID of the table (comes as string)&lt;br /&gt;
* time - UNIX GMT timestamp&lt;br /&gt;
* uid - unique identifier of the notification&lt;br /&gt;
* h - unknown&lt;br /&gt;
&lt;br /&gt;
&#039;&#039; Note that those information were inferred from observation on console log. If an Admin can confirm/correct (and remove this line), you&#039;re welcome :)&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
=== Ignoring notifications ===&lt;br /&gt;
&lt;br /&gt;
Sometimes you need to ignore some notification on client side. You don&#039;t want them to be shown in game log and you don&#039;t want them to be handled.&lt;br /&gt;
&lt;br /&gt;
The most common use case is when a player gets private information. They will receive a specific notification (such as &amp;quot;You received Ace of Heart&amp;quot;), while other players would receive more generic notification (&amp;quot;Player received a card&amp;quot;).&lt;br /&gt;
&lt;br /&gt;
In X.game.php&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        $this-&amp;gt;notifyAllPlayers(&amp;quot;dealCard&amp;quot;, clienttranslate(&#039;${player_name} received a card&#039;), [&lt;br /&gt;
            &#039;player_id&#039; =&amp;gt; $playerId,&lt;br /&gt;
            &#039;player_name&#039; =&amp;gt; $this-&amp;gt;getActivePlayerName()&lt;br /&gt;
        ]);&lt;br /&gt;
&lt;br /&gt;
        $this-&amp;gt;notifyPlayer($playerId, &amp;quot;dealCardPrivate&amp;quot;, clienttranslate(&#039;You received ${cardName}&#039;), [&lt;br /&gt;
            &amp;quot;type&amp;quot; =&amp;gt; $card[&amp;quot;type&amp;quot;],&lt;br /&gt;
            &amp;quot;cardName&amp;quot; =&amp;gt; $this-&amp;gt;getCardName($card[&amp;quot;type&amp;quot;])&lt;br /&gt;
        ]);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The problem with this approach is that the active player will receive two notifications:&lt;br /&gt;
* Player1 received a card&lt;br /&gt;
* You received Ace of Hearts&lt;br /&gt;
&lt;br /&gt;
Hence, notification ignoring.&lt;br /&gt;
&lt;br /&gt;
NOTE: You can think that it would be possible to send such notification to all players except active just by using notifyPlayer and it seems to work. The problem however is that table spectators would miss such notification and their user interface (and game log) wouldn&#039;t be updated. Since there is no way to send notification just to spectators, ignoring the notification (or &amp;quot;filtering&amp;quot;) is the only reasonable solution.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;setIgnoreNotificationCheck(notif_type: string, predicate: ((notif: Notif)=&amp;gt;boolean))&#039;&#039;&#039;&lt;br /&gt;
This method will set a check whether any of notifications of specific type should be ignored.&lt;br /&gt;
&lt;br /&gt;
The parameters are:&lt;br /&gt;
* notif_type: type of the notification &lt;br /&gt;
* predicate (notif =&amp;gt; boolean): a function that will receive notif object and will return true if this specific notification should be ignored&lt;br /&gt;
&lt;br /&gt;
Before dispatching any notification of this type, the framework will call predicate to check whether notification should be ignored, if it return true - the notification will be dispatched, i.e. logged or handled.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    this.notifqueue.setIgnoreNotificationCheck( &#039;dealCard&#039;, (notif) =&amp;gt; (notif.args.player_id == this.player_id) );&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
IMPORTANT: Remember that this notification is ignored on the client side, but was still received by the client. Therefore it shouldn&#039;t contain any private information as cheaters can get it. In other words this is not a way to hide information.&lt;br /&gt;
&lt;br /&gt;
IMPORTANT: When a game is reloaded with F5 or when opening a turn based game, old notifications are replayed as history notification. They are used just to update the game log and are stripped of all arguments except player_id, i18n and any argument present in message. If you use and other argument in your predicate you should &#039;&#039;&#039;preserve&#039;&#039;&#039; it as explained [[Main_game_logic:_yourgamename.game.php#Notify_players|here]].&lt;br /&gt;
&lt;br /&gt;
=== Synchronous notifications ===&lt;br /&gt;
&lt;br /&gt;
When several notifications are received by your game interface, these notifications are processed immediately, one after the other, in the same exact order they have been generated in your PHP game logic.&lt;br /&gt;
&lt;br /&gt;
However, sometimes, you need to give some time to the players to figure out what happened on the game before jumping to the next notification. Indeed, in many games, there are a lot of automatic actions, and the computer is going to resolve all these actions very fast if you don&#039;t tell it not to do so.&lt;br /&gt;
&lt;br /&gt;
As an example, for Reversi, when someone is playing a disc, we want to wait 500 milliseconds before doing anything else in order the opponent player can figure out what move has been played.&lt;br /&gt;
&lt;br /&gt;
Here&#039;s how we do this, right after our subscription:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    dojo.subscribe( &#039;playDisc&#039;, this, &amp;quot;notif_playDisc&amp;quot; );&lt;br /&gt;
    this.notifqueue.setSynchronous( &#039;playDisc&#039;, 500 );   // Wait 500 milliseconds after executing the playDisc handler&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
-----&lt;br /&gt;
&lt;br /&gt;
It is also possible to control the delay timing dynamically (e.g., using notification args). As an example, maybe your notification &#039;cardPlayed&#039; should pause for a different amount of time depending on the number or type of cards played.&lt;br /&gt;
&lt;br /&gt;
For this case, use &#039;&#039;&#039;setSynchronous&#039;&#039;&#039; without specifying the duration and use &#039;&#039;&#039;setSynchronousDuration&#039;&#039;&#039; within the notification callback.&lt;br /&gt;
&lt;br /&gt;
* NOTE: If you forget to invoke &#039;&#039;&#039;setSynchronousDuration&#039;&#039;&#039;, the game will remain paused forever!&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
setupNotifications: function () {&lt;br /&gt;
    dojo.subscribe( &#039;cardPlayed&#039;, this, &#039;notif_cardPlayed&#039; );&lt;br /&gt;
    this.notifqueue.setSynchronous( &#039;cardPlayed&#039; ); // wait time is dynamic&lt;br /&gt;
    ...&lt;br /&gt;
},&lt;br /&gt;
&lt;br /&gt;
notif_cardPlayed: function (notif) {&lt;br /&gt;
    // MUST call setSynchronousDuration&lt;br /&gt;
&lt;br /&gt;
    // Example 1: From notification args (PHP)&lt;br /&gt;
    this.notifqueue.setSynchronousDuration(notif.args.duration);&lt;br /&gt;
    ...&lt;br /&gt;
&lt;br /&gt;
    // Or, example 2: Match the duration to a Dojo animation&lt;br /&gt;
    var anim = dojo.fx.combine([&lt;br /&gt;
        ...&lt;br /&gt;
    ]);&lt;br /&gt;
    anim.play();&lt;br /&gt;
    this.notifqueue.setSynchronousDuration(anim.duration);&lt;br /&gt;
},&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You can also manually call this.notifqueue.setSynchronousDuration(0) once client operations are finished, but be careful that even fast replay still has a path to call it.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;WARNING: combining synchronous and ignored notifications&#039;&#039;&#039;&lt;br /&gt;
You must be careful when combining dynamic synchronous durations (as described above) with ignored notifications. If you have a conditionally ignored notification like this (see below section):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;this.notifqueue.setIgnoreNotificationCheck( &#039;myNotif&#039;, (notif) =&amp;gt; (notif.args.player_id == this.player_id) /* or any other condition */ )&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
then you CANNOT do&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;this.notifqueue.setSynchronous(&#039;myNotif&#039;);&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
as, when the ignored check passes, the notification handler, in which `this.notifqueue.setSychronousDuration` is called, is never called and so the duration is never set and interface locking results.&lt;br /&gt;
&lt;br /&gt;
The workaround is to set a &amp;quot;dummy&amp;quot; time:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;this.notifqueue.setSynchronous(&#039;myNotif&#039;, 5000);&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
whose value is irrelevant but must be large enough to cover the time before the notification handler is called. The large value never actually comes into play because the notification is either ignored, or the synchronous duration is reset to a sensible value inside the handler.&lt;br /&gt;
&lt;br /&gt;
=== Pre-defined notification types ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;tableWindow&#039;&#039;&#039; - This defines notification to display [[Game_interface_logic:_yourgamename.js#Scoring_dialogs|Scoring Dialogs]], see below.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;message&#039;&#039;&#039; - This defines notification that shows on players log and have no other effect (technically any unhandled notification will do the same but its recommended to use this keyword for consistency)&lt;br /&gt;
&lt;br /&gt;
   // You can call this on php side without doing anything on client side&lt;br /&gt;
    self::notifyAllPlayers( &#039;message&#039;, clienttranslate(&#039;hello&#039;), [] );&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;simplePause&#039;&#039;&#039; - This notification will just delay other notifications, maybe useful if you know you need some extra time for animation or something. Requires a time parameter.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    self::notifyAllPlayers( &#039;simplePause&#039;, &#039;&#039;, [ &#039;time&#039; =&amp;gt; 500] ); // time is in milliseconds&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note: the following types are RESERVED by framework, do not use:&lt;br /&gt;
&lt;br /&gt;
gameStateChange gameStateChangePrivateArg gameStateMultipleActiveUpdate newActivePlayer playerstatus yourturnack clockalert tableInfosChanged playerEliminated tableDecision  archivewaitingdelay end_archivewaitingdelay replaywaitingdelay end_replaywaitingdelay replayinitialwaitingdelay end_replayinitialwaitingdelay aiPlayerWaitingDelay replay_has_ended updateSpectatorList  wouldlikethink updateReflexionTime undoRestorePoint resetInterfaceWithAllDatas zombieModeFail zombieModeFailWarning aiError skipTurnOfPlayer zombieBack allPlayersAreZombie gameResultNeutralized playerConcedeGame showTutorial showCursor showCursorClick skipTurnOfPlayerWarning  banFromTable resultsAvailable switchToTurnbased newPrivateState infomsg&lt;br /&gt;
&lt;br /&gt;
== Tooltips ==&lt;br /&gt;
&lt;br /&gt;
=== Adding static tooltips ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.addTooltip(nodeId: string, helpStringTranslated: string, actionStringTranslated: string, delay?: number): void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Add a simple text tooltip to the DOM node.&lt;br /&gt;
&lt;br /&gt;
Specify &#039;helpStringTranslated&#039; to display some information about &amp;quot;what is this game element?&amp;quot;.&lt;br /&gt;
Specify &#039;actionStringTranslated&#039; to display some information about &amp;quot;what happens when I click on this element?&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
You must specify both of the strings. You can only use one and specify an empty string (&#039;&#039;) for the other one.&lt;br /&gt;
&lt;br /&gt;
When you pass text directly function _() must be used for the text to be marked for translation! Except for empty string.&lt;br /&gt;
&lt;br /&gt;
Parameter &amp;quot;delay&amp;quot; is optional. It is primarily used to specify a zero delay for some game element when the tooltip gives really important information for the game - but remember: no essential information must be placed in tooltips as they won&#039;t be displayed in some browsers (see [[BGA_Studio_Guidelines|Guidelines]]).&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
   this.addTooltip( &#039;cardcount&#039;, _(&#039;Number of cards in hand&#039;), &#039;&#039; );&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note: this generates static tooltip and attaches to existing dom element, if you need to generate tooltip more dynamically you have to call that method every time information about object is updated or use completely different tehnique, see dynamic tooltips below.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.addTooltipHtml(nodeId: string, html: string, delay?: number): void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Add an HTML tooltip to the DOM node (for more elaborate content such as presenting a bigger version of a card).&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.addTooltipToClass(cssClass: string, helpStringTranslated: string, actionStringTranslated: string, delay?: number ): void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Add a simple text tooltip to all the DOM nodes set with this cssClass. See more details above for this.addTooltip.&lt;br /&gt;
     this.addTooltipToClass( &#039;meeple&#039;, _(&#039;This is A Meeple&#039;), _(&#039;Click to tickle&#039;) );&lt;br /&gt;
&lt;br /&gt;
IMPORTANT: all concerned nodes must exist and have IDs to get tooltips.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.addTooltipHtmlToClass(cssClass: string, html: string, delay?: number): void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Add an HTML tooltip to to all the DOM nodes set with this cssClass (for more elaborate content such as presenting a bigger version of a card).&lt;br /&gt;
&lt;br /&gt;
IMPORTANT: all concerned nodes must exist and have IDs to get tooltips.&lt;br /&gt;
&lt;br /&gt;
=== Removing static tooltips ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.removeTooltip(nodeId: string): void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Remove a tooltip from the DOM node with given id.&lt;br /&gt;
&lt;br /&gt;
=== Advanced tooltips ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;force tooltip to open&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
If you want to force tooltip to open in reaction to some other action, i.e. click you can do this&lt;br /&gt;
&lt;br /&gt;
   this.tooltips[id].open(id)&lt;br /&gt;
&lt;br /&gt;
where id is the id of the tooltip node where tooltip was installed.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;dynamic tooltips&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
See [[BGA_Studio_Cookbook#Dynamic_tooltips]]&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;tooltips on mobile&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Tooltips is very unreliable on mobile, it is recommended to implement some other method to obtaining same information,&lt;br /&gt;
such as simple click handler in dedicated &amp;quot;Help&amp;quot; mode or provide dedicated clickable areas such as corner of card.&lt;br /&gt;
&lt;br /&gt;
== Warning messages ==&lt;br /&gt;
&lt;br /&gt;
Sometimes, there is something important that is happening in the game and you have to make sure all players get the message. Most of the time, the evolution of the game situation or the game log is enough, but sometimes you need something more visible.&lt;br /&gt;
&lt;br /&gt;
Ex: someone fulfills one of the end of the game conditions, so this is the last turn.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.showMessage(msg: string, type: string): void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
showMessage shows a message in a big rectangular area on the top of the screen of the current player, and it dissapears after few seconds (also it will be in the log in some cases).&lt;br /&gt;
&lt;br /&gt;
* &amp;quot;msg&amp;quot; is the string to display. It should be translated.&lt;br /&gt;
* &amp;quot;type&amp;quot; can be set to &amp;quot;info&amp;quot;, &amp;quot;error&amp;quot;, &amp;quot;only_to_log&amp;quot; or custom string. If set to &amp;quot;info&amp;quot;, the message will be an informative message on a white background. If set to &amp;quot;error&amp;quot;, the message will be an error message on a red background and it will be added to log. If set to &amp;quot;only_to_log&amp;quot;, the message will be added to the game log but will not popup at the top of the screen.&lt;br /&gt;
If set to custom string, it will be transparent, to use custom type define &amp;quot;head_xxx&amp;quot; in css, where xxx is the type. For example if you want yellow warning, use &amp;quot;warning&amp;quot; as type and add this to css:&lt;br /&gt;
 .head_warning {&lt;br /&gt;
    background-color: #e6c66e;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
Important: the normal way to inform players about the progression of the game is the game log. The &amp;quot;showMessage&amp;quot; is intrusive and should not be used often.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    notif_messageinfo: function(notif) {&lt;br /&gt;
	if (!g_archive_mode) {&lt;br /&gt;
        	var message = this.format_string_recursive(notif.log, notif.args);&lt;br /&gt;
		this.showMessage(_(&#039;Announcement:&#039;) + &amp;quot; &amp;quot; + message, &#039;info&#039;);		&lt;br /&gt;
         }&lt;br /&gt;
    },&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Show message could be used on the client side to prevent user wrong moves before it is send to server.&lt;br /&gt;
Example from &#039;battleship&#039;:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
onGrid: function(event) {&lt;br /&gt;
     if (checkIfPlayerTriesToFireOnThemselves(event)) {&lt;br /&gt;
        this.showMessage(_(&#039;This is your own board silly!&#039;), &#039;error&#039;);&lt;br /&gt;
        return;&lt;br /&gt;
     }&lt;br /&gt;
     ...&lt;br /&gt;
},&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.showMoveUnauthorized(): void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Shows predefined user error that move is unauthorized now&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
onPet: function(event) {&lt;br /&gt;
     if (checkPet(event)==false) {&lt;br /&gt;
        this.showMoveUnauthorized();&lt;br /&gt;
        return;&lt;br /&gt;
     }&lt;br /&gt;
     ...&lt;br /&gt;
},&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Dialogs ==&lt;br /&gt;
&lt;br /&gt;
=== Confirmation dialog ===&lt;br /&gt;
&lt;br /&gt;
When an important action with a lot of consequences is triggered by the player, you may want to propose a confirmation dialog.&lt;br /&gt;
&lt;br /&gt;
CAREFUL: the general guideline of BGA is to AVOID the use of confirmation dialogs. Confirmation dialogs slow down the game and bother players. The players know that they have to pay attention to each move when they are playing online.&lt;br /&gt;
&lt;br /&gt;
The situations where you should use a confirmation dialog are the following:&lt;br /&gt;
* It must not happen very often during a game.&lt;br /&gt;
* It must be linked to an action that can really &amp;quot;kill a game&amp;quot; if the player does not pay attention.&lt;br /&gt;
* It must be something that can be done by mistake (ex: a link on the action status bar).&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.confirmationDialog(message: string, yesHandler: (param: any) =&amp;gt; void, noHandler?: (param: any) =&amp;gt; void, param?: any): void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
* message - message will be shown to user, use _() to translate&lt;br /&gt;
* yesHandler - non-optional handler to be called on yes&lt;br /&gt;
* noHandler - optional handler to called on no&lt;br /&gt;
* param - if specified, it will be passed to both handlers&lt;br /&gt;
NOTE: this is async function, it does not return anything and you should not do anything after, you must do everything in handlers&lt;br /&gt;
&lt;br /&gt;
How to display a confirmation dialog:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    this.confirmationDialog(_(&amp;quot;Are you sure you want to bake a pie?&amp;quot;), () =&amp;gt; {&lt;br /&gt;
      this.bakeThePie();&lt;br /&gt;
    });&lt;br /&gt;
    return; // nothing should be called or done after calling this, all action must be done in the handler&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
With param and both handlers&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    this.confirmationDialog(_(&amp;quot;Are you sure you want to bake a pie?&amp;quot;), &lt;br /&gt;
           (ingredient) =&amp;gt; this.bakeThePie(ingredient), &lt;br /&gt;
           (ingredient) =&amp;gt; console.log(`cancelled baking of ${ingredient}`), &lt;br /&gt;
           &#039;apple&#039;);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Multiple choice dialog ===&lt;br /&gt;
&lt;br /&gt;
You can use this dialog to give user a choice with small amount of options&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.multipleChoiceDialog(message: string, choices: string[], callback: (choice: number) =&amp;gt; void): void&#039;&#039;&#039;&lt;br /&gt;
* message - message will be shown to user, use _() to translate&lt;br /&gt;
* choices - array of choices&lt;br /&gt;
* callback - non-optional handler to be called on choice made, the choice parameter is the INDEX of the choice from the array of choices&lt;br /&gt;
&lt;br /&gt;
NOTE: this is async function, it does not return anything and you should not do anything after, you must do everything in handlers&lt;br /&gt;
NOTE: there is no cancel handler, so make sure you gave user a choice to get out of it&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    const keys = [&amp;quot;0&amp;quot;, &amp;quot;1&amp;quot;, &amp;quot;5&amp;quot;, &amp;quot;10&amp;quot;];&lt;br /&gt;
    this.multipleChoiceDialog(_(&amp;quot;How many bugs to fix?&amp;quot;), keys, (choice) =&amp;gt; {&lt;br /&gt;
      if (choice==0) return; // cancel operation, do not call server action&lt;br /&gt;
      var bugchoice = keys[choice]; // choice will be 0,1,2,3 here&lt;br /&gt;
      this.bgaPerformAction(&amp;quot;fixBugs&amp;quot;, { number: bugchoice });&lt;br /&gt;
    });&lt;br /&gt;
    return; // must return here&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Generic Dialogs ===&lt;br /&gt;
&lt;br /&gt;
As a general rule, you shouldn&#039;t use dialogs windows.&lt;br /&gt;
&lt;br /&gt;
BGA guidelines specify that all game elements should be displayed on the main screen. Players can eventually scroll down to see game elements they don&#039;t need to see anytime, and you may eventually create anchors to move between game area section. Of course dialogs windows are very practical, but the thing is: all players know how to scroll down, and not all players know how to show up your dialog window. In addition, when the dialog shows up, players can&#039;t access the other game components.&lt;br /&gt;
&lt;br /&gt;
Sometimes although, you need to display a dialog window. Here is how you do this:&lt;br /&gt;
&lt;br /&gt;
  // Create the new dialog over the play zone. You should store the handler in a member variable to access it later&lt;br /&gt;
  this.myDlg = new ebg.popindialog();&lt;br /&gt;
  this.myDlg.create( &#039;myDialogUniqueId&#039; );&lt;br /&gt;
  this.myDlg.setTitle( _(&amp;quot;my dialog title to translate&amp;quot;) );&lt;br /&gt;
  this.myDlg.setMaxWidth( 500 ); // Optional&lt;br /&gt;
  &lt;br /&gt;
  // Create the HTML of my dialog. &lt;br /&gt;
  // The best practice here is to use [[Game_layout:_view_and_template:_yourgamename.view.php_and_yourgamename_yourgamename.tpl#Javascript_templates|Javascript templates]]&lt;br /&gt;
  var html = this.format_block( &#039;jstpl_myDialogTemplate&#039;, { &lt;br /&gt;
                arg1: myArg1,&lt;br /&gt;
                arg2: myArg2,&lt;br /&gt;
                ...&lt;br /&gt;
            } );  &lt;br /&gt;
  &lt;br /&gt;
  // Show the dialog&lt;br /&gt;
  this.myDlg.setContent( html ); // Must be set before calling show() so that the size of the content is defined before positioning the dialog&lt;br /&gt;
  this.myDlg.show();&lt;br /&gt;
  &lt;br /&gt;
  // Now that the dialog has been displayed, you can connect your method to some dialog elements&lt;br /&gt;
  // Example, if you have an &amp;quot;OK&amp;quot; button in the HTML of your dialog:&lt;br /&gt;
  dojo.connect($(&#039;my_ok_button&#039;), &#039;onclick&#039;, this, (event) =&amp;gt; {&lt;br /&gt;
                event.preventDefault();&lt;br /&gt;
                this.myDlg.destroy();&lt;br /&gt;
            });&lt;br /&gt;
&lt;br /&gt;
If necessary, you can remove the default top right corner &#039;close&#039; icon, or replace the function called when it is clicked:&lt;br /&gt;
  // Removes the default close icon&lt;br /&gt;
  this.myDlg.hideCloseIcon();&lt;br /&gt;
&lt;br /&gt;
  // Replace the function call when it&#039;s clicked&lt;br /&gt;
  this.myDlg.replaceCloseCallback((event) =&amp;gt; { ... });&lt;br /&gt;
&lt;br /&gt;
=== Scoring dialogs ===&lt;br /&gt;
&lt;br /&gt;
Sometimes at the end of a round you want to display a big table that details the points wins in each section of the game.&lt;br /&gt;
&lt;br /&gt;
Example: in Hearts game, we display at the end of each round the number of &amp;quot;heart&amp;quot; cards collected by each player, the player who collected the Queen of Spades, and the total number of points loose by each player.&lt;br /&gt;
&lt;br /&gt;
Scoring dialogs are managed entirely on &#039;&#039;&#039;PHP side&#039;&#039;&#039;, but they are described here as their effects are visible only on client side.&lt;br /&gt;
&lt;br /&gt;
Displaying a scoring dialog is quite simple and is using a special notification type: &amp;quot;tableWindow&amp;quot;:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  // on PHP side:&lt;br /&gt;
  $this-&amp;gt;notifyAllPlayers( &amp;quot;tableWindow&amp;quot;, &#039;&#039;, array(&lt;br /&gt;
            &amp;quot;id&amp;quot; =&amp;gt; &#039;finalScoring&#039;,&lt;br /&gt;
            &amp;quot;title&amp;quot; =&amp;gt; clienttranslate(&amp;quot;Title of the scoring dialog&amp;quot;),&lt;br /&gt;
            &amp;quot;table&amp;quot; =&amp;gt; $table&lt;br /&gt;
        )); &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The &amp;quot;table&amp;quot; argument is a 2 dimensional PHP array that describes the table you want to display, line by line and column by column.&lt;br /&gt;
&lt;br /&gt;
Example: display an 3x3 array of strings&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
   $table = [&lt;br /&gt;
      [ &amp;quot;one&amp;quot;, &amp;quot;two&amp;quot;, &amp;quot;three&amp;quot; ],    // This is my first line&lt;br /&gt;
      [ &amp;quot;four&amp;quot;, &amp;quot;five&amp;quot;, &amp;quot;six&amp;quot; ],    // This is my second line&lt;br /&gt;
      [ &amp;quot;seven&amp;quot;, &amp;quot;height&amp;quot;, &amp;quot;nine&amp;quot; ]    // This is my third line&lt;br /&gt;
   ];&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
As you can see above, in each &amp;quot;cell&amp;quot; of your array you can display a simple string value. But you can also display a complex value with a template and associated arguments like this:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
   $table = [&lt;br /&gt;
      [ &amp;quot;one&amp;quot;, &amp;quot;two&amp;quot;, [ &amp;quot;str&amp;quot; =&amp;gt; clienttranslate(&amp;quot;a string with an ${argument}&amp;quot;), &amp;quot;args&amp;quot; =&amp;gt; [ &#039;argument&#039; =&amp;gt; &#039;argument_value&#039; ] ] ],&lt;br /&gt;
      [ &amp;quot;four&amp;quot;, &amp;quot;five&amp;quot;, &amp;quot;six&amp;quot; ], &lt;br /&gt;
      [ &amp;quot;seven&amp;quot;, &amp;quot;height&amp;quot;, &amp;quot;nine&amp;quot; ]&lt;br /&gt;
   ];&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This is especially useful when you want to display player names with colors. Example from &amp;quot;Hearts&amp;quot;:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        $firstRow = [ &#039;&#039; ];&lt;br /&gt;
        foreach( $players as $player_id =&amp;gt; $player )    {&lt;br /&gt;
            $cell = [ &#039;str&#039; =&amp;gt; &#039;${player_name}&#039;,&lt;br /&gt;
                      &#039;args&#039; =&amp;gt; [ &#039;player_name&#039; =&amp;gt; $player[&#039;player_name&#039;] ],&lt;br /&gt;
                      &#039;type&#039; =&amp;gt; &#039;header&#039;&lt;br /&gt;
                    ];&lt;br /&gt;
            $firstRow[] = $cell;&lt;br /&gt;
        }&lt;br /&gt;
        $table[] = $firstRow;&lt;br /&gt;
        ...&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You can also use three extra attributes in the parameter array for the notification:&lt;br /&gt;
* &#039;&#039;&#039;header&#039;&#039;&#039;: the content for this parameter displays before the table (also, the html will be parsed and player names will be colored according to the current game colors). &lt;br /&gt;
* &#039;&#039;&#039;footer&#039;&#039;&#039;: the content for this parameter displays after the table (no parsing for coloring the player names)&lt;br /&gt;
* &#039;&#039;&#039;closing&#039;&#039;&#039;: if this parameter is used, a button will be displayed with this label at the bottom of the popup and will allow players to close it (more easily than by clicking the top right &#039;cross&#039; icon).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
   $this-&amp;gt;notifyAllPlayers( &amp;quot;tableWindow&amp;quot;, &#039;&#039;, [&lt;br /&gt;
            &amp;quot;id&amp;quot; =&amp;gt; &#039;finalScoring&#039;,&lt;br /&gt;
            &amp;quot;title&amp;quot; =&amp;gt; clienttranslate(&amp;quot;Title of the scoring dialog&amp;quot;),&lt;br /&gt;
            &amp;quot;table&amp;quot; =&amp;gt; $table,&lt;br /&gt;
            &amp;quot;header&amp;quot; =&amp;gt; [&#039;str&#039; =&amp;gt; clienttranslate(&#039;Table header with parameter ${number}&#039;),&lt;br /&gt;
                                 &#039;args&#039; =&amp;gt; [ &#039;number&#039; =&amp;gt; 3 ],&lt;br /&gt;
                               ],&lt;br /&gt;
            &amp;quot;footer&amp;quot; =&amp;gt; &#039;&amp;lt;div class=&amp;quot;myfoot&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&#039;,&lt;br /&gt;
            &amp;quot;closing&amp;quot; =&amp;gt; clienttranslate( &amp;quot;Closing button label&amp;quot; )&lt;br /&gt;
        ] ); &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note: currently id is not used - so you cannot access resulting div by id on js side&lt;br /&gt;
Note: any traslatable stirng have to be wrapped by clienttranslate() on top level OR it has to be recursive template. &lt;br /&gt;
&lt;br /&gt;
DO NOT DO THIS: &lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
   &amp;quot;footer&amp;quot; =&amp;gt; &#039;&amp;lt;div&amp;gt;&#039;.clienttranslate( &amp;quot;The end&amp;quot; ).&#039;&amp;lt;/div&amp;gt;&#039;, // this will not work for translations!!!&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Scoring animated display ===&lt;br /&gt;
&lt;br /&gt;
Sometimes, you may want to display a score value over an element to make the scoring easier to follow for the players (Terra Mystica final scoring for example).&lt;br /&gt;
You can do it with:&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.displayScoring(anchor_id: string, color: string, score: number | string, duration?: number, offset_x?: number, offset_y?: number): void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;anchor_id&#039;&#039;&#039;: ID of the html element to place the animated score onto (without the &#039;#&#039;) &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;color&#039;&#039;&#039;: hexadecimal RGB representation of the color (should be the color of the scoring player), but without a leading &#039;#&#039;.  For instance, &#039;ff0000&#039; for red.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;score&#039;&#039;&#039;: numeric score to display, prefixed by a &#039;+&#039; or &#039;-&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;duration&#039;&#039;&#039;: animation duration in milliseconds (optional, default is 1000)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;offset_x&#039;&#039;&#039; and &#039;&#039;&#039;offset_y&#039;&#039;&#039;: if both offset_x and offset_y are defined and not null, apply the following offset (in pixels) to the scoring animation. &lt;br /&gt;
Note that the score is centered in the anchor, so the offsets might have to be negative if you calculate the position.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Note: if you want to display successively each score, you can use &#039;&#039;this.notifqueue.setSynchronous()&#039;&#039; function.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    setupNotifications: function()   {&lt;br /&gt;
           dojo.subscribe( &#039;displayScoring&#039;, this, &amp;quot;notif_displayScoring&amp;quot; );&lt;br /&gt;
           ...&lt;br /&gt;
    }&lt;br /&gt;
...&lt;br /&gt;
&lt;br /&gt;
    notif_displayScoring: function(notif) {&lt;br /&gt;
            const duration = notif.args.duration?notif.args.duration:1000;&lt;br /&gt;
            this.notifqueue.setSynchronous(&#039;displayScoring&#039;, duration );&lt;br /&gt;
	    this.displayScoring( notif.args.target, notif.args.color, notif.args.score, duration);&lt;br /&gt;
    },&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Speech bubble ===&lt;br /&gt;
&lt;br /&gt;
For better interactivity in some games (Love Letter for example), you may use comic book style speech bubbles to express the players voices.&lt;br /&gt;
This is done with showBubble:&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.showBubble(anchor_id: string, text: string, delay?: number, duration?: number, custom_class?: string): void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
* anchor_id - where to attach the bubble&lt;br /&gt;
* text - what to put in bubble, can be html&lt;br /&gt;
* delay - delay in milliseconds (optional, default 0)&lt;br /&gt;
* duration -  duration of animation in milliseconds (optional, default 3000)&lt;br /&gt;
* custom_class - extra class to add to bubble (optional), if you need to override the default bubble style&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
   this.showBubble(&#039;meeple_2&#039;, _(&#039;Hello&#039;), 0, 1000, &#039;pink_bubble&#039;);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  notif_speechBubble(notif) {&lt;br /&gt;
    var html = this.format_string_recursive(notif.args.text, notif.args.args);&lt;br /&gt;
    this.showBubble(notif.args.target, html, notif.args.delay ?? 0, notif.args.duration ?? 1000);&lt;br /&gt;
  },&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Warning&#039;&#039;&#039;: if your bubble could overlap other active elements of the interface (buttons in particular), as it stays in place even after disappearing, you should use a custom class to give it the style &amp;quot;pointer-events: none;&amp;quot; in order to intercept click events.&lt;br /&gt;
&lt;br /&gt;
Note: If you want this visually, but want to take complete control over this bubble and its animation (for example to make it permanent) you can just use div with &#039;discussion_bubble&#039; class on it, and content of div is what will be shown.&lt;br /&gt;
&lt;br /&gt;
== Translations ==&lt;br /&gt;
&lt;br /&gt;
See [[Translations]]&lt;br /&gt;
&lt;br /&gt;
== Players panels ==&lt;br /&gt;
&lt;br /&gt;
=== Update players score ===&lt;br /&gt;
&lt;br /&gt;
The column player_score from the player table is automatically loaded into this.scoreCtrl and therefore into the stars location on the player board. This occurs sometime after the game setup() function. However this score must be updated as the game progresses using notifications.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Note: this.scoreCtrl[player_id] is object of class [[Counter]], you can use other counter API.&lt;br /&gt;
&lt;br /&gt;
Increase a player score (with a positive or negative number):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  this.scoreCtrl[ player_id ].incValue( score_delta );&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Set a player score to a specific value:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  this.scoreCtrl[ player_id ].setValue( new_score );&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Set a player score to a specific value with animation:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  this.scoreCtrl[ player_id ].toValue( new_score );&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Typical usage would be (that will process &#039;score&#039; notification):&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        setupNotifications : function() {&lt;br /&gt;
              ...&lt;br /&gt;
             dojo.subscribe(&#039;score&#039;, this, &amp;quot;notif_score&amp;quot;);&lt;br /&gt;
        },&lt;br /&gt;
        notif_score: function(notif) {&lt;br /&gt;
            this.scoreCtrl[notif.args.player_id].setValue(notif.args.player_score);&lt;br /&gt;
        },&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Adding stuff to player&#039;s panel ===&lt;br /&gt;
&lt;br /&gt;
At first, create a new &amp;quot;JS template&amp;quot; string in your template (tpl) file:&lt;br /&gt;
&lt;br /&gt;
(from Gomoku example)&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
var jstpl_player_board = &#039;\&amp;lt;div class=&amp;quot;cp_board&amp;quot;&amp;gt;\&lt;br /&gt;
    &amp;lt;div id=&amp;quot;stoneicon_p${id}&amp;quot; class=&amp;quot;gmk_stoneicon gmk_stoneicon_${color}&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&amp;lt;span id=&amp;quot;stonecount_p${id}&amp;quot;&amp;gt;0&amp;lt;/span&amp;gt;\&lt;br /&gt;
&amp;lt;/div&amp;gt;&#039;;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Then, you add this piece of code in your JS file to add this template to each player panel:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
            // Setting up player boards&lt;br /&gt;
            for( var player_id in gamedatas.players )&lt;br /&gt;
            {&lt;br /&gt;
                var player = gamedatas.players[player_id];&lt;br /&gt;
                         &lt;br /&gt;
                // Setting up players boards if needed&lt;br /&gt;
                var player_board_div = $(&#039;player_board_&#039;+player_id);&lt;br /&gt;
                dojo.place( this.format_block(&#039;jstpl_player_board&#039;, player ), player_board_div );&lt;br /&gt;
            }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
(Note: the code above is of course from your &amp;quot;setup&amp;quot; function in your Javascript).&lt;br /&gt;
&lt;br /&gt;
Very often, you have to distinguish current player and others players. In this case, you just have to create another JS template (ex: jstpl_otherplayer_board) and use it when &amp;quot;player_id&amp;quot; is different than &amp;quot;this.player_id&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Fixing Player Panel heights ===&lt;br /&gt;
&lt;br /&gt;
You may find that the player panels don&#039;t automatically resize when adding something to (or removing something from) a player panel while the display is in portrait mode (i.e. the player summary panels are at the top of the screen rather than down the right side).&lt;br /&gt;
&lt;br /&gt;
When this happens, call &amp;lt;pre&amp;gt;this.adaptPlayersPanels();&amp;lt;/pre&amp;gt; This recalculates the layout and also adjusts the position of the actionbar for you.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Player&#039;s panel disabling/enabling ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.disablePlayerPanel(player_id: number): void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Disable given player panel (the panel background become gray).&lt;br /&gt;
&lt;br /&gt;
Usually, this is used to signal that this played passes, or will be inactive during a while.&lt;br /&gt;
&lt;br /&gt;
Note that the only effect of this is visual. There are no consequences on the behaviour of the panel itself.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.enablePlayerPanel(player_id:number): void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Enable a player panel that has been disabled before.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.enableAllPlayerPanels(): void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Enable all player panels that has been disabled before.&lt;br /&gt;
&lt;br /&gt;
=== Player order ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.updatePlayerOrdering(): void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
This function makes sure that player order in player&#039;s panel matches this.gamedatas.playerorder and its normally called by framework.&lt;br /&gt;
You can call it yoursel if you change this.gamedatas.playerorder from notification.&lt;br /&gt;
Also you can override this function to change defaults  OR insert a non-player panel [[BGA_Studio_Cookbook#Inserting_non-player_panel]].&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Counters ===&lt;br /&gt;
Note: there is bga component called  &amp;quot;ebg/counter&amp;quot; this API is not using it, these methods&lt;br /&gt;
below declared right in core game. If you need animation for counters use ebg/counter&lt;br /&gt;
&lt;br /&gt;
To use this API just create a counter dom element like this (class does not really matter)&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 &amp;lt;div class=&amp;quot;counter&amp;quot; id=&amp;quot;bread&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
 &amp;lt;div class=&amp;quot;counter&amp;quot; id=&amp;quot;coin&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
The &amp;quot;bread&amp;quot; will the counter name.&lt;br /&gt;
&lt;br /&gt;
The php code should send all &amp;quot;counters&amp;quot; data from getAllDatas() method like this&lt;br /&gt;
&lt;br /&gt;
game.php&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  protected function getAllDatas() {&lt;br /&gt;
    // (the key must match counter_name)&lt;br /&gt;
    $result[&#039;counters&#039;]=[&lt;br /&gt;
        &#039;bread&#039; =&amp;gt; [ &lt;br /&gt;
         &#039;counter_name&#039; =&amp;gt; &#039;bread&#039;, &lt;br /&gt;
         &#039;counter_value&#039; =&amp;gt; 3&lt;br /&gt;
         ], &lt;br /&gt;
        &#039;coin&#039; =&amp;gt; [&lt;br /&gt;
          &#039;counter_name&#039; =&amp;gt; &#039;coin&#039;, &lt;br /&gt;
          &#039;counter_value&#039; =&amp;gt; 5&lt;br /&gt;
        ]&lt;br /&gt;
   ];&lt;br /&gt;
   return $result;&lt;br /&gt;
  }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;setCounter(counter_name: stirng, new_value: string | number): void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
updates the global this.gamedatas.counters and value of node $(counter_name)&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  notif_counter: function(notif) { &lt;br /&gt;
    this.setCounter(notif.args.counter_name, notif.args.counter_value);&lt;br /&gt;
  },&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;incCounter(counter_name: string, delta: number): void&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  notif_counter : function(notif) {&lt;br /&gt;
    this.incCounter(notif.args.counter_name, notif.args.inc);&lt;br /&gt;
  },&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;updateCounters(counters: object): void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Useful for updating game counters in the player panel (such as resources). &lt;br /&gt;
&#039;counters&#039; arg is map of counters (the key must match counter_name)&lt;br /&gt;
  {&lt;br /&gt;
    &#039;bread&#039;: { &lt;br /&gt;
         &#039;counter_name&#039; : &#039;bread&#039;, &lt;br /&gt;
         &#039;counter_value&#039; =&amp;gt; 3&lt;br /&gt;
    }, &lt;br /&gt;
    &#039;coin&#039;: { &lt;br /&gt;
         &#039;counter_name&#039; : &#039;coin&#039;, &lt;br /&gt;
         &#039;counter_value&#039; =&amp;gt; 5&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
All counters MUST be referenced in this.gamedatas.counters (means they should be send from php) and will be updated.&lt;br /&gt;
DOM objects referenced by &#039;counter_name&#039; will have their innerHTML updated with &#039;counter_value&#039;.&lt;br /&gt;
&lt;br /&gt;
Usually you call this from notification&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
                        notif_counter : function(notif) {&lt;br /&gt;
                            this.updateCounters(notif.args.counters);&lt;br /&gt;
                        },&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== BGA GUI components ==&lt;br /&gt;
&lt;br /&gt;
BGA framework provides some useful ready-to-use components for the game interface:&lt;br /&gt;
&lt;br /&gt;
[[Studio#BGA_Studio_game_components_reference]]&lt;br /&gt;
&lt;br /&gt;
Note that each time you are using an additional component, you must declare it at the top of your Javascript file in the list of modules used.&lt;br /&gt;
&lt;br /&gt;
Example if you are using &amp;quot;ebg.stock&amp;quot;:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
define([&lt;br /&gt;
    &amp;quot;dojo&amp;quot;,&amp;quot;dojo/_base/declare&amp;quot;,&lt;br /&gt;
    &amp;quot;ebg/core/gamegui&amp;quot;,&lt;br /&gt;
    &amp;quot;ebg/counter&amp;quot;,&lt;br /&gt;
    &amp;quot;ebg/stock&amp;quot;  /// &amp;lt;=== we are using ebg.stock module&lt;br /&gt;
],&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== BGA Buttons ==&lt;br /&gt;
&lt;br /&gt;
=== Basic Button ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.addActionButton(id: string, label: string, method: string | eventhandler, destination?: string, blinking?: boolean, color?: string): void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
You can use this method to add an action button in the main action status bar (or other places).&lt;br /&gt;
&lt;br /&gt;
Arguments:&lt;br /&gt;
* id: an element ID that should be unique in your HTML DOM document.&lt;br /&gt;
* label: the text of the button. Should be translatable (use _() function). Note: this can also be any html, such as &amp;quot;&amp;lt;div class=&#039;brick&#039;&amp;gt;&amp;lt;/div&amp;gt;&amp;quot;, see example below on how to make image action buttons.&lt;br /&gt;
* method: the name of your method that must be triggered when the player clicks on this button (can be name of the method on game class or handler).&lt;br /&gt;
* destination (optional): id of parent on where to add button, ONLY use in rare cases if location is not action bar. Use &#039;&#039;&#039;null&#039;&#039;&#039; as value if you need to specify other arguments.&lt;br /&gt;
* blinking (optional): if set to &#039;&#039;&#039;true&#039;&#039;&#039;, the button is going blink to catch player&#039;s attention. Please DO NOT abuse blinking button. If you need button to blink after some time passed add class &#039;blinking&#039; to the button later.&lt;br /&gt;
* color: could be &#039;&#039;&#039;blue&#039;&#039;&#039; (default), &#039;&#039;&#039;red&#039;&#039;&#039;,&#039;&#039;&#039;gray&#039;&#039;&#039; or &#039;&#039;&#039;none&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
You should only use this method in your &amp;quot;onUpdateActionButtons&amp;quot; method. Usually, you use it like this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        onUpdateActionButtons: function( stateName, args ) {                      &lt;br /&gt;
            if (this.isCurrentPlayerActive()) {            &lt;br /&gt;
                switch( stateName ) {&lt;br /&gt;
                case &#039;giveCards&#039;:&lt;br /&gt;
                    this.addActionButton( &#039;giveCards_button&#039;, _(&#039;Give selected cards&#039;), &#039;onGiveCards&#039; ); &lt;br /&gt;
                    this.addActionButton( &#039;pass_button&#039;, _(&#039;Pass&#039;), () =&amp;gt; this.bgaPerformAction(&#039;actPass&#039;) ); &lt;br /&gt;
                    break;&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        },   &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In the example above, we are adding a &amp;quot;Give selected cards&amp;quot; button in the case we are on game state &amp;quot;giveCards&amp;quot;. When player clicks on this button, it triggers our &amp;quot;onGiveCards&amp;quot; method.&lt;br /&gt;
&lt;br /&gt;
Example using blinking red button:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    this.addActionButton( &#039;button_confirm&#039;, _(&#039;Confirm?&#039;), &#039;onConfirm&#039;, null, true, &#039;red&#039;); &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If you want to call the handler with arguments, you can use arrow functions, like this:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
     this.addActionButton( &#039;commit_button&#039;, _(&#039;Confirm&#039;), () =&amp;gt; this.onConfirm(this.selectedCardId), null, false, &#039;red&#039;); &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Image Button ===&lt;br /&gt;
&lt;br /&gt;
You can use the same method, but add extra class to a button to disable the padding and style it, i.e.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
this.addActionButton( &#039;button_brick&#039;, &#039;&amp;lt;div class=&amp;quot;brick&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&#039;, ()=&amp;gt;{... on brick ...}, null, null, &#039;gray&#039;); &lt;br /&gt;
dojo.addClass(&#039;button_brick&#039;,&#039;bgaimagebutton&#039;);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
where&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
.bgaimagebutton {&lt;br /&gt;
  padding: 0px 12px;&lt;br /&gt;
  min-height: 28px;&lt;br /&gt;
  border: none;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If you use this a lot, you can define a helper function, i.e.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
 * This method can be used instead of addActionButton, to add a button which is an image (i.e. resource). Can be useful when player&lt;br /&gt;
 * need to make a choice of resources or tokens.&lt;br /&gt;
 */&lt;br /&gt;
addImageActionButton: function(id, div, handler, bcolor, tooltip) {&lt;br /&gt;
	if (typeof bcolor == &amp;quot;undefined&amp;quot;) {&lt;br /&gt;
		bcolor = &amp;quot;gray&amp;quot;;&lt;br /&gt;
	}&lt;br /&gt;
	// this will actually make a transparent button id color = gray&lt;br /&gt;
	this.addActionButton(id, div, handler, null, false, bcolor);&lt;br /&gt;
	// remove border, for images it better without&lt;br /&gt;
	dojo.style(id, &amp;quot;border&amp;quot;, &amp;quot;none&amp;quot;);&lt;br /&gt;
	// but add shadow style (box-shadow, see css)&lt;br /&gt;
	dojo.addClass(id, &amp;quot;shadow bgaimagebutton&amp;quot;);&lt;br /&gt;
	// you can also add additional styles, such as background&lt;br /&gt;
	if (tooltip) {&lt;br /&gt;
		dojo.attr(id, &amp;quot;title&amp;quot;, tooltip);&lt;br /&gt;
	}&lt;br /&gt;
	return $(id);&lt;br /&gt;
},&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Disabling Button ===&lt;br /&gt;
&lt;br /&gt;
You can disable the &#039;&#039;&#039;bgabutton&#039;&#039;&#039; by adding the css class &#039;&#039;&#039;disabled&#039;&#039;&#039; in you js. The disabled button is still visible but is grey and not clickable.&lt;br /&gt;
For example in the &#039;&#039;&#039;onUpdateActionButtons&#039;&#039;&#039; : &lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
this.addActionButton(&#039;play_button_id&#039;, _(&#039;Play 1 to 3 cards&#039;), &#039;playFunctionButton&#039;); &lt;br /&gt;
if (condition) {&lt;br /&gt;
  dojo.addClass(&#039;play_button_id&#039;, &#039;disabled&#039;);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Custom Buttons ===&lt;br /&gt;
&lt;br /&gt;
You can create a custom button, but the BGA framework provides a standard button that requires only .css classes: &#039;&#039;&#039;bgabutton&#039;&#039;&#039; and &#039;&#039;&#039;bgabutton_${color}&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Examples:&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;a href=&amp;quot;#&amp;quot; id=&amp;quot;my_button_id&amp;quot; class=&amp;quot;bgabutton bgabutton_blue&amp;quot;&amp;gt;&amp;lt;span&amp;gt;My blue button&amp;lt;/span&amp;gt;&amp;lt;/a&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;a href=&amp;quot;#&amp;quot; id=&amp;quot;my_button_id&amp;quot; class=&amp;quot;bgabutton bgabutton_red bgabutton_big&amp;quot;&amp;gt;&amp;lt;span&amp;gt;My big red button&amp;lt;/span&amp;gt;&amp;lt;/a&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note&#039;&#039;&#039;: To see it in action, check out &#039;&#039;Coloretto&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
=== Button outside of action bar ===&lt;br /&gt;
&lt;br /&gt;
Use addActionButton() method with destination argument set&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
this.addActionButton( &#039;commit_button&#039;, _(&#039;Confirm&#039;), &#039;onConfirm&#039;, &#039;player_board&#039;, true, &#039;red&#039;); &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
in example above the button will be place on object with id &#039;player_board&#039;&lt;br /&gt;
&lt;br /&gt;
== Image loading ==&lt;br /&gt;
&lt;br /&gt;
See also [[Game_art:_img_directory]].&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Be careful&#039;&#039;&#039;: by default, ALL images of your img directory are loaded on a player&#039;s browser when he loads the game. For this reason, don&#039;t let in your img directory images that are not useful, otherwise it&#039;s going to slowdown the game load.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.dontPreloadImage(image_file_name: string)&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Using dontPreloadImage, you tell the interface to not preload a specific image in your img directory.&lt;br /&gt;
&lt;br /&gt;
Example of use:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
this.dontPreloadImage( &#039;cards.png&#039; );&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This is particularly useful if for example you have 2 different themes for a game. To accelerate the loading of the game, you can specify to not preload images corresponding to the other theme.&lt;br /&gt;
&lt;br /&gt;
Another example of use: in &amp;quot;Gosu&amp;quot; game with Kamakor extension, you play with 5 sets of cards among 10 available. Cards images are organized by sets, and we only preload the images corresponding to the 5 current sets with &#039;&#039;&#039;ensureSpecificGameImageLoading( image_file_names_array )&#039;&#039;&#039;.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
// By default, do not preload anything&lt;br /&gt;
this.dontPreloadImage( &#039;cards.png&#039; );&lt;br /&gt;
this.dontPreloadImage( &#039;clan1.png&#039; );&lt;br /&gt;
this.dontPreloadImage( &#039;clan2.png&#039; );&lt;br /&gt;
this.dontPreloadImage( &#039;clan3.png&#039; );&lt;br /&gt;
this.dontPreloadImage( &#039;clan4.png&#039; );&lt;br /&gt;
this.dontPreloadImage( &#039;clan5.png&#039; );&lt;br /&gt;
this.dontPreloadImage( &#039;clan6.png&#039; );&lt;br /&gt;
this.dontPreloadImage( &#039;clan7.png&#039; );&lt;br /&gt;
this.dontPreloadImage( &#039;clan8.png&#039; );&lt;br /&gt;
this.dontPreloadImage( &#039;clan9.png&#039; );&lt;br /&gt;
this.dontPreloadImage( &#039;clan10.png&#039; );&lt;br /&gt;
var to_preload = [];&lt;br /&gt;
for( i in this.gamedatas.clans )&lt;br /&gt;
{&lt;br /&gt;
	var clan_id = this.gamedatas.clans[i];&lt;br /&gt;
	to_preload.push( &#039;clan&#039;+clan_id+&#039;.png&#039; );&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
this.ensureSpecificGameImageLoading( to_preload );&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note:&#039;&#039;&#039; You don&#039;t need to specify to not preload game box images (game_box.png, game_box75.png...) since they are not preloaded by default.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.ensureSpecificGameImageLoading(list: string[])&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
This is oppostive of dontPreloadImage - its ensure specific images is loaded. Note: only makes sense if preload list is empty, otherwise everything is loaded anyway&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;load specific images&#039;&#039;&#039;&lt;br /&gt;
All images that will be preloaded stored in g_img_preload. If you want to override it directly - there is no API, but you can do this in GAME constructor&lt;br /&gt;
&lt;br /&gt;
          g_img_preload = [&#039;tokens.png&#039;, &#039;trains.png&#039;, &#039;loc_plan.png&#039;, &#039;eng.png&#039;, &#039;eng-back.png&#039;];&lt;br /&gt;
&lt;br /&gt;
You can also set it to empty array and call ensureSpecificGameImageLoading() on specific images&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Sounds ==&lt;br /&gt;
&lt;br /&gt;
Add a custom sound and make it load with your interface:&lt;br /&gt;
&lt;br /&gt;
Add this in your template (.tpl) file:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;audio id=&amp;quot;audiosrc_&amp;lt;gamename&amp;gt;_&amp;lt;yoursoundname&amp;gt;&amp;quot; src=&amp;quot;{GAMETHEMEURL}img/&amp;lt;gamename&amp;gt;_&amp;lt;yoursoundname&amp;gt;.mp3&amp;quot; preload=&amp;quot;none&amp;quot; autobuffer&amp;gt;&amp;lt;/audio&amp;gt;&lt;br /&gt;
&amp;lt;audio id=&amp;quot;audiosrc_o_&amp;lt;gamename&amp;gt;_&amp;lt;yoursoundname&amp;gt;&amp;quot; src=&amp;quot;{GAMETHEMEURL}img/&amp;lt;gamename&amp;gt;_&amp;lt;yoursoundname&amp;gt;.ogg&amp;quot; preload=&amp;quot;none&amp;quot; autobuffer&amp;gt;&amp;lt;/audio&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note: this is a requirement to provide both a mp3 and a ogg file with the names &amp;lt;code&amp;gt;&amp;lt;gamename&amp;gt;_&amp;lt;yoursoundname&amp;gt;[.ogg][.mp3]&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Play the sound (from your .js file):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
playSound(&#039;&amp;lt;gamename&amp;gt;_&amp;lt;yoursoundname&amp;gt;&#039;);   // do not add &#039;this.&#039; - its a global function&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Disable the standard &amp;quot;move&amp;quot; sound for this move (to replace it with your custom sound):&lt;br /&gt;
&lt;br /&gt;
Add this to your notification handler:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
this.disableNextMoveSound();&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note: it only disable the sound for the next move.&lt;br /&gt;
&lt;br /&gt;
== Title bar and states ==&lt;br /&gt;
&lt;br /&gt;
=== Client states ===&lt;br /&gt;
&lt;br /&gt;
Client states is a way to simulate the state transition but without actually going&lt;br /&gt;
to server. It is usefull when you need to ask user multiple questions before you&lt;br /&gt;
send things to server&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.setClientState(newState: string, args: object)&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
     this.setClientState(&amp;quot;client_playerPicksLocation&amp;quot;, {&lt;br /&gt;
                               descriptionmyturn : _(&amp;quot;${you} must select location&amp;quot;),&lt;br /&gt;
                           });&lt;br /&gt;
&lt;br /&gt;
For more information see [[BGA_Studio_Cookbook#Multi_Step_Interactions:_Select_Worker.2FPlace_Worker_-_Using_Client_States]]&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.restoreServerGameState()&#039;&#039;&#039;&lt;br /&gt;
If you are in client state it will restore the current server state (cheap undo)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.on_client_state&#039;&#039;&#039;&lt;br /&gt;
Boolean indicating that we are in client state&lt;br /&gt;
&lt;br /&gt;
=== Title bar ===&lt;br /&gt;
If you simply want to show something in title bar you can do it directly &lt;br /&gt;
     $(&#039;pagemaintitletext&#039;).innerHTML = text;&lt;br /&gt;
&lt;br /&gt;
This however will not work with parameters and will not draw You in color,&lt;br /&gt;
if you want to do proper args rendering use method below&lt;br /&gt;
&lt;br /&gt;
;&#039;&#039;&#039;this.removeActionButtons()&#039;&#039;&#039;&lt;br /&gt;
Removes all buttons from title bar&lt;br /&gt;
&lt;br /&gt;
;&#039;&#039;&#039;this.updatePageTitle()&#039;&#039;&#039;&lt;br /&gt;
:This function allows to update the current page title and turn description according to the game state arguments. If the current game state description this.gamedatas.gamestate.descriptionmyturn is modified before calling this function it allows to update the turn description without changing state. This will handle arguments substitutions properly.&lt;br /&gt;
&lt;br /&gt;
Note: this functional also will calls this.onUpdateActionButtons, if you want different buttons then state defaults, use method in example to replace them, if it becomes too clumsy use client states (see above)&lt;br /&gt;
&lt;br /&gt;
Example from Terra Mystica:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
onClickFavorTile: function( evt ) {&lt;br /&gt;
    ...&lt;br /&gt;
    if ( ... ) {&lt;br /&gt;
        this.gamedatas.gamestate.descriptionmyturn = _(&#039;Special action: &#039;) + _(&#039;Advance 1 space	on a Cult track&#039;);&lt;br /&gt;
        this.updatePageTitle();&lt;br /&gt;
        this.removeActionButtons();&lt;br /&gt;
        this.addActionButton( ... );&lt;br /&gt;
         ...&lt;br /&gt;
        return;&lt;br /&gt;
    }&lt;br /&gt;
    ...&lt;br /&gt;
&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== User preferences ==&lt;br /&gt;
&#039;&#039;&#039;this.getGameUserPreference(pref_id)&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Return the value of a user preference. It will return the value currently selected in the select combo box, in the top-right menu.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.setGameUserPreference(pref_id, value)&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Programmatically change a user preference. It will have the same effect as if the player changed the value in the select combo box, in the top-right menu.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.onGameUserPreferenceChanged&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
A callback you can define if you want to be notified when a user changes a user preference.&lt;br /&gt;
&lt;br /&gt;
Example:&amp;lt;pre&amp;gt;&lt;br /&gt;
onGameUserPreferenceChanged: function(pref_id, pref_value) {&lt;br /&gt;
  switch (pref_id) {&lt;br /&gt;
    case 201: &lt;br /&gt;
      document.getElementsByTagName(&#039;html&#039;)[0].classList.toggle(&#039;dark-background&#039;, pref_value == 2);&lt;br /&gt;
      break;&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Other useful stuff ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;dojo.hitch&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
With dojo.hitch, you can create a callback function that will run with your game object context whatever happen.&lt;br /&gt;
&lt;br /&gt;
Typical example: display a BGA confirmation dialog with a callback function created with dojo.hitch:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        this.confirmationDialog( _(&#039;Are you sure you want to make this?&#039;), dojo.hitch( this, function() {&lt;br /&gt;
            this.bgaPerformAction(&#039;makeThis&#039;);&lt;br /&gt;
        } ) );   &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In the example above, using dojo.hitch, we ensure that the &amp;quot;this&amp;quot; object will be set when the callback is called.&lt;br /&gt;
&lt;br /&gt;
NOTE: In modern JS there are lambdas that eliminate need for that, the example above will look like this&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        this.confirmationDialog( _(&#039;Are you sure you want to make this?&#039;), () =&amp;gt; this.bgaPerformAction( &#039;makeThis&#039;) );   &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
;&#039;&#039;&#039;onScreenWidthChange()&#039;&#039;&#039;&lt;br /&gt;
:This function can be overridden in your game to manage some resizing on the client side when the browser window is resized. This function is also triggered at load time, so it can be used to adapt to the :viewport size at the start of the game too.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
; this.bRealtime&lt;br /&gt;
: Return true if the game is in realtime. Note that having a distinct behavior in realtime and turn-based should be exceptional.&lt;br /&gt;
&lt;br /&gt;
; g_replayFrom&lt;br /&gt;
: Global contains replay number in live game, it is set to undefined (i.e. not set) when it is not a replay mode, so consequentially the good check is &#039;&#039;&#039;typeof g_replayFrom != &#039;undefined&#039;&#039;&#039;&#039; which returns true if the game is in replay mode &amp;lt;i&amp;gt;during the game&amp;lt;/i&amp;gt; (the game is ongoing but the user clicked &amp;quot;replay from this move&amp;quot; in the log)&lt;br /&gt;
&lt;br /&gt;
; g_archive_mode&lt;br /&gt;
: Returns true if the game is in archive mode &amp;lt;i&amp;gt;after the game&amp;lt;/i&amp;gt; (the game has ended)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
; this.instantaneousMode&lt;br /&gt;
: Returns true during replay/archive mode if animations should be skipped. Only needed if you are doing custom animations. (The BGA-provided animation functions like &amp;lt;i&amp;gt;this.slideToObject()&amp;lt;/i&amp;gt; automatically handle instantaneous mode.)&lt;br /&gt;
: Technically, when you click &amp;quot;replay from move #20&amp;quot;, the system replays the game from the very beginning with moves 0 - 19 happening in instantaneous mode and moves 20+ happening in normal mode.&lt;br /&gt;
&lt;br /&gt;
; g_tutorialwritten&lt;br /&gt;
: Returns an object like the below if the game is in tutorial mode, or undefined otherwise. Tutorial mode is a special case of archive mode where comments have been added to a previous game to teach new players the rules.&lt;br /&gt;
    {&lt;br /&gt;
        author: &amp;quot;91577332&amp;quot;,&lt;br /&gt;
        id: &amp;quot;576&amp;quot;,&lt;br /&gt;
        mode: &amp;quot;view&amp;quot;&lt;br /&gt;
        status: &amp;quot;alpha&amp;quot;&lt;br /&gt;
        version_override: null&lt;br /&gt;
        viewer_id: &amp;quot;84554161&amp;quot;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;getBgaEnvironment(): string&#039;&#039;&#039;&lt;br /&gt;
: Returns &amp;quot;studio&amp;quot; for studio and &amp;quot;prod&amp;quot; for production environment (i.e. where games current runs). Only useful for debbugging hooks.&lt;br /&gt;
Note: alpha server is also &amp;quot;prod&amp;quot;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Category:Studio]]&lt;/div&gt;</summary>
		<author><name>Sguzzer Gunayer</name></author>
	</entry>
	<entry>
		<id>https://en.doc.boardgamearena.com/index.php?title=Game_interface_logic:_Game.js&amp;diff=22728</id>
		<title>Game interface logic: Game.js</title>
		<link rel="alternate" type="text/html" href="https://en.doc.boardgamearena.com/index.php?title=Game_interface_logic:_Game.js&amp;diff=22728"/>
		<updated>2024-09-25T16:34:36Z</updated>

		<summary type="html">&lt;p&gt;Sguzzer Gunayer: /* Accessing Players Information */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Studio_Framework_Navigation}}&lt;br /&gt;
&lt;br /&gt;
__TOC__&lt;br /&gt;
&lt;br /&gt;
This is the main file for your game interface. Here you will define:&lt;br /&gt;
&lt;br /&gt;
* Which actions on the page will generate calls to the server.&lt;br /&gt;
* What happens when you get a notification for a change from the server and how it will show in the browser. &lt;br /&gt;
* Setup user interface&lt;br /&gt;
&lt;br /&gt;
== File structure ==&lt;br /&gt;
&lt;br /&gt;
The details of how the file is structured are described below with comments in the code skeleton provided to you.&lt;br /&gt;
&lt;br /&gt;
Here is the basic structure:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;constructor&#039;&#039;&#039;: here you can define global variables for your whole interface.&lt;br /&gt;
* &#039;&#039;&#039;setup&#039;&#039;&#039;: this method is called when the page is refreshed, and sets up the game interface.&lt;br /&gt;
* &#039;&#039;&#039;onEnteringState&#039;&#039;&#039;: this method is called when entering a new game state. You can use it to customize the view for each game state.&lt;br /&gt;
* &#039;&#039;&#039;onLeavingState&#039;&#039;&#039;: this method is called when leaving a game state.&lt;br /&gt;
* &#039;&#039;&#039;onUpdateActionButtons&#039;&#039;&#039;: called on state changes, in order to add action buttons to the status bar. Note: in a multipleactiveplayer state, it will be called when another player has become inactive.&lt;br /&gt;
* &#039;&#039;(utility methods)&#039;&#039;: this is where you can define your utility methods.&lt;br /&gt;
* &#039;&#039;(player&#039;s actions)&#039;&#039;: this is where you can write your handlers for player actions on the interface (example: click on an item).&lt;br /&gt;
* &#039;&#039;&#039;setupNotifications&#039;&#039;&#039;: this method associates notifications with notification handlers. For each game notification, you can trigger a javascript method to handle it and update the game interface.&lt;br /&gt;
* &#039;&#039;(notification handlers)&#039;&#039;: this is where you define the notifications handlers associated with notifications in &#039;&#039;&#039;setupNotifications&#039;&#039;&#039;, above.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
More details:&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;setup(gamedatas: object)            &#039;&#039;&#039;&lt;br /&gt;
This method must set up the game user interface according to current game situation specified in parameters.&lt;br /&gt;
The method is called each time the game interface is displayed to a player, ie:&lt;br /&gt;
&lt;br /&gt;
* when the game starts&lt;br /&gt;
* when a player opens a game in the browser later &lt;br /&gt;
* when a player refreshes the game page (F5)&lt;br /&gt;
* when player does a server side Undo&lt;br /&gt;
&lt;br /&gt;
&amp;quot;gamedatas&amp;quot; argument contains all data retrieved by your &amp;quot;getAllDatas&amp;quot; PHP method and some more.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;onEnteringState(stateName: string, args: { args: any } | null): void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
This method is called each time we enter a new game state.&lt;br /&gt;
You can use this method to perform some user interface changes at this moment.&lt;br /&gt;
To access state arguments passed via calling php arg* method use args?.args.&lt;br /&gt;
Typically you would do something only for active player, using this.isCurrentPlayerActive() check.&lt;br /&gt;
It is also called (for the current game state only) when doing a browser refresh (after the setup method is called).&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Warning&#039;&#039;&#039;: for multipleactiveplayer states:&lt;br /&gt;
the active players are NOT active yet so you must use onUpdateActionButtons to perform the client side operation which depends on a player active/inactive status.&lt;br /&gt;
If you are doing initialization of some structures which do not depend on the active player, you can just replace (this.isCurrentPlayerActive()) with (!this.isSpectator) &lt;br /&gt;
for the main switch in that method.&lt;br /&gt;
&lt;br /&gt;
See more details in [[Your_game_state_machine:_states.inc.php#Difference_between_Single_active_and_Multi_active_states]]&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;onLeavingState(stateName: string): void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
This method is called each time we leave a game state.&lt;br /&gt;
You can use this method to perform some user interface changes at this point (i.e. cleanup).&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;onUpdateActionButtons(stateName: string, args: object | null): void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
In this method you can manage &amp;quot;action buttons&amp;quot; that are displayed in the action status bar and highlight active UI elements.&lt;br /&gt;
To access state arguments passed via calling php arg* method use &#039;&#039;&#039;args&#039;&#039;&#039; parameter. Note: args can be null! For &#039;&#039;&#039;game&#039;&#039;&#039; states and when you don&#039;t supply state args function - it is null.&lt;br /&gt;
This method is called when the active or multiactive player changes. In a classic &amp;quot;activePlayer&amp;quot; state this method is called before the onEnteringState state.&lt;br /&gt;
In multipleactiveplayer state it is a mess. The sequencing of calls depends on whether you get into that state from transitions OR from reloading the whole game (i.e. F5).&lt;br /&gt;
&lt;br /&gt;
See more details in [[Your_game_state_machine:_states.inc.php#Difference_between_Single_active_and_Multi_active_states]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Dojo framework ==&lt;br /&gt;
&lt;br /&gt;
BGA uses the [http://dojotoolkit.org/ Dojo Javascript framework].&lt;br /&gt;
&lt;br /&gt;
The Dojo framework allows us to do complex things more easily. The BGA framework uses Dojo extensively.&lt;br /&gt;
&lt;br /&gt;
To implement a game, you only need to use a few parts of the Dojo framework. All the Dojo methods you need are described on this page.&lt;br /&gt;
&lt;br /&gt;
== Javascript minimization (after July 2020) ==&lt;br /&gt;
&lt;br /&gt;
For performance reasons, when deploying a game the javascript code is minimized using &#039;&#039;&#039;terser&#039;&#039;&#039; (https://github.com/terser/terser). This minifier works with modern javascript syntax. From your project &amp;quot;Manage game&amp;quot; page, you can now test a minified version of your javascript on the studio (and revert to the original).&lt;br /&gt;
&lt;br /&gt;
NB: it has been reported that there is an issue with this minifier and percentage values for opacity.&lt;br /&gt;
&lt;br /&gt;
== Accessing Players Information ==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.player_id: number&#039;&#039;&#039;&lt;br /&gt;
id of the player who is looking at the game. The player may not be part of the game (i.e. spectator)&lt;br /&gt;
  if (notif.args.player_id == this.player_id) {&lt;br /&gt;
    ...&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.isSpectator: boolean&#039;&#039;&#039;&lt;br /&gt;
Flag set to true if the user at the table is a spectator (not a player).&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    if (this.isSpectator) {&lt;br /&gt;
        this.player_color = &#039;ffffff&#039;;&lt;br /&gt;
    } else {&lt;br /&gt;
        this.player_color = gamedatas.players[this.player_id].color;&lt;br /&gt;
    }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note: If you want to hide an element from spectators, you should use [[Game_interface_stylesheet:_yourgamename.css#spectatorMode|CSS &#039;spectatorMode&#039; class]].&lt;br /&gt;
&lt;br /&gt;
You may consider making a function like this, to detect if the game is in a read-only state (i.e. non-interactive):&lt;br /&gt;
  // Returns true for spectators, instant replay (during game), archive mode (after game end)&lt;br /&gt;
  isReadOnly: function () {&lt;br /&gt;
    return this.isSpectator || typeof g_replayFrom != &#039;undefined&#039; || g_archive_mode;&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.gamedatas: object&#039;&#039;&#039;&lt;br /&gt;
Contains the initial set of data to init the game, created at game start or by game refresh (F5).&lt;br /&gt;
You can update it as needed to keep an up-to-date reference of the game on the client side if you need it, however most of the time this is unnecessary.&lt;br /&gt;
&lt;br /&gt;
Note: In hotseat mode, the framework does not keep this.gamedatas of hotseat players and shares the same set as the main player to store data.&lt;br /&gt;
&lt;br /&gt;
Note: be careful when you update this data structurally, many framework functions expect data to be certain way and they will break if they see something else.&lt;br /&gt;
&lt;br /&gt;
Typical example of accessing player&#039;s info&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
for (var player_id in this.gamedatas.players) { &lt;br /&gt;
    var playerInfo = this.gamedatas.players [player_id];&lt;br /&gt;
    var c = playerInfo.color;&lt;br /&gt;
    var name = playerInfo.name;&lt;br /&gt;
    // do something &lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.isCurrentPlayerActive(): boolean&#039;&#039;&#039;&lt;br /&gt;
Returns true if the player on whose browser the code is running is currently active (it&#039;s his turn to play). Note: see remarks above about usage of this function inside onEnteringState method.&lt;br /&gt;
  if (this.isCurrentPlayerActive()) ...&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.getActivePlayerId(): number&#039;&#039;&#039;&lt;br /&gt;
Return the ID of the active player, or null if we are not in an &amp;quot;activeplayer&amp;quot; type state.&lt;br /&gt;
  if (this.player_id == this.getActivePlayerId()) ...&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.getActivePlayers(): number[]&#039;&#039;&#039;&lt;br /&gt;
Return an array with the IDs of players who are currently active (or an empty array if there are none).&lt;br /&gt;
&lt;br /&gt;
== Accessing and manipulating the DOM ==&lt;br /&gt;
&lt;br /&gt;
=== Element by Id ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;$(elementId: ElementOrId)&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
The $ function is used to get an HTML element using its &amp;quot;id&amp;quot; attribute.&lt;br /&gt;
&lt;br /&gt;
Example: modify the content of a &amp;quot;span&amp;quot; element:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
In your HTML code:&lt;br /&gt;
   &amp;lt;span id=&amp;quot;a_value_in_the_game_interface&amp;quot;&amp;gt;1234&amp;lt;/span&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In your Javascript code:&lt;br /&gt;
   $(&#039;a_value_in_the_game_interface&#039;).innerHTML = &amp;quot;9999&amp;quot;;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Note: It is safe to use if you don&#039;t know if variable is string (id of element) or element itself, i.e. &lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  foo: function(card) {&lt;br /&gt;
       card = $(card); // now its node, no need to write if (typeof card === &#039;string&#039;) ...&lt;br /&gt;
       // but its good idea to check for null here&lt;br /&gt;
       ...&lt;br /&gt;
  }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;getElementById(elementId: string)&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Note: $() is the standard method to access some HTML element with the BGA Framework. You can use &#039;&#039;&#039;getElementById&#039;&#039;&#039; but a longer to type and less handy as it does not do some checks.&lt;br /&gt;
&lt;br /&gt;
=== Style ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;dojo.style(node: ElementOrId, styleName: string, styleValue: any): void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
With dojo.style you can modify the CSS property of any HTML element in your interface.&lt;br /&gt;
&lt;br /&gt;
Examples:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
     // Make an element disappear&lt;br /&gt;
     dojo.style( &#039;my_element&#039;, &#039;display&#039;, &#039;none&#039; );&lt;br /&gt;
&lt;br /&gt;
     // Give an element a 2px border&lt;br /&gt;
     dojo.style( &#039;my_element&#039;, &#039;borderWidth&#039;, &#039;2px&#039; );&lt;br /&gt;
&lt;br /&gt;
     // Change the background position of an element&lt;br /&gt;
     // (very practical when you are using CSS sprites to transform an element to another)&lt;br /&gt;
     dojo.style( &#039;my_element&#039;, &#039;backgroundPosition&#039;, &#039;-20px -50px&#039; );&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note: if you have to modify several CSS properties of an element, or if you have a complex CSS transformation to do, you should consider using dojo.addClass/dojo.removeClass (see below).&lt;br /&gt;
&lt;br /&gt;
You can also use object to set multiple values&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
dojo.setStyle(&amp;quot;thinger&amp;quot;, {&lt;br /&gt;
  &amp;quot;opacity&amp;quot;: 0.5,&lt;br /&gt;
  &amp;quot;border&amp;quot;: &amp;quot;3px solid black&amp;quot;,&lt;br /&gt;
  &amp;quot;height&amp;quot;: &amp;quot;300px&amp;quot;&lt;br /&gt;
});&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.addStyleToClass(cssClassName: string, styleName: string, styleValue: any):&#039;&#039;&#039; &#039;&#039;&#039;void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Same as dojo.style(), but for all the nodes set with the specified cssClassName&lt;br /&gt;
Equivalent of &lt;br /&gt;
  &lt;br /&gt;
  dojo.query(`.${aclass}`).style(styleName, styleValue)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
dojo.query(&amp;quot;#baz &amp;gt; div&amp;quot;).style({&lt;br /&gt;
  opacity:0.75,&lt;br /&gt;
  fontSize:&amp;quot;13pt&amp;quot;&lt;br /&gt;
});&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Vanilla JS style&#039;&#039;&#039;&lt;br /&gt;
  $(&#039;my_element&#039;).style.display=&#039;none&#039;; // set&lt;br /&gt;
  var display = $(&#039;my_element&#039;).style.display; // get&lt;br /&gt;
  $(&#039;my_element&#039;).style.removeProperty(&#039;display&#039;); // remove&lt;br /&gt;
&lt;br /&gt;
=== Classes ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;dojo.addClass(node: ElementOrId, classes: string): void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;dojo.removeClass(node: ElementOrId, classes: string): void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;dojo.hasClass(node: ElementOrId, aclass: string): void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;dojo.toggleClass(node: ElementOrId, aclass: string): void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
In many situations, many small CSS property updates can be replaced by a CSS class change (i.e., you add a CSS class to your element instead of applying all modifications manually).&lt;br /&gt;
&lt;br /&gt;
Advantages are:&lt;br /&gt;
* All your CSS stuff remains in your CSS file.&lt;br /&gt;
* You can add/remove a list of CSS modifications with a simple function and without error.&lt;br /&gt;
* You can test whether you applied the CSS to an element with the &#039;&#039;&#039;dojo.hasClass&#039;&#039;&#039; method.&lt;br /&gt;
&lt;br /&gt;
Example from &#039;&#039;Reversi&#039;&#039;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    // We add &amp;quot;possibleMove&amp;quot; to an element&lt;br /&gt;
    dojo.addClass( &#039;square_&#039;+x+&#039;_&#039;+y, &#039;possibleMove&#039; );&lt;br /&gt;
&lt;br /&gt;
    // In our CSS file, the class is defined as:&lt;br /&gt;
    .possibleMove {&lt;br /&gt;
      background-color: white;&lt;br /&gt;
      opacity: 0.2;&lt;br /&gt;
      filter:alpha(opacity=20); /* For IE8 and earlier */  &lt;br /&gt;
      cursor: pointer;  &lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
     // So we&#039;ve applied 4 CSS property changes in one line of code.&lt;br /&gt;
&lt;br /&gt;
     // ... and when we need to check if a square is a possible move on the client side:&lt;br /&gt;
     if( dojo.hasClass( &#039;square_&#039;+x+&#039;_&#039;+y, &#039;possibleMove&#039; ) )&lt;br /&gt;
     { ... }&lt;br /&gt;
&lt;br /&gt;
     // ... and if we want to remove all possible moves in one line of code (see &amp;quot;dojo.query&amp;quot; method):&lt;br /&gt;
     dojo.query( &#039;.possibleMove&#039; ).removeClass( &#039;possibleMove&#039; );&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Vanilla JS classList&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
This is the only exception where dojo versions are better&lt;br /&gt;
  // add class&lt;br /&gt;
  $(token_id).classList.addClass(&#039;possibleMove&#039;);&lt;br /&gt;
  // remove class&lt;br /&gt;
  $(token_id).classList.removeClass(&#039;possibleMove&#039;);&lt;br /&gt;
  // add 2 classes&lt;br /&gt;
  const myclasses = [&#039;a&#039;,&#039;b&#039;];&lt;br /&gt;
  $(token_id).classList.addClass(...myclasses);&lt;br /&gt;
  // add classes to query result&lt;br /&gt;
  document.querySelectorAll(&amp;quot;.hand .card&amp;quot;).forEach((node)=&amp;gt;node.classList.addClass(&#039;possibleMove&#039;));&lt;br /&gt;
&lt;br /&gt;
=== Attributes ===&lt;br /&gt;
&lt;br /&gt;
;dojo.attr&lt;br /&gt;
&lt;br /&gt;
With dojo.attr you can access or change the value of an attribute or property of any HTML element in your interface.&lt;br /&gt;
&lt;br /&gt;
Exemple:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
     // Get the title of a node&lt;br /&gt;
     var title = dojo.attr( id, &#039;title&#039; );&lt;br /&gt;
     // Change the height of a node&lt;br /&gt;
     dojo.attr( &#039;img_growing_tree&#039;, &#039;height&#039;, 100 );&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Vanilla JS attr&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
   $(token).id=new_id; // set attr for &amp;quot;id&amp;quot;&lt;br /&gt;
   var id = $(token).id; // get&lt;br /&gt;
&lt;br /&gt;
=== Queries ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;dojo.query(cssSelector: string): Element[]&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
With dojo.query, you can query a bunch of HTML elements with a single function, with a &amp;quot;CSS selector&amp;quot; style.&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
     // All elements with class &amp;quot;possibleMove&amp;quot;:&lt;br /&gt;
     var elements = dojo.query( &#039;.possibleMove&#039; );&lt;br /&gt;
&lt;br /&gt;
     // Count number of tokens (i.e., elements of class &amp;quot;token&amp;quot;) on the board (i.e., the element with id &amp;quot;board&amp;quot;):&lt;br /&gt;
     dojo.query( &#039;#board .token&#039; ).length;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
But what is really cool with dojo.query is that you can combine it with almost all methods above.&lt;br /&gt;
&lt;br /&gt;
Examples:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
     // Trigger a method when the mouse enter in any element with class &amp;quot;meeple&amp;quot;:&lt;br /&gt;
     dojo.query( &#039;.meeple&#039; ).connect( &#039;onmouseenter&#039;, this, &#039;myMethodToTrigger&#039; );&lt;br /&gt;
&lt;br /&gt;
     // Hide all meeples who are on the board&lt;br /&gt;
     dojo.query( &#039;#board .meeple&#039; ).style( &#039;display&#039;, &#039;none&#039; );&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Vanilla JS query&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
  var cards=document.querySelectorAll(&amp;quot;.hand .card&amp;quot;);// all cards in all hands&lt;br /&gt;
  var cards=$(&#039;hand&#039;).querySelectorAll(&amp;quot;.card&amp;quot;);// all cards in specific hand&lt;br /&gt;
  var card=document.querySelector(&amp;quot;.hand .card&amp;quot;);// first card or null if none (super handy)&lt;br /&gt;
&lt;br /&gt;
=== Creating and Destroying elements ===&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;dojo.empty(node: ElementOrId)&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Remove all children of the node element&lt;br /&gt;
   dojo.empty(&#039;my_hand&#039;);&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;dojo.destroy(node: ElementOrId)&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Remove the element&lt;br /&gt;
   dojo.destroy(&#039;my_token&#039;);&lt;br /&gt;
&lt;br /&gt;
   dojo.query(&amp;quot;.green&amp;quot;, mynode).forEach(dojo.destroy); // this remove all subnode of class green from mynode&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;dojo.create(tag: string, attributes?: obj, parent?: ElementOrId): Element&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Create element&lt;br /&gt;
&lt;br /&gt;
    dojo.create(&amp;quot;div&amp;quot;, { class: &amp;quot;yellow_arrow&amp;quot; }, parent); // this creates div with class yellow_array and places it in &amp;quot;parent&amp;quot;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.format_block(name: string, args: object): string&#039;&#039;&#039;&lt;br /&gt;
This bga function that takes global var from template file and substitute variables, typical use would be&lt;br /&gt;
&lt;br /&gt;
                var player = gamedatas.players[player_id];&lt;br /&gt;
                var div = this.format_block(&#039;jstpl_player_board&#039;, player ); // var jstpl_player_board = ... is defined in .tpl file &lt;br /&gt;
Note: result is trimmed&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.format_string(name: string, args: object): string&#039;&#039;&#039;&lt;br /&gt;
This bga function just substitute variables in a string, i.e.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
     var div = this.format_string(&#039;&amp;lt;div color=&amp;quot;${player_color}&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&#039;, {player_color: &#039;#ff0000&#039;} );&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Note: result is trimmed&lt;br /&gt;
&lt;br /&gt;
Note: this can be replaced by using backquoted string now: &lt;br /&gt;
     const player_color =  &#039;#ff0000&#039;;&lt;br /&gt;
     const div = `&amp;lt;div color=&amp;quot;${player_color}&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;`;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.format_string_recursive&#039;&#039;&#039;&lt;br /&gt;
This bga function is similar to this.format_string but is capable of processing recursive argument structures and translations. It is used to format server notifications.&lt;br /&gt;
&lt;br /&gt;
TODO: find better place for these function docs&lt;br /&gt;
&lt;br /&gt;
=== Moving elements ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;dojo.place(node: string | Element, refNode: ElementOrId, pos?: string | number): Element&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
dojo.place is the best function to insert HTML code somewhere in your game interface without breaking something. It is much better to use than the &#039;&#039;&#039;innerHTML=&#039;&#039;&#039; method if you must insert HTML tags and not only values.&lt;br /&gt;
&lt;br /&gt;
node: &lt;br /&gt;
&lt;br /&gt;
Can be a String or a DOM node. If it is a string starting with “&amp;lt;”, it is assumed to be an HTML fragment, which will be created. Otherwise it is assumed to be an id of a DOM node.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
     // Insert your HTML code as a child of a container element&lt;br /&gt;
     dojo.place( &amp;quot;&amp;lt;div class=&#039;foo&#039;&amp;gt;&amp;lt;/div&amp;gt;&amp;quot;, &amp;quot;your_container_element_id&amp;quot; );&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
pos:&lt;br /&gt;
&lt;br /&gt;
Optional argument. Can be a number or one of the following strings: “before”, “after”, “replace”, “only”, “first”, or “last”. If omitted, “last” is assumed. &lt;br /&gt;
&lt;br /&gt;
&amp;quot;replace&amp;quot;: Replace the container element with my_node element&lt;br /&gt;
&lt;br /&gt;
&amp;quot;first&amp;quot;: Places the node as a child of the reference node. The node is placed as the first child.&lt;br /&gt;
&lt;br /&gt;
&amp;quot;last&amp;quot; (default): Places the node as a child of the reference node. The node is placed as the last child.&lt;br /&gt;
&lt;br /&gt;
&amp;quot;before&amp;quot;: places the node right before the reference node.&lt;br /&gt;
&lt;br /&gt;
&amp;quot;after&amp;quot;: places the node right after the reference node.&lt;br /&gt;
&lt;br /&gt;
&amp;quot;only&amp;quot;: replaces all children of the reference node with the node.&lt;br /&gt;
&lt;br /&gt;
positive integer: This parameter can be a positive integer. In this case, the node will be placed as a child of the reference node with this number (counting from 0). If the number is more than number of children, the node will be appended to the reference node making it the last child. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
     // Replace all children of container with my_node &lt;br /&gt;
     dojo.place( $(&#039;my_node&#039;), &amp;quot;your_container_element_id&amp;quot;, &amp;quot;only&amp;quot; );&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
See also full doc on dojo.place: [https://dojotoolkit.org/reference-guide/1.7/dojo/place.html]&lt;br /&gt;
&lt;br /&gt;
Usually, when you want to insert some piece of HTML in your game interface, you should use &amp;quot;[[Game_layout:_view_and_template:_yourgamename.view.php_and_yourgamename_yourgamename.tpl#Javascript_templates|Javascript templates]]&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
But you can also relocate elements like that. Note: it won&#039;t animate if you do that.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.placeOnObject(mobile_obj: ElementOrId, target_obj: ElementOrId): void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
places mobile_obj on target_obj, set the absolute positions and centers the mobile_obj on target_obj,&lt;br /&gt;
effect is immediate&lt;br /&gt;
&lt;br /&gt;
This is not really an animation, but placeOnObject is frequently used before starting an animation.&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  // (We just created an object &amp;quot;my_new_token&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
  // Place the new token on current player board&lt;br /&gt;
  this.placeOnObject( &amp;quot;my_new_token&amp;quot;, &amp;quot;overall_player_board_&amp;quot;+this.player_id );&lt;br /&gt;
  &lt;br /&gt;
  // Then slide it to its position on the board&lt;br /&gt;
  this.slideToObject( &amp;quot;my_new_token&amp;quot;, &amp;quot;a_place_on_board&amp;quot; ).play();&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.placeOnObjectPos(mobile_obj: ElementOrId, target_obj: ElementOrId, target_x: number, target_y: number): void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
This method works exactly like placeOnObject, except than you can specify some (x,y) coordinates (in px). This way, the center of &amp;quot;mobile_obj&amp;quot; will be placed to the specified x,y position relatively to the center of &amp;quot;target_obj&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Note: the placement works differently from this.slideToObjectPos&#039;&#039;, since coordinates are calculated based on the center of objects.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.attachToNewParent(mobile_obj: ElementOrId, target_obj: ElementOrId): void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
With this method, you change the HTML parent of &amp;quot;mobile_obj&amp;quot; element without moving it. &lt;br /&gt;
&amp;quot;target_obj&amp;quot; is the new parent of this element. The beauty of &lt;br /&gt;
attachToNewParent is that the mobile_obj element DOES NOT MOVE during this process.&lt;br /&gt;
&lt;br /&gt;
What happens is that the method calculate a relative position of mobile_obj to make sure it does not move after the HTML parent changes.&lt;br /&gt;
&lt;br /&gt;
Why using this method?&lt;br /&gt;
&lt;br /&gt;
Changing the HTML parent of an element can be useful for the following reasons:&lt;br /&gt;
* When the HTML parent moves, all its child are moving with them. If some game elements is no more linked with a parent HTML object, you may want to attach it to another place.&lt;br /&gt;
* The z_order (vertical order of display) depends on the position in the DOM, so you may need to change the parent of some game elements when they are moving in your game area.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;CAREFUL&#039;&#039;&#039;: this function destroys original object and places a clone onto a new parent, this will break all references to this HTML element (ex: dojo.connect).&lt;br /&gt;
If you need version that does not destroy the object but the same otherwise see [[BGA_Studio_Cookbook#Attach_to_new_parent_without_destroying_the_object]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Animations ==&lt;br /&gt;
&lt;br /&gt;
===Dojo Animations===&lt;br /&gt;
&lt;br /&gt;
BGA animations is based on Dojo Animation ([http://dojotoolkit.org/documentation/tutorials/1.8/animation/ see tutorial here]).&lt;br /&gt;
&lt;br /&gt;
However, most of the time, you can just use methods below, which are built on top of Dojo Animation.&lt;br /&gt;
&lt;br /&gt;
Note: one interesting method from Dojo that could be useful from time to time is &amp;quot;Dojo.Animation&amp;quot;. It allows you to make any CSS property &amp;quot;slide&amp;quot; from one value to another.&lt;br /&gt;
&lt;br /&gt;
Note 2: the slideTo methods are not compatible with CSS transform (scale, zoom, rotate...). If possible, avoid using CSS transform on nodes that are being slided. Eventually, the only possible solution to make these 2 compatible is to disable all CSS transform properties, use slideToObjectPos/placeOnObjectPos, and then apply them again.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Sliding===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.slideToObject(mobile_obj: ElementOrId, target_obj: ElementOrId, duration?: number, delay?: number): Animation&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
You can use slideToObject to &amp;quot;slide&amp;quot; an element to a target position.&lt;br /&gt;
&lt;br /&gt;
Sliding element on the game area is the recommended and the most used way to animate your game interface. Using slides allow players to figure out what is happening on the game, as if they were playing with the real boardgame.&lt;br /&gt;
&lt;br /&gt;
The parameters are:&lt;br /&gt;
* mobile_obj: the ID of the object to move. This object must be &amp;quot;relative&amp;quot; or &amp;quot;absolute&amp;quot; positioned.&lt;br /&gt;
* target_obj: the ID of the target object. This object must be &amp;quot;relative&amp;quot; or &amp;quot;absolute&amp;quot; positioned. Note that it is not mandatory that mobile_obj and target_obj have the same size. If their size are different, the system slides the center of mobile_obj to the center of target_obj.&lt;br /&gt;
* duration: (optional) defines the duration in millisecond of the slide. The default is 500 milliseconds.&lt;br /&gt;
* delay: (optional). If you defines a delay, the slide will start only after this delay. This is particularly useful when you want to slide several object from the same position to the same position: you can give a 0ms delay to the first object, a 100ms delay to the second one, a 200ms delay to the third one, ... this way they won&#039;t be superposed during the slide.&lt;br /&gt;
&lt;br /&gt;
BE CAREFUL: The method returns an dojo.fx animation, so you can combine it with other animation if you want to. It means that you have to call the &amp;quot;play()&amp;quot; method, otherwise the animation WON&#039;T START.&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
   this.slideToObject( &amp;quot;some_token&amp;quot;, &amp;quot;some_place_on_board&amp;quot; ).play();&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.slideToObjectPos(mobile_obj: ElementOrId, target_obj: ElementOrId, target_x: number, target_y: number, duration?: number, delay?: number): Animation&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
This method does exactly the same as &amp;quot;slideToObject&amp;quot;, except than you can specify some (x,y) coordinates. This way, &amp;quot;mobile_obj&amp;quot; will slide to the specified x,y position relatively to &amp;quot;target_obj&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
Example: slide a token to some place on the board, 10 pixels from the top:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
   this.slideToObjectPos( &amp;quot;some_token&amp;quot;, &amp;quot;some_place_on_board&amp;quot;, 0, 10 ).play();&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.slideTemporaryObject(mobile_obj_html: string, parent: ElementOrId, from: ElementOrId, to: ElementOrId, duration?: number, delay?: number): Animation&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
This method is useful when you want to slide a temporary HTML object from one place to another. As this object does not exists before the animation and won&#039;t remain after, it could be complex to create this object (with dojo.place), to place it at its origin (with placeOnObject) to slide it (with slideToObject) and to make it disappear at the end.&lt;br /&gt;
&lt;br /&gt;
slideTemporaryObject does all of this for you:&lt;br /&gt;
* mobile_obj_html is a piece of HTML code that represent the object to slide.&lt;br /&gt;
* parent is the ID of an HTML element of your interface that will be the parent of this temporary HTML object.&lt;br /&gt;
* from is the ID of the origin of the slide.&lt;br /&gt;
* to is the ID of the target of the slide.&lt;br /&gt;
* duration/delay works exactly like in &amp;quot;slideToObject&amp;quot;&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
this.slideTemporaryObject( &#039;&amp;lt;div class=&amp;quot;token_icon&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&#039;, &#039;tokens&#039;, &#039;my_origin_div&#039;, &#039;my_target_div&#039; ).play();&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Destroy===&lt;br /&gt;
&#039;&#039;&#039;this.slideToObjectAndDestroy(mobile_obj: ElementOrId, target_obj: ElementOrId, duration?: number, delay?: number): void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
This method is a handy shortcut to slide an existing HTML object to some place then destroy it upon arrival. It can be used for example to move a victory token or a card from the board to the player panel to show that the player earns it, then destroy it when we don&#039;t need to keep it visible on the player panel.&lt;br /&gt;
&lt;br /&gt;
It works the same as this.slideToObject and takes the same arguments, but it starts the animation. &lt;br /&gt;
&lt;br /&gt;
CAREFUL: Make sure nothing is creating the same object at the same time the animation is running, because this will cause some random disappearing effects&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
this.slideToObjectAndDestroy( &amp;quot;some_token&amp;quot;, &amp;quot;some_place_on_board&amp;quot;, 1000, 0 );&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.fadeOutAndDestroy( node: string | Element, duration?: number, delay?: number):&#039;&#039;&#039; &#039;&#039;&#039;void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
This function fade out the target node, then destroy it. Its starts the animation.&lt;br /&gt;
* duration/delay works exactly like in &amp;quot;slideToObject&amp;quot;&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
   this.fadeOutAndDestroy( &amp;quot;a_card_that_must_disappear&amp;quot; );&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
CAREFUL: the HTML node still exists until during few milliseconds, until the fadeOut has been completed.&lt;br /&gt;
Make sure nothing is creating same object at the same time as animation is running, because you will be some random dissapearing effects&lt;br /&gt;
&lt;br /&gt;
===Rotating elements===&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
This example combines &amp;quot;Dojo.Animation&amp;quot; method and a CSS property transform that allow you to rotate the element.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
// node is Element we rotating&lt;br /&gt;
		    var animation = new dojo.Animation({&lt;br /&gt;
			    curve: [fromDegree, toDegree],&lt;br /&gt;
			    onAnimate: (v) =&amp;gt; {&lt;br /&gt;
				    node.style.transform = &#039;rotate(&#039; + v + &#039;deg)&#039;;&lt;br /&gt;
			    } &lt;br /&gt;
		    });&lt;br /&gt;
		    &lt;br /&gt;
		    animation.play();  &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
BGA has its own interface to rotate&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.rotateTo(node: string | Element, degree: number): void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
It starts the animation, and stored the rotation degree in the class, so next time you rotate object - it is additive.&lt;br /&gt;
There is no animation hooks in this one, if you need to change any parameters use dojo animation above.&lt;br /&gt;
&lt;br /&gt;
There is also &#039;&#039;&#039;rotateInstantTo&#039;&#039;&#039; with same signature which does not animate&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Animation Callbacks===&lt;br /&gt;
&lt;br /&gt;
If you wish to run some code only after an animation has completed you can do this by linking a callback method to &#039;onEnd&#039;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
var animation_id = this.slideToObject( mobile_obj, target_obj, 500 );&lt;br /&gt;
dojo.connect(animation_id, &#039;onEnd&#039;, () =&amp;gt; {&lt;br /&gt;
   // do something here&lt;br /&gt;
});&lt;br /&gt;
animation_id.play();&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If you wish to call a second animation after the first (rather than general code) then you can use a dojo animation chain (see tutorial referenced above).&lt;br /&gt;
&lt;br /&gt;
== Players input ==&lt;br /&gt;
&lt;br /&gt;
=== Connecting ===&lt;br /&gt;
&#039;&#039;&#039;dojo.connect(element: Element, event: string, context: object, method: eventHandler): any&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;dojo.connect(element: Element, event: string, hander: eventHandler): any&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Used to associate a player event with one of your notification methods.&lt;br /&gt;
&lt;br /&gt;
Example: associate a click on an element (&amp;quot;my_element&amp;quot;) with one of our methods (&amp;quot;onClickOnMyElement&amp;quot;):&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
      dojo.connect( $(&#039;my_element&#039;), &#039;onclick&#039;, this, &#039;onClickOnMyElement&#039; );&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Same idea but base on query (i.e. all element of &#039;pet&#039; class)&lt;br /&gt;
      dojo.query(&amp;quot;.pet&amp;quot;).connect(&#039;onclick&#039;, this, &#039;onPet&#039;);&lt;br /&gt;
&lt;br /&gt;
Note: if you need to disconnect the handler you have to store handler returned from this method, i.e.&lt;br /&gt;
   &lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    var handler = dojo.connect(...);&lt;br /&gt;
    ...&lt;br /&gt;
    dojo.disconnect(handler);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If you don&#039;t store the handler - you have to destroy the object to disconnect it&lt;br /&gt;
&lt;br /&gt;
Typical function that implements the input handler will look like this&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
onPet: function(event) {&lt;br /&gt;
    var id = event.currentTarget.id;&lt;br /&gt;
    console.log(&#039;onPet &#039; + id);&lt;br /&gt;
    dojo.stopEvent(event);&lt;br /&gt;
    if (this.gamedatas.gamestate.name == &#039;playerTurnPet&#039;) {&lt;br /&gt;
          this.bgaPerformAction(&#039;actPlayPet&#039;, {card: id});&lt;br /&gt;
    } else {&lt;br /&gt;
          this.showMoveUnauthorized();&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.connect(element: ElementOrId, event: string, method: eventHandler): void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Used to associate a player event with one of your notification methods.&lt;br /&gt;
&lt;br /&gt;
      this.connect( $(&#039;my_element&#039;), &#039;onclick&#039;, &#039;onClickOnMyElement&#039; );&lt;br /&gt;
&lt;br /&gt;
Or you can use an in-place handler&lt;br /&gt;
&lt;br /&gt;
      this.connect( $(&#039;my_element&#039;), &#039;onclick&#039;, (e) =&amp;gt; { console.log(&#039;boo&#039;); } );&lt;br /&gt;
&lt;br /&gt;
Note that this function stores the connection handler. That is the only real difference between &#039;&#039;&#039;this.connect&#039;&#039;&#039; and &#039;&#039;&#039;dojo.connect&#039;&#039;&#039;. If you plan to destroy the element you connected, you &#039;&#039;&#039;must&#039;&#039;&#039; call this.disconnect() to prevent memory leaks.&lt;br /&gt;
This function is mainly for permanent objects - if you just want to connect the temp object you should probably not use this method but use dojo.connect which won&#039;t require any clean-up.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.connectClass(cssClassName: string, event: string, method: eventHandler): void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Same as connect(), but for all the nodes set with the specified cssClassName.&lt;br /&gt;
&lt;br /&gt;
	this.connectClass(&#039;pet&#039;, &#039;onclick&#039;, &#039;onPet&#039;);&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.disconnect(element: ElementOrId, event: string): void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Disconnect event handler (previously registered with this.connect or this.connectClass).&lt;br /&gt;
&lt;br /&gt;
   this.disconnect( $(&#039;my_element&#039;), &#039;onclick&#039;);&lt;br /&gt;
&lt;br /&gt;
Note: dynamic connect/disconnect is for advanced cases ONLY, you should always connect elements statically if possible, i.e. in setup() method.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.disconnectAll(): void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Disconnect all previously registed event handlers (registered via this.connect or this.connectClass)&lt;br /&gt;
&lt;br /&gt;
  this.disconnectAll();&lt;br /&gt;
&lt;br /&gt;
=== Actions ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.bgaPerformAction(action: string, args?: object, options: object = { lock: true, checkAction: true }): Promise&amp;lt;void&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Triggers an action on the backend. This is a combination of checkAction and ajaxcall, returning a Promise which resoves when ajaxcall ends.&lt;br /&gt;
&lt;br /&gt;
This method must be used to send a player input to the game server. &#039;&#039;&#039;It should not be triggered programmatically&#039;&#039;&#039;, especially not in loops, in callbacks, in notifications, or in onEnteringState/onUpdateActionButtons/onLeavingState, in order not to create race conditions or break replay game and tutorial features. It should be used only in reaction to a user action in the interface.&lt;br /&gt;
&lt;br /&gt;
* action: name of the action, as it is written in &amp;quot;possibleactions&amp;quot; of the current state.&lt;br /&gt;
* args: an object containing the call parameters to send to the action&lt;br /&gt;
* options: options to tweak the call with some defaults. Default is &amp;lt;code&amp;gt;{ lock: true, checkAction: true }&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Example of a standard call without args:&lt;br /&gt;
  this.bgaPerformAction(&#039;pass&#039;);&lt;br /&gt;
&lt;br /&gt;
Example of a standard call with action args:&lt;br /&gt;
  this.bgaPerformAction(&#039;actPlayCard&#039;, { id: this.selectedCardId });&lt;br /&gt;
&lt;br /&gt;
Example of a call without checking action (because player is inactive in a multiactive state):&lt;br /&gt;
&lt;br /&gt;
 this.bgaPerformAction(&#039;actChangeMind&#039;, {}, { checkAction: false });&lt;br /&gt;
&lt;br /&gt;
Example of a call without lock (because of a special action not directly related to the game flow):&lt;br /&gt;
&lt;br /&gt;
 this.bgaPerformAction(&#039;actSetAutoBid&#039;, { alwaysBidUntil: 500 }, { lock: false, checkAction: false });&lt;br /&gt;
&lt;br /&gt;
Example of call with reaction to exception:&lt;br /&gt;
  this.bgaPerformAction(&#039;actPlayCard&#039;, { id: this.selectedCardId }).catch(()=&amp;gt;{ this.selectedCardId = undefined; });&lt;br /&gt;
&lt;br /&gt;
Example of call with reaction to success:&lt;br /&gt;
  this.bgaPerformAction(&#039;actPlayCard&#039;, { id: this.selectedCardId }).then(()=&amp;gt;{ this.unselectAll(); });&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.ajaxcall(url, parameters, obj_callback, callback, callback_anycase?, ajax_method?: string)&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Note: bgaPerformAction is a simpler way to use ajax calls, ajaxcall stays in the doc for legacy reasons only and should not be used in new projects.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Same warning as &#039;&#039;&#039;this.bgaPerformAction&#039;&#039;&#039; about using on user action only.&lt;br /&gt;
&lt;br /&gt;
* url: the url of the action to perform. For a game, it must be: &amp;quot;/&amp;lt;mygame&amp;gt;/&amp;lt;mygame&amp;gt;/myAction.html&amp;quot;&lt;br /&gt;
* parameters: an array of parameter to send to the game server. &lt;br /&gt;
** Note that &amp;quot;lock: true&amp;quot; must always be specified in this list of parameters in order the interface can be locked during the server call. Cannot use lock: false - to not lock it has to be undefined.&lt;br /&gt;
** Note: Restricted parameter names (please don&#039;t use them):&lt;br /&gt;
*** &amp;quot;action&amp;quot;&lt;br /&gt;
*** &amp;quot;module&amp;quot;&lt;br /&gt;
*** &amp;quot;class&amp;quot;&lt;br /&gt;
* obj_callback: must be set to &amp;quot;this&amp;quot;.&lt;br /&gt;
* callback (non-optional but rarely used): a function to trigger when the server returns result and everything went fine (not used, as all data handling is done via notifications).&lt;br /&gt;
* callback_anycase: (optional) a function to trigger when the server returns ok OR error.  If no error this function is called with parameter value false. If an error occurred, the first parameter will be set to true, the second will contain the error message sent by the PHP back-end, and the third will contain an error code.&lt;br /&gt;
* ajax_method: (optional and rarely used) if you need to send large amounts of data (over 2048 bytes), you can set this parameter to &#039;post&#039; (all lower-case) to send a POST request as opposed to the default GET. This works, but was not officially documented, so only use if you really need to.&lt;br /&gt;
&lt;br /&gt;
Usage:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
this.ajaxcall( &#039;/mygame/mygame/actMyAction.html&#039;, { lock: true, &lt;br /&gt;
   arg1: myarg1, &lt;br /&gt;
   arg2: myarg2&lt;br /&gt;
}, this, (result)=&amp;gt;{} );&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.checkAction(action: string, nomessage?: boolean): boolean &#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Check if player can do the specified action by taking into account:&lt;br /&gt;
* if interface is locked it will return false and show message &amp;quot;An action is already in progress&amp;quot;,  unless nomessage set to true &lt;br /&gt;
* if player is not active it will return false and show message &amp;quot;This is not your turn&amp;quot;, unless nomessage set to true &lt;br /&gt;
* if action is not in list in possible actions (defined by &amp;quot;possibleaction&amp;quot; in current game state) it will return false and show &amp;quot;This move is not authorized now&amp;quot; error (unconditionally).&lt;br /&gt;
* otherwise returns true&lt;br /&gt;
Example:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  function onClickOnGameElement( evt )  {&lt;br /&gt;
     if( this.checkAction( &amp;quot;actMyAction&amp;quot; ) ) {&lt;br /&gt;
        // Do the action&lt;br /&gt;
     }&lt;br /&gt;
  }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.checkPossibleActions(action: string): boolean&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
* this is independent of the player being active, so can be used instead of this.checkAction(). This is particularly useful for multiplayer states when the player is not active in a &#039;player may like to change their mind&#039; scenario. Unlike this.checkAction, this function does NOT take interface locking into account &lt;br /&gt;
&lt;br /&gt;
* if action is not in list in possible actions (defined by &amp;quot;possibleaction&amp;quot; in current game state) it will return false and show &amp;quot;This move is not authorized now&amp;quot; error (unconditionally).&lt;br /&gt;
* otherwise returns true&lt;br /&gt;
&lt;br /&gt;
  function onChangeMyMind( evt )  {&lt;br /&gt;
     if( this.checkPossibleActions( &amp;quot;actMyAction&amp;quot; ) ) {&lt;br /&gt;
        // Do the action&lt;br /&gt;
     }&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.checkLock(nomessage?: boolean): boolean&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
When using &amp;quot;lock: true&amp;quot; in ajax call you can use this function to check if interface is in lock state (it will be locked during server call and notification processing).&lt;br /&gt;
This check can be used to block some other interactions which do not result in ajaxcall or if you want to suppress errors. Note: normally you only need to use this.checkAction(...), this is for advanced cases.&lt;br /&gt;
&lt;br /&gt;
It will also show error unless nomessage is set to true&lt;br /&gt;
&lt;br /&gt;
  function onChangeMyMind( evt )  {&lt;br /&gt;
     if( this.checkLock() ) {&lt;br /&gt;
        // Do the action&lt;br /&gt;
     }&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
== Notifications ==&lt;br /&gt;
&lt;br /&gt;
When something happens on the server side, your game interface Javascript logic received a notification.&lt;br /&gt;
If you have not done so yet check what notification are in [[Main_game_logic:_yourgamename.game.php#Notifications]]&lt;br /&gt;
&lt;br /&gt;
Here&#039;s how you can handle these notifications on the client side.&lt;br /&gt;
&lt;br /&gt;
=== Subscribe to notifications ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;dojo.subscribe(notif_type: string, callback_obj: Object, handler: string|handler)&#039;&#039;&#039;&lt;br /&gt;
* notif_type - notification type/name send by php server&lt;br /&gt;
* callback_obj - usually this&lt;br /&gt;
* handler - if string method of callback_obj with name name is called, when notification is called, with notification object as parameter (see below)&lt;br /&gt;
&lt;br /&gt;
Your Javascript &amp;quot;setupNotifications&amp;quot; method is the place where you can subscribe to notifications from your PHP code.&lt;br /&gt;
&lt;br /&gt;
Here&#039;s how you associate one of your Javascript method to a notification &amp;quot;playDisc&amp;quot; (from Reversi example):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
   setupNotifications: function() {&lt;br /&gt;
      ...&lt;br /&gt;
      dojo.subscribe(&#039;playDisc&#039;, this, &amp;quot;notif_playDisc&amp;quot;);&lt;br /&gt;
   },&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note: the &amp;quot;playDisc&amp;quot; corresponds to the name of the notification you define it in your PHP code, in your &amp;quot;notifyAllPlayers&amp;quot; or &amp;quot;notifyPlayer&amp;quot; method.&lt;br /&gt;
&lt;br /&gt;
Then, you have to define your &amp;quot;notif_playDisc&amp;quot; method:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
   notif_playDisc: function(notif) {&lt;br /&gt;
     // Remove current possible moves (makes the board more clear)&lt;br /&gt;
     dojo.query( &#039;.possibleMove&#039; ).removeClass( &#039;possibleMove&#039; );          &lt;br /&gt;
     this.addDiscOnBoard( notif.args.x, notif.args.y, notif.args.player_id );&lt;br /&gt;
   },&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In a notification handler like our &amp;quot;notif_playDisc&amp;quot; method, you can access all notifications arguments with &amp;quot;notif.args&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&lt;br /&gt;
PHP&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    $this-&amp;gt;notifyAllPlayers( &amp;quot;apples&amp;quot;, clienttranslate(&#039;player takes ${count} apples&#039;), [ &amp;quot;count&amp;quot; =&amp;gt; 3 ] );&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
JavaScript&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    setupNotifications: function() {&lt;br /&gt;
       dojo.subscribe( &#039;apples&#039;, this, &#039;notif_apples&#039; );&lt;br /&gt;
    },&lt;br /&gt;
&lt;br /&gt;
    notif_apples: function(notif) {&lt;br /&gt;
      //You can access the &amp;quot;count&amp;quot; like this:&lt;br /&gt;
       alert(&amp;quot;count = &amp;quot; + notif.args.count);&lt;br /&gt;
    }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== The notification Object received by client ===&lt;br /&gt;
&lt;br /&gt;
When sending a notification on your PHP, the client side will receive an Object with the following attributes:&lt;br /&gt;
&lt;br /&gt;
* type - type of the notification (as passed by php function)&lt;br /&gt;
* log - the log string passed from php notification&lt;br /&gt;
* args - This is the arguments that you passed on your notification method on php&lt;br /&gt;
* bIsTableMsg - is true when you use [[Main_game_logic:_yourgamename.game.php#NotifyAllPlayers|NotifyAllPlayers]] method (false otherwise)&lt;br /&gt;
* channelorig - information about table ID (formatted as : &amp;quot;/table/t[TABLE_NUMBER]&amp;quot;)&lt;br /&gt;
* gamenameorig - name of the game&lt;br /&gt;
* move_id - ID of the move associated with the notification&lt;br /&gt;
* table_id - ID of the table (comes as string)&lt;br /&gt;
* time - UNIX GMT timestamp&lt;br /&gt;
* uid - unique identifier of the notification&lt;br /&gt;
* h - unknown&lt;br /&gt;
&lt;br /&gt;
&#039;&#039; Note that those information were inferred from observation on console log. If an Admin can confirm/correct (and remove this line), you&#039;re welcome :)&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
=== Ignoring notifications ===&lt;br /&gt;
&lt;br /&gt;
Sometimes you need to ignore some notification on client side. You don&#039;t want them to be shown in game log and you don&#039;t want them to be handled.&lt;br /&gt;
&lt;br /&gt;
The most common use case is when a player gets private information. They will receive a specific notification (such as &amp;quot;You received Ace of Heart&amp;quot;), while other players would receive more generic notification (&amp;quot;Player received a card&amp;quot;).&lt;br /&gt;
&lt;br /&gt;
In X.game.php&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        $this-&amp;gt;notifyAllPlayers(&amp;quot;dealCard&amp;quot;, clienttranslate(&#039;${player_name} received a card&#039;), [&lt;br /&gt;
            &#039;player_id&#039; =&amp;gt; $playerId,&lt;br /&gt;
            &#039;player_name&#039; =&amp;gt; $this-&amp;gt;getActivePlayerName()&lt;br /&gt;
        ]);&lt;br /&gt;
&lt;br /&gt;
        $this-&amp;gt;notifyPlayer($playerId, &amp;quot;dealCardPrivate&amp;quot;, clienttranslate(&#039;You received ${cardName}&#039;), [&lt;br /&gt;
            &amp;quot;type&amp;quot; =&amp;gt; $card[&amp;quot;type&amp;quot;],&lt;br /&gt;
            &amp;quot;cardName&amp;quot; =&amp;gt; $this-&amp;gt;getCardName($card[&amp;quot;type&amp;quot;])&lt;br /&gt;
        ]);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The problem with this approach is that the active player will receive two notifications:&lt;br /&gt;
* Player1 received a card&lt;br /&gt;
* You received Ace of Hearts&lt;br /&gt;
&lt;br /&gt;
Hence, notification ignoring.&lt;br /&gt;
&lt;br /&gt;
NOTE: You can think that it would be possible to send such notification to all players except active just by using notifyPlayer and it seems to work. The problem however is that table spectators would miss such notification and their user interface (and game log) wouldn&#039;t be updated. Since there is no way to send notification just to spectators, ignoring the notification (or &amp;quot;filtering&amp;quot;) is the only reasonable solution.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;setIgnoreNotificationCheck(notif_type: string, predicate: ((notif: Notif)=&amp;gt;boolean))&#039;&#039;&#039;&lt;br /&gt;
This method will set a check whether any of notifications of specific type should be ignored.&lt;br /&gt;
&lt;br /&gt;
The parameters are:&lt;br /&gt;
* notif_type: type of the notification &lt;br /&gt;
* predicate (notif =&amp;gt; boolean): a function that will receive notif object and will return true if this specific notification should be ignored&lt;br /&gt;
&lt;br /&gt;
Before dispatching any notification of this type, the framework will call predicate to check whether notification should be ignored, if it return true - the notification will be dispatched, i.e. logged or handled.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    this.notifqueue.setIgnoreNotificationCheck( &#039;dealCard&#039;, (notif) =&amp;gt; (notif.args.player_id == this.player_id) );&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
IMPORTANT: Remember that this notification is ignored on the client side, but was still received by the client. Therefore it shouldn&#039;t contain any private information as cheaters can get it. In other words this is not a way to hide information.&lt;br /&gt;
&lt;br /&gt;
IMPORTANT: When a game is reloaded with F5 or when opening a turn based game, old notifications are replayed as history notification. They are used just to update the game log and are stripped of all arguments except player_id, i18n and any argument present in message. If you use and other argument in your predicate you should &#039;&#039;&#039;preserve&#039;&#039;&#039; it as explained [[Main_game_logic:_yourgamename.game.php#Notify_players|here]].&lt;br /&gt;
&lt;br /&gt;
=== Synchronous notifications ===&lt;br /&gt;
&lt;br /&gt;
When several notifications are received by your game interface, these notifications are processed immediately, one after the other, in the same exact order they have been generated in your PHP game logic.&lt;br /&gt;
&lt;br /&gt;
However, sometimes, you need to give some time to the players to figure out what happened on the game before jumping to the next notification. Indeed, in many games, there are a lot of automatic actions, and the computer is going to resolve all these actions very fast if you don&#039;t tell it not to do so.&lt;br /&gt;
&lt;br /&gt;
As an example, for Reversi, when someone is playing a disc, we want to wait 500 milliseconds before doing anything else in order the opponent player can figure out what move has been played.&lt;br /&gt;
&lt;br /&gt;
Here&#039;s how we do this, right after our subscription:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    dojo.subscribe( &#039;playDisc&#039;, this, &amp;quot;notif_playDisc&amp;quot; );&lt;br /&gt;
    this.notifqueue.setSynchronous( &#039;playDisc&#039;, 500 );   // Wait 500 milliseconds after executing the playDisc handler&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
-----&lt;br /&gt;
&lt;br /&gt;
It is also possible to control the delay timing dynamically (e.g., using notification args). As an example, maybe your notification &#039;cardPlayed&#039; should pause for a different amount of time depending on the number or type of cards played.&lt;br /&gt;
&lt;br /&gt;
For this case, use &#039;&#039;&#039;setSynchronous&#039;&#039;&#039; without specifying the duration and use &#039;&#039;&#039;setSynchronousDuration&#039;&#039;&#039; within the notification callback.&lt;br /&gt;
&lt;br /&gt;
* NOTE: If you forget to invoke &#039;&#039;&#039;setSynchronousDuration&#039;&#039;&#039;, the game will remain paused forever!&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
setupNotifications: function () {&lt;br /&gt;
    dojo.subscribe( &#039;cardPlayed&#039;, this, &#039;notif_cardPlayed&#039; );&lt;br /&gt;
    this.notifqueue.setSynchronous( &#039;cardPlayed&#039; ); // wait time is dynamic&lt;br /&gt;
    ...&lt;br /&gt;
},&lt;br /&gt;
&lt;br /&gt;
notif_cardPlayed: function (notif) {&lt;br /&gt;
    // MUST call setSynchronousDuration&lt;br /&gt;
&lt;br /&gt;
    // Example 1: From notification args (PHP)&lt;br /&gt;
    this.notifqueue.setSynchronousDuration(notif.args.duration);&lt;br /&gt;
    ...&lt;br /&gt;
&lt;br /&gt;
    // Or, example 2: Match the duration to a Dojo animation&lt;br /&gt;
    var anim = dojo.fx.combine([&lt;br /&gt;
        ...&lt;br /&gt;
    ]);&lt;br /&gt;
    anim.play();&lt;br /&gt;
    this.notifqueue.setSynchronousDuration(anim.duration);&lt;br /&gt;
},&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You can also manually call this.notifqueue.setSynchronousDuration(0) once client operations are finished, but be careful that even fast replay still has a path to call it.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;WARNING: combining synchronous and ignored notifications&#039;&#039;&#039;&lt;br /&gt;
You must be careful when combining dynamic synchronous durations (as described above) with ignored notifications. If you have a conditionally ignored notification like this (see below section):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;this.notifqueue.setIgnoreNotificationCheck( &#039;myNotif&#039;, (notif) =&amp;gt; (notif.args.player_id == this.player_id) /* or any other condition */ )&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
then you CANNOT do&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;this.notifqueue.setSynchronous(&#039;myNotif&#039;);&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
as, when the ignored check passes, the notification handler, in which `this.notifqueue.setSychronousDuration` is called, is never called and so the duration is never set and interface locking results.&lt;br /&gt;
&lt;br /&gt;
The workaround is to set a &amp;quot;dummy&amp;quot; time:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;this.notifqueue.setSynchronous(&#039;myNotif&#039;, 5000);&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
whose value is irrelevant but must be large enough to cover the time before the notification handler is called. The large value never actually comes into play because the notification is either ignored, or the synchronous duration is reset to a sensible value inside the handler.&lt;br /&gt;
&lt;br /&gt;
=== Pre-defined notification types ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;tableWindow&#039;&#039;&#039; - This defines notification to display [[Game_interface_logic:_yourgamename.js#Scoring_dialogs|Scoring Dialogs]], see below.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;message&#039;&#039;&#039; - This defines notification that shows on players log and have no other effect (technically any unhandled notification will do the same but its recommended to use this keyword for consistency)&lt;br /&gt;
&lt;br /&gt;
   // You can call this on php side without doing anything on client side&lt;br /&gt;
    self::notifyAllPlayers( &#039;message&#039;, clienttranslate(&#039;hello&#039;), [] );&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;simplePause&#039;&#039;&#039; - This notification will just delay other notifications, maybe useful if you know you need some extra time for animation or something. Requires a time parameter.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    self::notifyAllPlayers( &#039;simplePause&#039;, &#039;&#039;, [ &#039;time&#039; =&amp;gt; 500] ); // time is in milliseconds&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note: the following types are RESERVED by framework, do not use:&lt;br /&gt;
&lt;br /&gt;
gameStateChange gameStateChangePrivateArg gameStateMultipleActiveUpdate newActivePlayer playerstatus yourturnack clockalert tableInfosChanged playerEliminated tableDecision  archivewaitingdelay end_archivewaitingdelay replaywaitingdelay end_replaywaitingdelay replayinitialwaitingdelay end_replayinitialwaitingdelay aiPlayerWaitingDelay replay_has_ended updateSpectatorList  wouldlikethink updateReflexionTime undoRestorePoint resetInterfaceWithAllDatas zombieModeFail zombieModeFailWarning aiError skipTurnOfPlayer zombieBack allPlayersAreZombie gameResultNeutralized playerConcedeGame showTutorial showCursor showCursorClick skipTurnOfPlayerWarning  banFromTable resultsAvailable switchToTurnbased newPrivateState infomsg&lt;br /&gt;
&lt;br /&gt;
== Tooltips ==&lt;br /&gt;
&lt;br /&gt;
=== Adding static tooltips ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.addTooltip(nodeId: string, helpStringTranslated: string, actionStringTranslated: string, delay?: number): void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Add a simple text tooltip to the DOM node.&lt;br /&gt;
&lt;br /&gt;
Specify &#039;helpStringTranslated&#039; to display some information about &amp;quot;what is this game element?&amp;quot;.&lt;br /&gt;
Specify &#039;actionStringTranslated&#039; to display some information about &amp;quot;what happens when I click on this element?&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
You must specify both of the strings. You can only use one and specify an empty string (&#039;&#039;) for the other one.&lt;br /&gt;
&lt;br /&gt;
When you pass text directly function _() must be used for the text to be marked for translation! Except for empty string.&lt;br /&gt;
&lt;br /&gt;
Parameter &amp;quot;delay&amp;quot; is optional. It is primarily used to specify a zero delay for some game element when the tooltip gives really important information for the game - but remember: no essential information must be placed in tooltips as they won&#039;t be displayed in some browsers (see [[BGA_Studio_Guidelines|Guidelines]]).&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
   this.addTooltip( &#039;cardcount&#039;, _(&#039;Number of cards in hand&#039;), &#039;&#039; );&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note: this generates static tooltip and attaches to existing dom element, if you need to generate tooltip more dynamically you have to call that method every time information about object is updated or use completely different tehnique, see dynamic tooltips below.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.addTooltipHtml(nodeId: string, html: string, delay?: number): void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Add an HTML tooltip to the DOM node (for more elaborate content such as presenting a bigger version of a card).&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.addTooltipToClass(cssClass: string, helpStringTranslated: string, actionStringTranslated: string, delay?: number ): void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Add a simple text tooltip to all the DOM nodes set with this cssClass. See more details above for this.addTooltip.&lt;br /&gt;
     this.addTooltipToClass( &#039;meeple&#039;, _(&#039;This is A Meeple&#039;), _(&#039;Click to tickle&#039;) );&lt;br /&gt;
&lt;br /&gt;
IMPORTANT: all concerned nodes must exist and have IDs to get tooltips.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.addTooltipHtmlToClass(cssClass: string, html: string, delay?: number): void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Add an HTML tooltip to to all the DOM nodes set with this cssClass (for more elaborate content such as presenting a bigger version of a card).&lt;br /&gt;
&lt;br /&gt;
IMPORTANT: all concerned nodes must exist and have IDs to get tooltips.&lt;br /&gt;
&lt;br /&gt;
=== Removing static tooltips ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.removeTooltip(nodeId: string): void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Remove a tooltip from the DOM node with given id.&lt;br /&gt;
&lt;br /&gt;
=== Advanced tooltips ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;force tooltip to open&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
If you want to force tooltip to open in reaction to some other action, i.e. click you can do this&lt;br /&gt;
&lt;br /&gt;
   this.tooltips[id].open(id)&lt;br /&gt;
&lt;br /&gt;
where id is the id of the tooltip node where tooltip was installed.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;dynamic tooltips&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
See [[BGA_Studio_Cookbook#Dynamic_tooltips]]&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;tooltips on mobile&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Tooltips is very unreliable on mobile, it is recommended to implement some other method to obtaining same information,&lt;br /&gt;
such as simple click handler in dedicated &amp;quot;Help&amp;quot; mode or provide dedicated clickable areas such as corner of card.&lt;br /&gt;
&lt;br /&gt;
== Warning messages ==&lt;br /&gt;
&lt;br /&gt;
Sometimes, there is something important that is happening in the game and you have to make sure all players get the message. Most of the time, the evolution of the game situation or the game log is enough, but sometimes you need something more visible.&lt;br /&gt;
&lt;br /&gt;
Ex: someone fulfills one of the end of the game conditions, so this is the last turn.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.showMessage(msg: string, type: string): void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
showMessage shows a message in a big rectangular area on the top of the screen of the current player, and it dissapears after few seconds (also it will be in the log in some cases).&lt;br /&gt;
&lt;br /&gt;
* &amp;quot;msg&amp;quot; is the string to display. It should be translated.&lt;br /&gt;
* &amp;quot;type&amp;quot; can be set to &amp;quot;info&amp;quot;, &amp;quot;error&amp;quot;, &amp;quot;only_to_log&amp;quot; or custom string. If set to &amp;quot;info&amp;quot;, the message will be an informative message on a white background. If set to &amp;quot;error&amp;quot;, the message will be an error message on a red background and it will be added to log. If set to &amp;quot;only_to_log&amp;quot;, the message will be added to the game log but will not popup at the top of the screen.&lt;br /&gt;
If set to custom string, it will be transparent, to use custom type define &amp;quot;head_xxx&amp;quot; in css, where xxx is the type. For example if you want yellow warning, use &amp;quot;warning&amp;quot; as type and add this to css:&lt;br /&gt;
 .head_warning {&lt;br /&gt;
    background-color: #e6c66e;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
Important: the normal way to inform players about the progression of the game is the game log. The &amp;quot;showMessage&amp;quot; is intrusive and should not be used often.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    notif_messageinfo: function(notif) {&lt;br /&gt;
	if (!g_archive_mode) {&lt;br /&gt;
        	var message = this.format_string_recursive(notif.log, notif.args);&lt;br /&gt;
		this.showMessage(_(&#039;Announcement:&#039;) + &amp;quot; &amp;quot; + message, &#039;info&#039;);		&lt;br /&gt;
         }&lt;br /&gt;
    },&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Show message could be used on the client side to prevent user wrong moves before it is send to server.&lt;br /&gt;
Example from &#039;battleship&#039;:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
onGrid: function(event) {&lt;br /&gt;
     if (checkIfPlayerTriesToFireOnThemselves(event)) {&lt;br /&gt;
        this.showMessage(_(&#039;This is your own board silly!&#039;), &#039;error&#039;);&lt;br /&gt;
        return;&lt;br /&gt;
     }&lt;br /&gt;
     ...&lt;br /&gt;
},&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.showMoveUnauthorized(): void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Shows predefined user error that move is unauthorized now&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
onPet: function(event) {&lt;br /&gt;
     if (checkPet(event)==false) {&lt;br /&gt;
        this.showMoveUnauthorized();&lt;br /&gt;
        return;&lt;br /&gt;
     }&lt;br /&gt;
     ...&lt;br /&gt;
},&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Dialogs ==&lt;br /&gt;
&lt;br /&gt;
=== Confirmation dialog ===&lt;br /&gt;
&lt;br /&gt;
When an important action with a lot of consequences is triggered by the player, you may want to propose a confirmation dialog.&lt;br /&gt;
&lt;br /&gt;
CAREFUL: the general guideline of BGA is to AVOID the use of confirmation dialogs. Confirmation dialogs slow down the game and bother players. The players know that they have to pay attention to each move when they are playing online.&lt;br /&gt;
&lt;br /&gt;
The situations where you should use a confirmation dialog are the following:&lt;br /&gt;
* It must not happen very often during a game.&lt;br /&gt;
* It must be linked to an action that can really &amp;quot;kill a game&amp;quot; if the player does not pay attention.&lt;br /&gt;
* It must be something that can be done by mistake (ex: a link on the action status bar).&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.confirmationDialog(message: string, yesHandler: (param: any) =&amp;gt; void, noHandler?: (param: any) =&amp;gt; void, param?: any): void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
* message - message will be shown to user, use _() to translate&lt;br /&gt;
* yesHandler - non-optional handler to be called on yes&lt;br /&gt;
* noHandler - optional handler to called on no&lt;br /&gt;
* param - if specified, it will be passed to both handlers&lt;br /&gt;
NOTE: this is async function, it does not return anything and you should not do anything after, you must do everything in handlers&lt;br /&gt;
&lt;br /&gt;
How to display a confirmation dialog:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    this.confirmationDialog(_(&amp;quot;Are you sure you want to bake a pie?&amp;quot;), () =&amp;gt; {&lt;br /&gt;
      this.bakeThePie();&lt;br /&gt;
    });&lt;br /&gt;
    return; // nothing should be called or done after calling this, all action must be done in the handler&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
With param and both handlers&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    this.confirmationDialog(_(&amp;quot;Are you sure you want to bake a pie?&amp;quot;), &lt;br /&gt;
           (ingredient) =&amp;gt; this.bakeThePie(ingredient), &lt;br /&gt;
           (ingredient) =&amp;gt; console.log(`cancelled baking of ${ingredient}`), &lt;br /&gt;
           &#039;apple&#039;);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Multiple choice dialog ===&lt;br /&gt;
&lt;br /&gt;
You can use this dialog to give user a choice with small amount of options&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.multipleChoiceDialog(message: string, choices: string[], callback: (choice: number) =&amp;gt; void): void&#039;&#039;&#039;&lt;br /&gt;
* message - message will be shown to user, use _() to translate&lt;br /&gt;
* choices - array of choices&lt;br /&gt;
* callback - non-optional handler to be called on choice made, the choice parameter is the INDEX of the choice from the array of choices&lt;br /&gt;
&lt;br /&gt;
NOTE: this is async function, it does not return anything and you should not do anything after, you must do everything in handlers&lt;br /&gt;
NOTE: there is no cancel handler, so make sure you gave user a choice to get out of it&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    const keys = [&amp;quot;0&amp;quot;, &amp;quot;1&amp;quot;, &amp;quot;5&amp;quot;, &amp;quot;10&amp;quot;];&lt;br /&gt;
    this.multipleChoiceDialog(_(&amp;quot;How many bugs to fix?&amp;quot;), keys, (choice) =&amp;gt; {&lt;br /&gt;
      if (choice==0) return; // cancel operation, do not call server action&lt;br /&gt;
      var bugchoice = keys[choice]; // choice will be 0,1,2,3 here&lt;br /&gt;
      this.bgaPerformAction(&amp;quot;fixBugs&amp;quot;, { number: bugchoice });&lt;br /&gt;
    });&lt;br /&gt;
    return; // must return here&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Generic Dialogs ===&lt;br /&gt;
&lt;br /&gt;
As a general rule, you shouldn&#039;t use dialogs windows.&lt;br /&gt;
&lt;br /&gt;
BGA guidelines specify that all game elements should be displayed on the main screen. Players can eventually scroll down to see game elements they don&#039;t need to see anytime, and you may eventually create anchors to move between game area section. Of course dialogs windows are very practical, but the thing is: all players know how to scroll down, and not all players know how to show up your dialog window. In addition, when the dialog shows up, players can&#039;t access the other game components.&lt;br /&gt;
&lt;br /&gt;
Sometimes although, you need to display a dialog window. Here is how you do this:&lt;br /&gt;
&lt;br /&gt;
  // Create the new dialog over the play zone. You should store the handler in a member variable to access it later&lt;br /&gt;
  this.myDlg = new ebg.popindialog();&lt;br /&gt;
  this.myDlg.create( &#039;myDialogUniqueId&#039; );&lt;br /&gt;
  this.myDlg.setTitle( _(&amp;quot;my dialog title to translate&amp;quot;) );&lt;br /&gt;
  this.myDlg.setMaxWidth( 500 ); // Optional&lt;br /&gt;
  &lt;br /&gt;
  // Create the HTML of my dialog. &lt;br /&gt;
  // The best practice here is to use [[Game_layout:_view_and_template:_yourgamename.view.php_and_yourgamename_yourgamename.tpl#Javascript_templates|Javascript templates]]&lt;br /&gt;
  var html = this.format_block( &#039;jstpl_myDialogTemplate&#039;, { &lt;br /&gt;
                arg1: myArg1,&lt;br /&gt;
                arg2: myArg2,&lt;br /&gt;
                ...&lt;br /&gt;
            } );  &lt;br /&gt;
  &lt;br /&gt;
  // Show the dialog&lt;br /&gt;
  this.myDlg.setContent( html ); // Must be set before calling show() so that the size of the content is defined before positioning the dialog&lt;br /&gt;
  this.myDlg.show();&lt;br /&gt;
  &lt;br /&gt;
  // Now that the dialog has been displayed, you can connect your method to some dialog elements&lt;br /&gt;
  // Example, if you have an &amp;quot;OK&amp;quot; button in the HTML of your dialog:&lt;br /&gt;
  dojo.connect($(&#039;my_ok_button&#039;), &#039;onclick&#039;, this, (event) =&amp;gt; {&lt;br /&gt;
                event.preventDefault();&lt;br /&gt;
                this.myDlg.destroy();&lt;br /&gt;
            });&lt;br /&gt;
&lt;br /&gt;
If necessary, you can remove the default top right corner &#039;close&#039; icon, or replace the function called when it is clicked:&lt;br /&gt;
  // Removes the default close icon&lt;br /&gt;
  this.myDlg.hideCloseIcon();&lt;br /&gt;
&lt;br /&gt;
  // Replace the function call when it&#039;s clicked&lt;br /&gt;
  this.myDlg.replaceCloseCallback((event) =&amp;gt; { ... });&lt;br /&gt;
&lt;br /&gt;
=== Scoring dialogs ===&lt;br /&gt;
&lt;br /&gt;
Sometimes at the end of a round you want to display a big table that details the points wins in each section of the game.&lt;br /&gt;
&lt;br /&gt;
Example: in Hearts game, we display at the end of each round the number of &amp;quot;heart&amp;quot; cards collected by each player, the player who collected the Queen of Spades, and the total number of points loose by each player.&lt;br /&gt;
&lt;br /&gt;
Scoring dialogs are managed entirely on &#039;&#039;&#039;PHP side&#039;&#039;&#039;, but they are described here as their effects are visible only on client side.&lt;br /&gt;
&lt;br /&gt;
Displaying a scoring dialog is quite simple and is using a special notification type: &amp;quot;tableWindow&amp;quot;:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  // on PHP side:&lt;br /&gt;
  $this-&amp;gt;notifyAllPlayers( &amp;quot;tableWindow&amp;quot;, &#039;&#039;, array(&lt;br /&gt;
            &amp;quot;id&amp;quot; =&amp;gt; &#039;finalScoring&#039;,&lt;br /&gt;
            &amp;quot;title&amp;quot; =&amp;gt; clienttranslate(&amp;quot;Title of the scoring dialog&amp;quot;),&lt;br /&gt;
            &amp;quot;table&amp;quot; =&amp;gt; $table&lt;br /&gt;
        )); &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The &amp;quot;table&amp;quot; argument is a 2 dimensional PHP array that describes the table you want to display, line by line and column by column.&lt;br /&gt;
&lt;br /&gt;
Example: display an 3x3 array of strings&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
   $table = [&lt;br /&gt;
      [ &amp;quot;one&amp;quot;, &amp;quot;two&amp;quot;, &amp;quot;three&amp;quot; ],    // This is my first line&lt;br /&gt;
      [ &amp;quot;four&amp;quot;, &amp;quot;five&amp;quot;, &amp;quot;six&amp;quot; ],    // This is my second line&lt;br /&gt;
      [ &amp;quot;seven&amp;quot;, &amp;quot;height&amp;quot;, &amp;quot;nine&amp;quot; ]    // This is my third line&lt;br /&gt;
   ];&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
As you can see above, in each &amp;quot;cell&amp;quot; of your array you can display a simple string value. But you can also display a complex value with a template and associated arguments like this:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
   $table = [&lt;br /&gt;
      [ &amp;quot;one&amp;quot;, &amp;quot;two&amp;quot;, [ &amp;quot;str&amp;quot; =&amp;gt; clienttranslate(&amp;quot;a string with an ${argument}&amp;quot;), &amp;quot;args&amp;quot; =&amp;gt; [ &#039;argument&#039; =&amp;gt; &#039;argument_value&#039; ] ] ],&lt;br /&gt;
      [ &amp;quot;four&amp;quot;, &amp;quot;five&amp;quot;, &amp;quot;six&amp;quot; ], &lt;br /&gt;
      [ &amp;quot;seven&amp;quot;, &amp;quot;height&amp;quot;, &amp;quot;nine&amp;quot; ]&lt;br /&gt;
   ];&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This is especially useful when you want to display player names with colors. Example from &amp;quot;Hearts&amp;quot;:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        $firstRow = [ &#039;&#039; ];&lt;br /&gt;
        foreach( $players as $player_id =&amp;gt; $player )    {&lt;br /&gt;
            $cell = [ &#039;str&#039; =&amp;gt; &#039;${player_name}&#039;,&lt;br /&gt;
                      &#039;args&#039; =&amp;gt; [ &#039;player_name&#039; =&amp;gt; $player[&#039;player_name&#039;] ],&lt;br /&gt;
                      &#039;type&#039; =&amp;gt; &#039;header&#039;&lt;br /&gt;
                    ];&lt;br /&gt;
            $firstRow[] = $cell;&lt;br /&gt;
        }&lt;br /&gt;
        $table[] = $firstRow;&lt;br /&gt;
        ...&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You can also use three extra attributes in the parameter array for the notification:&lt;br /&gt;
* &#039;&#039;&#039;header&#039;&#039;&#039;: the content for this parameter displays before the table (also, the html will be parsed and player names will be colored according to the current game colors). &lt;br /&gt;
* &#039;&#039;&#039;footer&#039;&#039;&#039;: the content for this parameter displays after the table (no parsing for coloring the player names)&lt;br /&gt;
* &#039;&#039;&#039;closing&#039;&#039;&#039;: if this parameter is used, a button will be displayed with this label at the bottom of the popup and will allow players to close it (more easily than by clicking the top right &#039;cross&#039; icon).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
   $this-&amp;gt;notifyAllPlayers( &amp;quot;tableWindow&amp;quot;, &#039;&#039;, [&lt;br /&gt;
            &amp;quot;id&amp;quot; =&amp;gt; &#039;finalScoring&#039;,&lt;br /&gt;
            &amp;quot;title&amp;quot; =&amp;gt; clienttranslate(&amp;quot;Title of the scoring dialog&amp;quot;),&lt;br /&gt;
            &amp;quot;table&amp;quot; =&amp;gt; $table,&lt;br /&gt;
            &amp;quot;header&amp;quot; =&amp;gt; [&#039;str&#039; =&amp;gt; clienttranslate(&#039;Table header with parameter ${number}&#039;),&lt;br /&gt;
                                 &#039;args&#039; =&amp;gt; [ &#039;number&#039; =&amp;gt; 3 ],&lt;br /&gt;
                               ],&lt;br /&gt;
            &amp;quot;footer&amp;quot; =&amp;gt; &#039;&amp;lt;div class=&amp;quot;myfoot&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&#039;,&lt;br /&gt;
            &amp;quot;closing&amp;quot; =&amp;gt; clienttranslate( &amp;quot;Closing button label&amp;quot; )&lt;br /&gt;
        ] ); &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note: currently id is not used - so you cannot access resulting div by id on js side&lt;br /&gt;
Note: any traslatable stirng have to be wrapped by clienttranslate() on top level OR it has to be recursive template. &lt;br /&gt;
&lt;br /&gt;
DO NOT DO THIS: &lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
   &amp;quot;footer&amp;quot; =&amp;gt; &#039;&amp;lt;div&amp;gt;&#039;.clienttranslate( &amp;quot;The end&amp;quot; ).&#039;&amp;lt;/div&amp;gt;&#039;, // this will not work for translations!!!&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Scoring animated display ===&lt;br /&gt;
&lt;br /&gt;
Sometimes, you may want to display a score value over an element to make the scoring easier to follow for the players (Terra Mystica final scoring for example).&lt;br /&gt;
You can do it with:&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.displayScoring(anchor_id: string, color: string, score: number | string, duration?: number, offset_x?: number, offset_y?: number): void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;anchor_id&#039;&#039;&#039;: ID of the html element to place the animated score onto (without the &#039;#&#039;) &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;color&#039;&#039;&#039;: hexadecimal RGB representation of the color (should be the color of the scoring player), but without a leading &#039;#&#039;.  For instance, &#039;ff0000&#039; for red.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;score&#039;&#039;&#039;: numeric score to display, prefixed by a &#039;+&#039; or &#039;-&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;duration&#039;&#039;&#039;: animation duration in milliseconds (optional, default is 1000)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;offset_x&#039;&#039;&#039; and &#039;&#039;&#039;offset_y&#039;&#039;&#039;: if both offset_x and offset_y are defined and not null, apply the following offset (in pixels) to the scoring animation. &lt;br /&gt;
Note that the score is centered in the anchor, so the offsets might have to be negative if you calculate the position.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Note: if you want to display successively each score, you can use &#039;&#039;this.notifqueue.setSynchronous()&#039;&#039; function.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    setupNotifications: function()   {&lt;br /&gt;
           dojo.subscribe( &#039;displayScoring&#039;, this, &amp;quot;notif_displayScoring&amp;quot; );&lt;br /&gt;
           ...&lt;br /&gt;
    }&lt;br /&gt;
...&lt;br /&gt;
&lt;br /&gt;
    notif_displayScoring: function(notif) {&lt;br /&gt;
            const duration = notif.args.duration?notif.args.duration:1000;&lt;br /&gt;
            this.notifqueue.setSynchronous(&#039;displayScoring&#039;, duration );&lt;br /&gt;
	    this.displayScoring( notif.args.target, notif.args.color, notif.args.score, duration);&lt;br /&gt;
    },&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Speech bubble ===&lt;br /&gt;
&lt;br /&gt;
For better interactivity in some games (Love Letter for example), you may use comic book style speech bubbles to express the players voices.&lt;br /&gt;
This is done with showBubble:&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.showBubble(anchor_id: string, text: string, delay?: number, duration?: number, custom_class?: string): void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
* anchor_id - where to attach the bubble&lt;br /&gt;
* text - what to put in bubble, can be html&lt;br /&gt;
* delay - delay in milliseconds (optional, default 0)&lt;br /&gt;
* duration -  duration of animation in milliseconds (optional, default 3000)&lt;br /&gt;
* custom_class - extra class to add to bubble (optional), if you need to override the default bubble style&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
   this.showBubble(&#039;meeple_2&#039;, _(&#039;Hello&#039;), 0, 1000, &#039;pink_bubble&#039;);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  notif_speechBubble(notif) {&lt;br /&gt;
    var html = this.format_string_recursive(notif.args.text, notif.args.args);&lt;br /&gt;
    this.showBubble(notif.args.target, html, notif.args.delay ?? 0, notif.args.duration ?? 1000);&lt;br /&gt;
  },&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Warning&#039;&#039;&#039;: if your bubble could overlap other active elements of the interface (buttons in particular), as it stays in place even after disappearing, you should use a custom class to give it the style &amp;quot;pointer-events: none;&amp;quot; in order to intercept click events.&lt;br /&gt;
&lt;br /&gt;
Note: If you want this visually, but want to take complete control over this bubble and its animation (for example to make it permanent) you can just use div with &#039;discussion_bubble&#039; class on it, and content of div is what will be shown.&lt;br /&gt;
&lt;br /&gt;
== Translations ==&lt;br /&gt;
&lt;br /&gt;
See [[Translations]]&lt;br /&gt;
&lt;br /&gt;
== Players panels ==&lt;br /&gt;
&lt;br /&gt;
=== Update players score ===&lt;br /&gt;
&lt;br /&gt;
The column player_score from the player table is automatically loaded into this.scoreCtrl and therefore into the stars location on the player board. This occurs sometime after the game setup() function. However this score must be updated as the game progresses using notifications.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Note: this.scoreCtrl[player_id] is object of class [[Counter]], you can use other counter API.&lt;br /&gt;
&lt;br /&gt;
Increase a player score (with a positive or negative number):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  this.scoreCtrl[ player_id ].incValue( score_delta );&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Set a player score to a specific value:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  this.scoreCtrl[ player_id ].setValue( new_score );&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Set a player score to a specific value with animation:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  this.scoreCtrl[ player_id ].toValue( new_score );&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Typical usage would be (that will process &#039;score&#039; notification):&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        setupNotifications : function() {&lt;br /&gt;
              ...&lt;br /&gt;
             dojo.subscribe(&#039;score&#039;, this, &amp;quot;notif_score&amp;quot;);&lt;br /&gt;
        },&lt;br /&gt;
        notif_score: function(notif) {&lt;br /&gt;
            this.scoreCtrl[notif.args.player_id].setValue(notif.args.player_score);&lt;br /&gt;
        },&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Adding stuff to player&#039;s panel ===&lt;br /&gt;
&lt;br /&gt;
At first, create a new &amp;quot;JS template&amp;quot; string in your template (tpl) file:&lt;br /&gt;
&lt;br /&gt;
(from Gomoku example)&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
var jstpl_player_board = &#039;\&amp;lt;div class=&amp;quot;cp_board&amp;quot;&amp;gt;\&lt;br /&gt;
    &amp;lt;div id=&amp;quot;stoneicon_p${id}&amp;quot; class=&amp;quot;gmk_stoneicon gmk_stoneicon_${color}&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&amp;lt;span id=&amp;quot;stonecount_p${id}&amp;quot;&amp;gt;0&amp;lt;/span&amp;gt;\&lt;br /&gt;
&amp;lt;/div&amp;gt;&#039;;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Then, you add this piece of code in your JS file to add this template to each player panel:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
            // Setting up player boards&lt;br /&gt;
            for( var player_id in gamedatas.players )&lt;br /&gt;
            {&lt;br /&gt;
                var player = gamedatas.players[player_id];&lt;br /&gt;
                         &lt;br /&gt;
                // Setting up players boards if needed&lt;br /&gt;
                var player_board_div = $(&#039;player_board_&#039;+player_id);&lt;br /&gt;
                dojo.place( this.format_block(&#039;jstpl_player_board&#039;, player ), player_board_div );&lt;br /&gt;
            }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
(Note: the code above is of course from your &amp;quot;setup&amp;quot; function in your Javascript).&lt;br /&gt;
&lt;br /&gt;
Very often, you have to distinguish current player and others players. In this case, you just have to create another JS template (ex: jstpl_otherplayer_board) and use it when &amp;quot;player_id&amp;quot; is different than &amp;quot;this.player_id&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Fixing Player Panel heights ===&lt;br /&gt;
&lt;br /&gt;
You may find that the player panels don&#039;t automatically resize when adding something to (or removing something from) a player panel while the display is in portrait mode (i.e. the player summary panels are at the top of the screen rather than down the right side).&lt;br /&gt;
&lt;br /&gt;
When this happens, call &amp;lt;pre&amp;gt;this.adaptPlayersPanels();&amp;lt;/pre&amp;gt; This recalculates the layout and also adjusts the position of the actionbar for you.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Player&#039;s panel disabling/enabling ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.disablePlayerPanel(player_id: number): void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Disable given player panel (the panel background become gray).&lt;br /&gt;
&lt;br /&gt;
Usually, this is used to signal that this played passes, or will be inactive during a while.&lt;br /&gt;
&lt;br /&gt;
Note that the only effect of this is visual. There are no consequences on the behaviour of the panel itself.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.enablePlayerPanel(player_id:number): void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Enable a player panel that has been disabled before.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.enableAllPlayerPanels(): void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Enable all player panels that has been disabled before.&lt;br /&gt;
&lt;br /&gt;
=== Player order ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.updatePlayerOrdering(): void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
This function makes sure that player order in player&#039;s panel matches this.gamedatas.playerorder and its normally called by framework.&lt;br /&gt;
You can call it yoursel if you change this.gamedatas.playerorder from notification.&lt;br /&gt;
Also you can override this function to change defaults  OR insert a non-player panel [[BGA_Studio_Cookbook#Inserting_non-player_panel]].&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Counters ===&lt;br /&gt;
Note: there is bga component called  &amp;quot;ebg/counter&amp;quot; this API is not using it, these methods&lt;br /&gt;
below declared right in core game. If you need animation for counters use ebg/counter&lt;br /&gt;
&lt;br /&gt;
To use this API just create a counter dom element like this (class does not really matter)&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 &amp;lt;div class=&amp;quot;counter&amp;quot; id=&amp;quot;bread&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
 &amp;lt;div class=&amp;quot;counter&amp;quot; id=&amp;quot;coin&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
The &amp;quot;bread&amp;quot; will the counter name.&lt;br /&gt;
&lt;br /&gt;
The php code should send all &amp;quot;counters&amp;quot; data from getAllDatas() method like this&lt;br /&gt;
&lt;br /&gt;
game.php&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  protected function getAllDatas() {&lt;br /&gt;
    // (the key must match counter_name)&lt;br /&gt;
    $result[&#039;counters&#039;]=[&lt;br /&gt;
        &#039;bread&#039; =&amp;gt; [ &lt;br /&gt;
         &#039;counter_name&#039; =&amp;gt; &#039;bread&#039;, &lt;br /&gt;
         &#039;counter_value&#039; =&amp;gt; 3&lt;br /&gt;
         ], &lt;br /&gt;
        &#039;coin&#039; =&amp;gt; [&lt;br /&gt;
          &#039;counter_name&#039; =&amp;gt; &#039;coin&#039;, &lt;br /&gt;
          &#039;counter_value&#039; =&amp;gt; 5&lt;br /&gt;
        ]&lt;br /&gt;
   ];&lt;br /&gt;
   return $result;&lt;br /&gt;
  }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;setCounter(counter_name: stirng, new_value: string | number): void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
updates the global this.gamedatas.counters and value of node $(counter_name)&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  notif_counter: function(notif) { &lt;br /&gt;
    this.setCounter(notif.args.counter_name, notif.args.counter_value);&lt;br /&gt;
  },&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;incCounter(counter_name: string, delta: number): void&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  notif_counter : function(notif) {&lt;br /&gt;
    this.incCounter(notif.args.counter_name, notif.args.inc);&lt;br /&gt;
  },&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;updateCounters(counters: object): void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Useful for updating game counters in the player panel (such as resources). &lt;br /&gt;
&#039;counters&#039; arg is map of counters (the key must match counter_name)&lt;br /&gt;
  {&lt;br /&gt;
    &#039;bread&#039;: { &lt;br /&gt;
         &#039;counter_name&#039; : &#039;bread&#039;, &lt;br /&gt;
         &#039;counter_value&#039; =&amp;gt; 3&lt;br /&gt;
    }, &lt;br /&gt;
    &#039;coin&#039;: { &lt;br /&gt;
         &#039;counter_name&#039; : &#039;coin&#039;, &lt;br /&gt;
         &#039;counter_value&#039; =&amp;gt; 5&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
All counters MUST be referenced in this.gamedatas.counters (means they should be send from php) and will be updated.&lt;br /&gt;
DOM objects referenced by &#039;counter_name&#039; will have their innerHTML updated with &#039;counter_value&#039;.&lt;br /&gt;
&lt;br /&gt;
Usually you call this from notification&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
                        notif_counter : function(notif) {&lt;br /&gt;
                            this.updateCounters(notif.args.counters);&lt;br /&gt;
                        },&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== BGA GUI components ==&lt;br /&gt;
&lt;br /&gt;
BGA framework provides some useful ready-to-use components for the game interface:&lt;br /&gt;
&lt;br /&gt;
[[Studio#BGA_Studio_game_components_reference]]&lt;br /&gt;
&lt;br /&gt;
Note that each time you are using an additional component, you must declare it at the top of your Javascript file in the list of modules used.&lt;br /&gt;
&lt;br /&gt;
Example if you are using &amp;quot;ebg.stock&amp;quot;:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
define([&lt;br /&gt;
    &amp;quot;dojo&amp;quot;,&amp;quot;dojo/_base/declare&amp;quot;,&lt;br /&gt;
    &amp;quot;ebg/core/gamegui&amp;quot;,&lt;br /&gt;
    &amp;quot;ebg/counter&amp;quot;,&lt;br /&gt;
    &amp;quot;ebg/stock&amp;quot;  /// &amp;lt;=== we are using ebg.stock module&lt;br /&gt;
],&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== BGA Buttons ==&lt;br /&gt;
&lt;br /&gt;
=== Basic Button ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.addActionButton(id: string, label: string, method: string | eventhandler, destination?: string, blinking?: boolean, color?: string): void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
You can use this method to add an action button in the main action status bar (or other places).&lt;br /&gt;
&lt;br /&gt;
Arguments:&lt;br /&gt;
* id: an element ID that should be unique in your HTML DOM document.&lt;br /&gt;
* label: the text of the button. Should be translatable (use _() function). Note: this can also be any html, such as &amp;quot;&amp;lt;div class=&#039;brick&#039;&amp;gt;&amp;lt;/div&amp;gt;&amp;quot;, see example below on how to make image action buttons.&lt;br /&gt;
* method: the name of your method that must be triggered when the player clicks on this button (can be name of the method on game class or handler).&lt;br /&gt;
* destination (optional): id of parent on where to add button, ONLY use in rare cases if location is not action bar. Use &#039;&#039;&#039;null&#039;&#039;&#039; as value if you need to specify other arguments.&lt;br /&gt;
* blinking (optional): if set to &#039;&#039;&#039;true&#039;&#039;&#039;, the button is going blink to catch player&#039;s attention. Please DO NOT abuse blinking button. If you need button to blink after some time passed add class &#039;blinking&#039; to the button later.&lt;br /&gt;
* color: could be &#039;&#039;&#039;blue&#039;&#039;&#039; (default), &#039;&#039;&#039;red&#039;&#039;&#039;,&#039;&#039;&#039;gray&#039;&#039;&#039; or &#039;&#039;&#039;none&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
You should only use this method in your &amp;quot;onUpdateActionButtons&amp;quot; method. Usually, you use it like this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        onUpdateActionButtons: function( stateName, args ) {                      &lt;br /&gt;
            if (this.isCurrentPlayerActive()) {            &lt;br /&gt;
                switch( stateName ) {&lt;br /&gt;
                case &#039;giveCards&#039;:&lt;br /&gt;
                    this.addActionButton( &#039;giveCards_button&#039;, _(&#039;Give selected cards&#039;), &#039;onGiveCards&#039; ); &lt;br /&gt;
                    this.addActionButton( &#039;pass_button&#039;, _(&#039;Pass&#039;), () =&amp;gt; this.bgaPerformAction(&#039;actPass&#039;) ); &lt;br /&gt;
                    break;&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        },   &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In the example above, we are adding a &amp;quot;Give selected cards&amp;quot; button in the case we are on game state &amp;quot;giveCards&amp;quot;. When player clicks on this button, it triggers our &amp;quot;onGiveCards&amp;quot; method.&lt;br /&gt;
&lt;br /&gt;
Example using blinking red button:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    this.addActionButton( &#039;button_confirm&#039;, _(&#039;Confirm?&#039;), &#039;onConfirm&#039;, null, true, &#039;red&#039;); &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If you want to call the handler with arguments, you can use arrow functions, like this:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
     this.addActionButton( &#039;commit_button&#039;, _(&#039;Confirm&#039;), () =&amp;gt; this.onConfirm(this.selectedCardId), null, false, &#039;red&#039;); &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Image Button ===&lt;br /&gt;
&lt;br /&gt;
You can use the same method, but add extra class to a button to disable the padding and style it, i.e.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
this.addActionButton( &#039;button_brick&#039;, &#039;&amp;lt;div class=&amp;quot;brick&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&#039;, ()=&amp;gt;{... on brick ...}, null, null, &#039;gray&#039;); &lt;br /&gt;
dojo.addClass(&#039;button_brick&#039;,&#039;bgaimagebutton&#039;);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
where&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
.bgaimagebutton {&lt;br /&gt;
  padding: 0px 12px;&lt;br /&gt;
  min-height: 28px;&lt;br /&gt;
  border: none;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If you use this a lot, you can define a helper function, i.e.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
 * This method can be used instead of addActionButton, to add a button which is an image (i.e. resource). Can be useful when player&lt;br /&gt;
 * need to make a choice of resources or tokens.&lt;br /&gt;
 */&lt;br /&gt;
addImageActionButton: function(id, div, handler, bcolor, tooltip) {&lt;br /&gt;
	if (typeof bcolor == &amp;quot;undefined&amp;quot;) {&lt;br /&gt;
		bcolor = &amp;quot;gray&amp;quot;;&lt;br /&gt;
	}&lt;br /&gt;
	// this will actually make a transparent button id color = gray&lt;br /&gt;
	this.addActionButton(id, div, handler, null, false, bcolor);&lt;br /&gt;
	// remove border, for images it better without&lt;br /&gt;
	dojo.style(id, &amp;quot;border&amp;quot;, &amp;quot;none&amp;quot;);&lt;br /&gt;
	// but add shadow style (box-shadow, see css)&lt;br /&gt;
	dojo.addClass(id, &amp;quot;shadow bgaimagebutton&amp;quot;);&lt;br /&gt;
	// you can also add additional styles, such as background&lt;br /&gt;
	if (tooltip) {&lt;br /&gt;
		dojo.attr(id, &amp;quot;title&amp;quot;, tooltip);&lt;br /&gt;
	}&lt;br /&gt;
	return $(id);&lt;br /&gt;
},&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Disabling Button ===&lt;br /&gt;
&lt;br /&gt;
You can disable the &#039;&#039;&#039;bgabutton&#039;&#039;&#039; by adding the css class &#039;&#039;&#039;disabled&#039;&#039;&#039; in you js. The disabled button is still visible but is grey and not clickable.&lt;br /&gt;
For example in the &#039;&#039;&#039;onUpdateActionButtons&#039;&#039;&#039; : &lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
this.addActionButton(&#039;play_button_id&#039;, _(&#039;Play 1 to 3 cards&#039;), &#039;playFunctionButton&#039;); &lt;br /&gt;
if (condition) {&lt;br /&gt;
  dojo.addClass(&#039;play_button_id&#039;, &#039;disabled&#039;);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Custom Buttons ===&lt;br /&gt;
&lt;br /&gt;
You can create a custom button, but the BGA framework provides a standard button that requires only .css classes: &#039;&#039;&#039;bgabutton&#039;&#039;&#039; and &#039;&#039;&#039;bgabutton_${color}&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Examples:&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;a href=&amp;quot;#&amp;quot; id=&amp;quot;my_button_id&amp;quot; class=&amp;quot;bgabutton bgabutton_blue&amp;quot;&amp;gt;&amp;lt;span&amp;gt;My blue button&amp;lt;/span&amp;gt;&amp;lt;/a&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;a href=&amp;quot;#&amp;quot; id=&amp;quot;my_button_id&amp;quot; class=&amp;quot;bgabutton bgabutton_red bgabutton_big&amp;quot;&amp;gt;&amp;lt;span&amp;gt;My big red button&amp;lt;/span&amp;gt;&amp;lt;/a&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note&#039;&#039;&#039;: To see it in action, check out &#039;&#039;Coloretto&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
=== Button outside of action bar ===&lt;br /&gt;
&lt;br /&gt;
Use addActionButton() method with destination argument set&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
this.addActionButton( &#039;commit_button&#039;, _(&#039;Confirm&#039;), &#039;onConfirm&#039;, &#039;player_board&#039;, true, &#039;red&#039;); &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
in example above the button will be place on object with id &#039;player_board&#039;&lt;br /&gt;
&lt;br /&gt;
== Image loading ==&lt;br /&gt;
&lt;br /&gt;
See also [[Game_art:_img_directory]].&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Be careful&#039;&#039;&#039;: by default, ALL images of your img directory are loaded on a player&#039;s browser when he loads the game. For this reason, don&#039;t let in your img directory images that are not useful, otherwise it&#039;s going to slowdown the game load.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.dontPreloadImage(image_file_name: string)&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Using dontPreloadImage, you tell the interface to not preload a specific image in your img directory.&lt;br /&gt;
&lt;br /&gt;
Example of use:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
this.dontPreloadImage( &#039;cards.png&#039; );&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This is particularly useful if for example you have 2 different themes for a game. To accelerate the loading of the game, you can specify to not preload images corresponding to the other theme.&lt;br /&gt;
&lt;br /&gt;
Another example of use: in &amp;quot;Gosu&amp;quot; game with Kamakor extension, you play with 5 sets of cards among 10 available. Cards images are organized by sets, and we only preload the images corresponding to the 5 current sets with &#039;&#039;&#039;ensureSpecificGameImageLoading( image_file_names_array )&#039;&#039;&#039;.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
// By default, do not preload anything&lt;br /&gt;
this.dontPreloadImage( &#039;cards.png&#039; );&lt;br /&gt;
this.dontPreloadImage( &#039;clan1.png&#039; );&lt;br /&gt;
this.dontPreloadImage( &#039;clan2.png&#039; );&lt;br /&gt;
this.dontPreloadImage( &#039;clan3.png&#039; );&lt;br /&gt;
this.dontPreloadImage( &#039;clan4.png&#039; );&lt;br /&gt;
this.dontPreloadImage( &#039;clan5.png&#039; );&lt;br /&gt;
this.dontPreloadImage( &#039;clan6.png&#039; );&lt;br /&gt;
this.dontPreloadImage( &#039;clan7.png&#039; );&lt;br /&gt;
this.dontPreloadImage( &#039;clan8.png&#039; );&lt;br /&gt;
this.dontPreloadImage( &#039;clan9.png&#039; );&lt;br /&gt;
this.dontPreloadImage( &#039;clan10.png&#039; );&lt;br /&gt;
var to_preload = [];&lt;br /&gt;
for( i in this.gamedatas.clans )&lt;br /&gt;
{&lt;br /&gt;
	var clan_id = this.gamedatas.clans[i];&lt;br /&gt;
	to_preload.push( &#039;clan&#039;+clan_id+&#039;.png&#039; );&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
this.ensureSpecificGameImageLoading( to_preload );&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note:&#039;&#039;&#039; You don&#039;t need to specify to not preload game box images (game_box.png, game_box75.png...) since they are not preloaded by default.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.ensureSpecificGameImageLoading(list: string[])&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
This is oppostive of dontPreloadImage - its ensure specific images is loaded. Note: only makes sense if preload list is empty, otherwise everything is loaded anyway&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;load specific images&#039;&#039;&#039;&lt;br /&gt;
All images that will be preloaded stored in g_img_preload. If you want to override it directly - there is no API, but you can do this in GAME constructor&lt;br /&gt;
&lt;br /&gt;
          g_img_preload = [&#039;tokens.png&#039;, &#039;trains.png&#039;, &#039;loc_plan.png&#039;, &#039;eng.png&#039;, &#039;eng-back.png&#039;];&lt;br /&gt;
&lt;br /&gt;
You can also set it to empty array and call ensureSpecificGameImageLoading() on specific images&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Sounds ==&lt;br /&gt;
&lt;br /&gt;
Add a custom sound and make it load with your interface:&lt;br /&gt;
&lt;br /&gt;
Add this in your template (.tpl) file:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;audio id=&amp;quot;audiosrc_&amp;lt;gamename&amp;gt;_&amp;lt;yoursoundname&amp;gt;&amp;quot; src=&amp;quot;{GAMETHEMEURL}img/&amp;lt;gamename&amp;gt;_&amp;lt;yoursoundname&amp;gt;.mp3&amp;quot; preload=&amp;quot;none&amp;quot; autobuffer&amp;gt;&amp;lt;/audio&amp;gt;&lt;br /&gt;
&amp;lt;audio id=&amp;quot;audiosrc_o_&amp;lt;gamename&amp;gt;_&amp;lt;yoursoundname&amp;gt;&amp;quot; src=&amp;quot;{GAMETHEMEURL}img/&amp;lt;gamename&amp;gt;_&amp;lt;yoursoundname&amp;gt;.ogg&amp;quot; preload=&amp;quot;none&amp;quot; autobuffer&amp;gt;&amp;lt;/audio&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note: this is a requirement to provide both a mp3 and a ogg file with the names &amp;lt;code&amp;gt;&amp;lt;gamename&amp;gt;_&amp;lt;yoursoundname&amp;gt;[.ogg][.mp3]&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Play the sound (from your .js file):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
playSound(&#039;&amp;lt;gamename&amp;gt;_&amp;lt;yoursoundname&amp;gt;&#039;);   // do not add &#039;this.&#039; - its a global function&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Disable the standard &amp;quot;move&amp;quot; sound for this move (to replace it with your custom sound):&lt;br /&gt;
&lt;br /&gt;
Add this to your notification handler:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
this.disableNextMoveSound();&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note: it only disable the sound for the next move.&lt;br /&gt;
&lt;br /&gt;
== Title bar and states ==&lt;br /&gt;
&lt;br /&gt;
=== Client states ===&lt;br /&gt;
&lt;br /&gt;
Client states is a way to simulate the state transition but without actually going&lt;br /&gt;
to server. It is usefull when you need to ask user multiple questions before you&lt;br /&gt;
send things to server&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.setClientState(newState: string, args: object)&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
     this.setClientState(&amp;quot;client_playerPicksLocation&amp;quot;, {&lt;br /&gt;
                               descriptionmyturn : _(&amp;quot;${you} must select location&amp;quot;),&lt;br /&gt;
                           });&lt;br /&gt;
&lt;br /&gt;
For more information see [[BGA_Studio_Cookbook#Multi_Step_Interactions:_Select_Worker.2FPlace_Worker_-_Using_Client_States]]&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.restoreServerGameState()&#039;&#039;&#039;&lt;br /&gt;
If you are in client state it will restore the current server state (cheap undo)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.on_client_state&#039;&#039;&#039;&lt;br /&gt;
Boolean indicating that we are in client state&lt;br /&gt;
&lt;br /&gt;
=== Title bar ===&lt;br /&gt;
If you simply want to show something in title bar you can do it directly &lt;br /&gt;
     $(&#039;pagemaintitletext&#039;).innerHTML = text;&lt;br /&gt;
&lt;br /&gt;
This however will not work with parameters and will not draw You in color,&lt;br /&gt;
if you want to do proper args rendering use method below&lt;br /&gt;
&lt;br /&gt;
;&#039;&#039;&#039;this.removeActionButtons()&#039;&#039;&#039;&lt;br /&gt;
Removes all buttons from title bar&lt;br /&gt;
&lt;br /&gt;
;&#039;&#039;&#039;this.updatePageTitle()&#039;&#039;&#039;&lt;br /&gt;
:This function allows to update the current page title and turn description according to the game state arguments. If the current game state description this.gamedatas.gamestate.descriptionmyturn is modified before calling this function it allows to update the turn description without changing state. This will handle arguments substitutions properly.&lt;br /&gt;
&lt;br /&gt;
Note: this functional also will calls this.onUpdateActionButtons, if you want different buttons then state defaults, use method in example to replace them, if it becomes too clumsy use client states (see above)&lt;br /&gt;
&lt;br /&gt;
Example from Terra Mystica:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
onClickFavorTile: function( evt ) {&lt;br /&gt;
    ...&lt;br /&gt;
    if ( ... ) {&lt;br /&gt;
        this.gamedatas.gamestate.descriptionmyturn = _(&#039;Special action: &#039;) + _(&#039;Advance 1 space	on a Cult track&#039;);&lt;br /&gt;
        this.updatePageTitle();&lt;br /&gt;
        this.removeActionButtons();&lt;br /&gt;
        this.addActionButton( ... );&lt;br /&gt;
         ...&lt;br /&gt;
        return;&lt;br /&gt;
    }&lt;br /&gt;
    ...&lt;br /&gt;
&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== User preferences ==&lt;br /&gt;
&#039;&#039;&#039;this.getGameUserPreference(pref_id)&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Return the value of a user preference. It will return the value currently selected in the select combo box, in the top-right menu.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.setGameUserPreference(pref_id, value)&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Programmatically change a user preference. It will have the same effect as if the player changed the value in the select combo box, in the top-right menu.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.onGameUserPreferenceChanged&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
A callback you can define if you want to be notified when a user changes a user preference.&lt;br /&gt;
&lt;br /&gt;
Example:&amp;lt;pre&amp;gt;&lt;br /&gt;
onGameUserPreferenceChanged: function(pref_id, pref_value) {&lt;br /&gt;
  switch (pref_id) {&lt;br /&gt;
    case 201: &lt;br /&gt;
      document.getElementsByTagName(&#039;html&#039;)[0].classList.toggle(&#039;dark-background&#039;, pref_value == 2);&lt;br /&gt;
      break;&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Other useful stuff ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;dojo.hitch&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
With dojo.hitch, you can create a callback function that will run with your game object context whatever happen.&lt;br /&gt;
&lt;br /&gt;
Typical example: display a BGA confirmation dialog with a callback function created with dojo.hitch:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        this.confirmationDialog( _(&#039;Are you sure you want to make this?&#039;), dojo.hitch( this, function() {&lt;br /&gt;
            this.bgaPerformAction(&#039;makeThis&#039;);&lt;br /&gt;
        } ) );   &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In the example above, using dojo.hitch, we ensure that the &amp;quot;this&amp;quot; object will be set when the callback is called.&lt;br /&gt;
&lt;br /&gt;
NOTE: In modern JS there are lambdas that eliminate need for that, the example above will look like this&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        this.confirmationDialog( _(&#039;Are you sure you want to make this?&#039;), () =&amp;gt; this.bgaPerformAction( &#039;makeThis&#039;) );   &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
;&#039;&#039;&#039;onScreenWidthChange()&#039;&#039;&#039;&lt;br /&gt;
:This function can be overridden in your game to manage some resizing on the client side when the browser window is resized. This function is also triggered at load time, so it can be used to adapt to the :viewport size at the start of the game too.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
; this.bRealtime&lt;br /&gt;
: Return true if the game is in realtime. Note that having a distinct behavior in realtime and turn-based should be exceptional.&lt;br /&gt;
&lt;br /&gt;
; g_replayFrom&lt;br /&gt;
: Global contains replay number in live game, it is set to undefined (i.e. not set) when it is not a replay mode, so consequentially the good check is &#039;&#039;&#039;typeof g_replayFrom != &#039;undefined&#039;&#039;&#039;&#039; which returns true if the game is in replay mode &amp;lt;i&amp;gt;during the game&amp;lt;/i&amp;gt; (the game is ongoing but the user clicked &amp;quot;replay from this move&amp;quot; in the log)&lt;br /&gt;
&lt;br /&gt;
; g_archive_mode&lt;br /&gt;
: Returns true if the game is in archive mode &amp;lt;i&amp;gt;after the game&amp;lt;/i&amp;gt; (the game has ended)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
; this.instantaneousMode&lt;br /&gt;
: Returns true during replay/archive mode if animations should be skipped. Only needed if you are doing custom animations. (The BGA-provided animation functions like &amp;lt;i&amp;gt;this.slideToObject()&amp;lt;/i&amp;gt; automatically handle instantaneous mode.)&lt;br /&gt;
: Technically, when you click &amp;quot;replay from move #20&amp;quot;, the system replays the game from the very beginning with moves 0 - 19 happening in instantaneous mode and moves 20+ happening in normal mode.&lt;br /&gt;
&lt;br /&gt;
; g_tutorialwritten&lt;br /&gt;
: Returns an object like the below if the game is in tutorial mode, or undefined otherwise. Tutorial mode is a special case of archive mode where comments have been added to a previous game to teach new players the rules.&lt;br /&gt;
    {&lt;br /&gt;
        author: &amp;quot;91577332&amp;quot;,&lt;br /&gt;
        id: &amp;quot;576&amp;quot;,&lt;br /&gt;
        mode: &amp;quot;view&amp;quot;&lt;br /&gt;
        status: &amp;quot;alpha&amp;quot;&lt;br /&gt;
        version_override: null&lt;br /&gt;
        viewer_id: &amp;quot;84554161&amp;quot;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;getBgaEnvironment(): string&#039;&#039;&#039;&lt;br /&gt;
: Returns &amp;quot;studio&amp;quot; for studio and &amp;quot;prod&amp;quot; for production environment (i.e. where games current runs). Only useful for debbugging hooks.&lt;br /&gt;
Note: alpha server is also &amp;quot;prod&amp;quot;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Category:Studio]]&lt;/div&gt;</summary>
		<author><name>Sguzzer Gunayer</name></author>
	</entry>
	<entry>
		<id>https://en.doc.boardgamearena.com/index.php?title=BGA_Studio_Cookbook&amp;diff=22707</id>
		<title>BGA Studio Cookbook</title>
		<link rel="alternate" type="text/html" href="https://en.doc.boardgamearena.com/index.php?title=BGA_Studio_Cookbook&amp;diff=22707"/>
		<updated>2024-09-24T14:41:22Z</updated>

		<summary type="html">&lt;p&gt;Sguzzer Gunayer: /* Action Stack - Using Client States */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;br /&gt;
&lt;br /&gt;
This page is a cookbook of design and implementation recipes for BGA Studio framework.&lt;br /&gt;
For tooling and usage recipes see [[Tools and tips of BGA Studio]].&lt;br /&gt;
If you have your own recipes feel free to edit this page.&lt;br /&gt;
&lt;br /&gt;
__TOC__&lt;br /&gt;
&lt;br /&gt;
== Visual Effects, Layout and Animation ==&lt;br /&gt;
&lt;br /&gt;
=== DOM manipulatons ===&lt;br /&gt;
&lt;br /&gt;
==== Create pieces dynamically (using template) ====&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Ingredients:&#039;&#039;&#039; ggg_ggg.tpl, ggg.js&lt;br /&gt;
&lt;br /&gt;
Note: this method is recommended by BGA guildlines&lt;br /&gt;
&lt;br /&gt;
Declared js template with variables in .tpl file, like this&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;script type=&amp;quot;text/javascript&amp;quot;&amp;gt;&lt;br /&gt;
    // Javascript HTML templates&lt;br /&gt;
    var jstpl_ipiece = &#039;&amp;lt;div class=&amp;quot;${type} ${type}_${color} inlineblock&amp;quot; aria-label=&amp;quot;${name}&amp;quot; title=&amp;quot;${name}&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&#039;;&lt;br /&gt;
&amp;lt;/script&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Use it like this in .js file&lt;br /&gt;
  div = this.format_block(&#039;jstpl_ipiece&#039;, {&lt;br /&gt;
                                type : &#039;meeple&#039;,&lt;br /&gt;
                                color : &#039;ff0000&#039;,&lt;br /&gt;
                                name : &#039;Bob&#039;,&lt;br /&gt;
                            });&lt;br /&gt;
  &lt;br /&gt;
Then you do whatever you need to do with that div, this one specifically design to go to log entries, because it has embedded title (otherwise its a picture only) and no id.&lt;br /&gt;
&lt;br /&gt;
Note: you could have place this variable in js itself, but keeping it in .tpl allows you to have your js code be free of HTML. Normally it never happens but&lt;br /&gt;
it is good to strive for it.&lt;br /&gt;
Note: you can also use string concatenation, its less readable. You can also use dojo dom object creation api&#039;s but its brutally verbose and its more unreadable.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Create pieces dynamically (using string concatenation) ====&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Ingredients:&#039;&#039;&#039; ggg.js&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  div = &amp;quot;&amp;lt;div class=&#039;meeple_&amp;quot;+color+&amp;quot;&#039;&amp;gt;&amp;lt;/div&amp;gt;&amp;quot;;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
or modern way&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  div = `&amp;lt;div class=&#039;meeple_${color}&#039;&amp;gt;&amp;lt;/div&amp;gt;`;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Create all pieces statically ====&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Ingredients:&#039;&#039;&#039; ggg_ggg.tpl, ggg.css, ggg.view.php (optional) &lt;br /&gt;
&lt;br /&gt;
* Create ALL game pieces in html template (.tpl)&lt;br /&gt;
* ALL pieces should have unique id, and it should be meaningful, i.e. meeple_red_1&lt;br /&gt;
* Do not use inline styling&lt;br /&gt;
* Id of player&#039;s specific pieces should use some sort of &#039;color&#039; identification, since player id cannot be used in static layout, you can use english color name, hex 6 char value, or color &amp;quot;number&amp;quot; (1,2,3...)&lt;br /&gt;
* Pieces should have separated class for its color, type, etc, so it can be easily styled in groups. In example below you now can style all meeples, all red meeples or all red tokens, or all &amp;quot;first&amp;quot; meeples&lt;br /&gt;
&lt;br /&gt;
ggg.tpl:&lt;br /&gt;
&amp;lt;pre&amp;gt; &lt;br /&gt;
  &amp;lt;div id=&amp;quot;home_red&amp;quot; class=&amp;quot;home_red home&amp;quot;&amp;gt;&lt;br /&gt;
     &amp;lt;div id=&amp;quot;meeple_red_1&amp;quot; class=&amp;quot;meeple red n1&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
     &amp;lt;div id=&amp;quot;meeple_red_2&amp;quot; class=&amp;quot;meeple red n2&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
  &amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
ggg.css:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
.meeple {&lt;br /&gt;
	width: 32px;&lt;br /&gt;
	height: 39px;&lt;br /&gt;
	background-image: url(img/78_64_stand_meeples.png);&lt;br /&gt;
	background-size: 352px;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.meeple.red {&lt;br /&gt;
	background-position: 30% 0%;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* There should be straight forward mapping between server id and js id (or 1:1)&lt;br /&gt;
* You place objects in different zones of the layout, and setup css to take care of layout&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
.home .meeple{&lt;br /&gt;
   display: inline-block;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
* If you need to have a temporary object that look like original you can use dojo.clone (and change id to some temp id)&lt;br /&gt;
* If there is lots of repetition or zone grid you can use template generator, but inject style declaration in css instead of inline style for flexibility&lt;br /&gt;
&lt;br /&gt;
Note:&lt;br /&gt;
* If you use this model you cannot use premade js components such as Stock and Zone&lt;br /&gt;
* You have to use alternative methods of animation (slightly altered) since default method will leave object with inline style attributes which you don&#039;t need&lt;br /&gt;
&lt;br /&gt;
==== Use player color in template ====&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Ingredients:&#039;&#039;&#039; ggg_ggg.tpl, ggg.view.php&lt;br /&gt;
&lt;br /&gt;
.view.php:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    function build_page($viewArgs) {&lt;br /&gt;
        // Get players &amp;amp; players number&lt;br /&gt;
        $players = $this-&amp;gt;game-&amp;gt;loadPlayersBasicInfos();&lt;br /&gt;
        $players_nbr = count($players);&lt;br /&gt;
        /**&lt;br /&gt;
         * ********* Place your code below: ***********&lt;br /&gt;
         */&lt;br /&gt;
        &lt;br /&gt;
        // Set PCOLOR to the current player color hex&lt;br /&gt;
        global $g_user;&lt;br /&gt;
        $cplayer = $g_user-&amp;gt;get_id();&lt;br /&gt;
        if (array_key_exists($cplayer, $players)) { // may be not set if spectator&lt;br /&gt;
            $player_color = $players [$cplayer] [&#039;player_color&#039;];&lt;br /&gt;
        } else {&lt;br /&gt;
            $player_color = &#039;ffffff&#039;; // spectator&lt;br /&gt;
        }&lt;br /&gt;
        $this-&amp;gt;tpl [&#039;PCOLOR&#039;] = $player_color;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Status bar ===&lt;br /&gt;
&lt;br /&gt;
==== Changing state prompt ====&lt;br /&gt;
&lt;br /&gt;
State prompt is message displayed for player which usually comes from state description.&lt;br /&gt;
Sometimes you want to change it without changing state (one way is change state but locally, see client states above).&lt;br /&gt;
&lt;br /&gt;
Simple way just change the html&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        setMainTitle: function(text) {&lt;br /&gt;
            $(&#039;pagemaintitletext&#039;).innerHTML = text;&lt;br /&gt;
        },&lt;br /&gt;
         // usage&lt;br /&gt;
        onMeeple: function(event) {&lt;br /&gt;
              //... &lt;br /&gt;
              this.setMainTitle(_(&#039;You must select where meeple is going&#039;));&lt;br /&gt;
        },&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This however will not work with parameters and will not draw You in color, if you want this its more sophisticated:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        setDescriptionOnMyTurn : function(text) {&lt;br /&gt;
            this.gamedatas.gamestate.descriptionmyturn = text;&lt;br /&gt;
            var tpl = dojo.clone(this.gamedatas.gamestate.args);&lt;br /&gt;
            if (tpl === null) {&lt;br /&gt;
                tpl = {};&lt;br /&gt;
            }&lt;br /&gt;
            var title = &amp;quot;&amp;quot;;&lt;br /&gt;
            if (this.isCurrentPlayerActive() &amp;amp;&amp;amp; text !== null) {&lt;br /&gt;
                tpl.you = this.divYou(); &lt;br /&gt;
            }&lt;br /&gt;
            title = this.format_string_recursive(text, tpl);&lt;br /&gt;
&lt;br /&gt;
            if (!title) {&lt;br /&gt;
                this.setMainTitle(&amp;quot;&amp;amp;nbsp;&amp;quot;);&lt;br /&gt;
            } else {&lt;br /&gt;
                this.setMainTitle(title);&lt;br /&gt;
            }&lt;br /&gt;
        },&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note: this method uses &#039;&#039;&#039;setMainTitle&#039;&#039;&#039; defined above and &#039;&#039;&#039;divYou&#039;&#039;&#039; defined in another section of this wiki.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Animation ===&lt;br /&gt;
&lt;br /&gt;
==== Attach to new parent without destroying the object ====&lt;br /&gt;
&lt;br /&gt;
BGA function attachToNewParent for some reason destroys the original, if you want similar function that does not you can use this&lt;br /&gt;
ggg.js&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        /**&lt;br /&gt;
         * This method will attach mobile to a new_parent without destroying, unlike original attachToNewParent which destroys mobile and&lt;br /&gt;
         * all its connectors (onClick, etc)&lt;br /&gt;
         */&lt;br /&gt;
        attachToNewParentNoDestroy: function (mobile_in, new_parent_in, relation, place_position) {&lt;br /&gt;
&lt;br /&gt;
            const mobile = $(mobile_in);&lt;br /&gt;
            const new_parent = $(new_parent_in);&lt;br /&gt;
&lt;br /&gt;
            var src = dojo.position(mobile);&lt;br /&gt;
            if (place_position)&lt;br /&gt;
                mobile.style.position = place_position;&lt;br /&gt;
            dojo.place(mobile, new_parent, relation);&lt;br /&gt;
            mobile.offsetTop;//force re-flow&lt;br /&gt;
            var tgt = dojo.position(mobile);&lt;br /&gt;
            var box = dojo.marginBox(mobile);&lt;br /&gt;
            var cbox = dojo.contentBox(mobile);&lt;br /&gt;
            var left = box.l + src.x - tgt.x;&lt;br /&gt;
            var top = box.t + src.y - tgt.y;&lt;br /&gt;
&lt;br /&gt;
            mobile.style.position = &amp;quot;absolute&amp;quot;;&lt;br /&gt;
            mobile.style.left = left + &amp;quot;px&amp;quot;;&lt;br /&gt;
            mobile.style.top = top + &amp;quot;px&amp;quot;;&lt;br /&gt;
            box.l += box.w - cbox.w;&lt;br /&gt;
            box.t += box.h - cbox.h;&lt;br /&gt;
            mobile.offsetTop;//force re-flow&lt;br /&gt;
            return box;&lt;br /&gt;
        },&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Animation on oversurface ====&lt;br /&gt;
If you use non-absolute position for your game elements (i.e you use layouts) - you cannot really use BGA animation functions. After years of fidding with different options I use&lt;br /&gt;
techique which I call animation on oversurface that works when parents use different zoom, rotation, etc&lt;br /&gt;
&lt;br /&gt;
* You need another layer on top of everything - oversurface&lt;br /&gt;
* We create copy of the object on oversurface - to move&lt;br /&gt;
* We move the real object on final position - but make it invisible for now&lt;br /&gt;
* We move the phantom to final position applying required zoom and rotation (using css animation), then destroy it&lt;br /&gt;
* When animation is done we make original object visible in new position&lt;br /&gt;
&lt;br /&gt;
The code is bit complex it can be found here&lt;br /&gt;
&lt;br /&gt;
https://codepen.io/VictoriaLa/pen/gORvdJo&lt;br /&gt;
&lt;br /&gt;
Game using it: century, ultimaterailroads&lt;br /&gt;
&lt;br /&gt;
==== Scroll element into view ====&lt;br /&gt;
Ingredients: game.js&lt;br /&gt;
&lt;br /&gt;
This function will scroll given node (div) into view and respect replays and archive mode&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    scrollIntoViewAfter: function (node, delay) {&lt;br /&gt;
      if (this.instantaneousMode || this.inSetup) {&lt;br /&gt;
        return;&lt;br /&gt;
      }&lt;br /&gt;
      if (typeof g_replayFrom != &amp;quot;undefined&amp;quot;) {&lt;br /&gt;
        $(node).scrollIntoView();&lt;br /&gt;
        return;&lt;br /&gt;
      }&lt;br /&gt;
      if (!delay) delay = 0;&lt;br /&gt;
      setTimeout(() =&amp;gt; {&lt;br /&gt;
        $(node).scrollIntoView({ behavior: &amp;quot;smooth&amp;quot;, block: &amp;quot;center&amp;quot; });&lt;br /&gt;
      }, delay);&lt;br /&gt;
    },&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Logs ===&lt;br /&gt;
&lt;br /&gt;
==== Inject icon images in the log ====&lt;br /&gt;
&lt;br /&gt;
Here is an example of what was done for Terra Mystica which is simple and straightforward:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
//Define the proper message&lt;br /&gt;
		$message = clienttranslate(&#039;${player_name} gets ${power_income} via Structures&#039;);&lt;br /&gt;
		if ($price &amp;gt; 0) {&lt;br /&gt;
			$this-&amp;gt;DbQuery(&amp;quot;UPDATE player SET player_score = player_score - $price WHERE player_id = $player_id&amp;quot;);&lt;br /&gt;
			$message = clienttranslate(&#039;${player_name} pays ${vp_price} and gets ${power_income} via Structures&#039;);&lt;br /&gt;
		}&lt;br /&gt;
&lt;br /&gt;
// Notify&lt;br /&gt;
		$this-&amp;gt;notifyAllPlayers( &amp;quot;powerViaStructures&amp;quot;, $message, array(&lt;br /&gt;
			&#039;i18n&#039; =&amp;gt; array( ),&lt;br /&gt;
			&#039;player_id&#039; =&amp;gt; $player_id,&lt;br /&gt;
			&#039;player_name&#039; =&amp;gt; $this-&amp;gt;getUniqueValueFromDb( &amp;quot;SELECT player_name FROM player WHERE player_id = $player_id&amp;quot; ),&lt;br /&gt;
			&#039;power_tokens&#039; =&amp;gt; $power_tokens,&lt;br /&gt;
			&#039;vp_price&#039; =&amp;gt; $this-&amp;gt;getLogsVPAmount($price),&lt;br /&gt;
			&#039;power_income&#039; =&amp;gt; $this-&amp;gt;getLogsPowerAmount($power_income),&lt;br /&gt;
			&#039;newScore&#039; =&amp;gt; $this-&amp;gt;getUniqueValueFromDb( &amp;quot;SELECT player_score FROM player WHERE player_id = $player_id&amp;quot; ),&lt;br /&gt;
			&#039;counters&#039; =&amp;gt; $this-&amp;gt;getGameCounters(null),&lt;br /&gt;
		) );&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
With some functions to have the needed html added inside the substitution variable, such as:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
function getLogsPowerAmount( $amount ) {&lt;br /&gt;
		return &amp;quot;&amp;lt;div class=&#039;tmlogs_icon&#039; title=&#039;Power&#039;&amp;gt;&amp;lt;div class=&#039;power_amount&#039;&amp;gt;$amount&amp;lt;/div&amp;gt;&amp;lt;/div&amp;gt;&amp;quot;;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Note: injecting html from php is not ideal but easy, if you want more clean solution, use method below but it is a lot more sophisticated.&lt;br /&gt;
&lt;br /&gt;
==== Inject images and styled html in the log ====&lt;br /&gt;
&lt;br /&gt;
{{InfoBox|title=Warning — Translation|maxWidth=500|color=#c00|body=&#039;&#039;&#039;In order to prevent interference with the translation process, keep in mind that you must only apply modifications to the args object, and not try to substitute the keys (the &amp;lt;code&amp;gt;${player_name}&amp;lt;/code&amp;gt; parts of your string) in the log string.&#039;&#039;&#039;}}&lt;br /&gt;
&lt;br /&gt;
So you want nice pictures in the game log. What do you do? The first idea that comes to mind is to send html from php in notifications (see method above). &lt;br /&gt;
&lt;br /&gt;
This is a bad idea for many reasons:&lt;br /&gt;
&lt;br /&gt;
* It&#039;s bad architecture. ui elements leak into the server, and now you have to manage the ui in multiple places.&lt;br /&gt;
* If you decided to change something in the ui in future version, replay logs for old games and tutorials may not work, since they use stored notifications.&lt;br /&gt;
* Log previews for old games become unreadable. (This is the log state before you enter the game replay, which is useful for troubleshooting and game analysis.)&lt;br /&gt;
* It&#039;s more data to transfer and store in the db.&lt;br /&gt;
* It&#039;s a nightmare for translators.&lt;br /&gt;
&lt;br /&gt;
So what else can you do? You can use client side log injection to intercept log arguments (which come from the server) and replace them with html on the client side. Here are three different method you can use to achieve this.&lt;br /&gt;
&lt;br /&gt;
===== Override &amp;lt;code&amp;gt;this.format_string_recursive()&amp;lt;/code&amp;gt; method =====&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Ingredients:&#039;&#039;&#039; ggg.js, ggg.game.php&lt;br /&gt;
&lt;br /&gt;
I use this recipe for &#039;&#039;&#039;client side log injection&#039;&#039;&#039; to intercept log arguments (which come from the server) and replace them with html on the client side.&lt;br /&gt;
&lt;br /&gt;
[[File:clientloginjection.png|left]] &lt;br /&gt;
&lt;br /&gt;
ggg.js&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt; &lt;br /&gt;
&lt;br /&gt;
        /** Override this function to inject html into log items. This is a built-in BGA method.  */&lt;br /&gt;
&lt;br /&gt;
        /* @Override */&lt;br /&gt;
        format_string_recursive : function format_string_recursive(log, args) {&lt;br /&gt;
            try {&lt;br /&gt;
                if (log &amp;amp;&amp;amp; args &amp;amp;&amp;amp; !args.processed) {&lt;br /&gt;
                    args.processed = true;&lt;br /&gt;
                    &lt;br /&gt;
&lt;br /&gt;
                    // list of special keys we want to replace with images&lt;br /&gt;
                    var keys = [&#039;place_name&#039;,&#039;token_name&#039;];&lt;br /&gt;
                    &lt;br /&gt;
                  &lt;br /&gt;
                    for ( var i in keys) {&lt;br /&gt;
                        var key = keys[i];&lt;br /&gt;
                        key in args &amp;amp;&amp;amp; args[key] = this.getTokenDiv(key, args);                            &lt;br /&gt;
&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            } catch (e) {&lt;br /&gt;
                console.error(log,args,&amp;quot;Exception thrown&amp;quot;, e.stack);&lt;br /&gt;
            }&lt;br /&gt;
            return this.inherited({callee: format_string_recursive}, arguments);&lt;br /&gt;
        },&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Important:&#039;&#039;&#039; In the &#039;&#039;format_string_recursive&#039;&#039; method, the &#039;args&#039; parameter will only contain arguments passed to it from the notify method in ggg.game.php (see below).&lt;br /&gt;
&lt;br /&gt;
The &#039;log&#039; parameter is the actual string that is inserted into the logs. You can perform additional js string manipulation on it.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        getTokenDiv : function(key, args) {&lt;br /&gt;
            // ... implement whatever html you want here, example from sharedcode.js&lt;br /&gt;
            var token_id = args[key];&lt;br /&gt;
            var item_type = getPart(token_id,0);&lt;br /&gt;
            var logid = &amp;quot;log&amp;quot; + (this.globalid++) + &amp;quot;_&amp;quot; + token_id;&lt;br /&gt;
            switch (item_type) {&lt;br /&gt;
                case &#039;wcube&#039;:&lt;br /&gt;
                    var tokenDiv = this.format_block(&#039;jstpl_resource_log&#039;, {&lt;br /&gt;
                        &amp;quot;id&amp;quot; : logid,&lt;br /&gt;
                        &amp;quot;type&amp;quot; : &amp;quot;wcube&amp;quot;,&lt;br /&gt;
                        &amp;quot;color&amp;quot; : getPart(token_id,1),&lt;br /&gt;
                    });&lt;br /&gt;
                    return tokenDiv;&lt;br /&gt;
             &lt;br /&gt;
                case &#039;meeple&#039;:&lt;br /&gt;
                    if ($(token_id)) {&lt;br /&gt;
                        var clone = dojo.clone($(token_id));&lt;br /&gt;
    &lt;br /&gt;
                        dojo.attr(clone, &amp;quot;id&amp;quot;, logid);&lt;br /&gt;
                        this.stripPosition(clone);&lt;br /&gt;
                        dojo.addClass(clone, &amp;quot;logitem&amp;quot;);&lt;br /&gt;
                        return clone.outerHTML;&lt;br /&gt;
                    }&lt;br /&gt;
                    break;&lt;br /&gt;
     &lt;br /&gt;
                default:&lt;br /&gt;
                    break;&lt;br /&gt;
            }&lt;br /&gt;
&lt;br /&gt;
            return &amp;quot;&#039;&amp;quot; + this.clienttranslate_string(this.getTokenName(token_id)) + &amp;quot;&#039;&amp;quot;;&lt;br /&gt;
       },&lt;br /&gt;
       getTokenName : function(key) {&lt;br /&gt;
           return this.gamedatas.token_types[key].name; // get name for the key, from static table for example&lt;br /&gt;
       },&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note that in this case the server simply injects token_id as a name, and the client substitutes it for the translated name or the picture.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
ggg.game.php:&lt;br /&gt;
&lt;br /&gt;
           $this-&amp;gt;notifyAllPlayers(&#039;playerLog&#039;,clienttranslate(&#039;Game moves ${token_name}&#039;),[&#039;token_name&#039;=&amp;gt;$token_id]);&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Important:&#039;&#039;&#039; As noted above, only arguments actually passed by this method are available to the args parameter received in the client-side &#039;&#039;format_string_recursive&#039;&#039; method.&lt;br /&gt;
&lt;br /&gt;
Sometimes it is the case that you want to pass arguments that are not actually included in the output message. For example, suppose we have a method like this:&lt;br /&gt;
&lt;br /&gt;
           $this-&amp;gt;notifyAllPlayers(&#039;tokenPlaced&#039;,clienttranslate(&#039;Player placed ${token_name}&#039;),array(&lt;br /&gt;
              &#039;token_name&#039; =&amp;gt; $token_id,&lt;br /&gt;
              &#039;zone_played&#039; =&amp;gt; $zone);&lt;br /&gt;
&lt;br /&gt;
This will output &amp;quot;Player placed ${token_name}&amp;quot; in the log, and if we subscribe to a notification method activated by the &amp;quot;tokenPlaced&amp;quot; event in the client-side code, that method can make use of the &#039;zone_played&#039; argument. &lt;br /&gt;
&lt;br /&gt;
Now if you want to make some really cool things with game log, most probably you would need more arguments than are included in log message. The problem with that,&lt;br /&gt;
it will work at first, but if you reload game using F5 or when the game loads in turn based mode, you will loose your additional parameters, why? Because when game reloads it does not actually send same notifications, it sends special &amp;quot;hitstorical_log&amp;quot; notification where all  parameters not listed in the message are removed. In example above, field zone_played would be removed from historical log as it is not included in message of the notification. You can till preserve specific arguments in historical log by adding special field preserve to notification arguments like this:&lt;br /&gt;
 &lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
           $this-&amp;gt;notifyAllPlayers(&#039;tokenPlaced&#039;,clienttranslate(&#039;Player placed ${token_name}&#039;),array(&lt;br /&gt;
              &#039;token_name&#039; =&amp;gt; $token_id,&lt;br /&gt;
              &#039;zone_played&#039; =&amp;gt; $zone,&lt;br /&gt;
              &#039;preserve&#039; =&amp;gt; [ &#039;zone_played&#039; ]&lt;br /&gt;
           );&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Now you can use zone_played in format_string_recursive even in historical logs.&lt;br /&gt;
&lt;br /&gt;
===== Use &amp;lt;code&amp;gt;:formatFunction&amp;lt;/code&amp;gt; option provided by &amp;lt;code&amp;gt;dojo.string.substitute&amp;lt;/code&amp;gt; =====&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Ingredients:&#039;&#039;&#039; ggg.js, ggg.game.php, ggg_ggg.tpl, ggg.css&lt;br /&gt;
&lt;br /&gt;
The above method will work in most of the cases, but if you use dotted keys such as &amp;lt;code&amp;gt;${card.name}&amp;lt;/code&amp;gt; (which is supported by the framework, for private state args), the key won&#039;t be substituted because the &amp;lt;code&amp;gt;key in arg&amp;lt;/code&amp;gt; test will fail. If so you need to rely either on this way, or the one after.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;WARNING:&#039;&#039;&#039; using this method on an already advanced project will require you to go through all your notifications to change keys !&lt;br /&gt;
&lt;br /&gt;
Under the hood, the &#039;&#039;&#039;this.format_string_recursive()&#039;&#039;&#039; function calls the &#039;&#039;&#039;dojo.string.substitute&#039;&#039;&#039; method which substitutes &amp;lt;code&amp;gt;${keys}&amp;lt;/code&amp;gt; with the value provided. If you take a look at the [https://dojotoolkit.org/reference-guide/1.7/dojo/string.html#substitute documentation] and [https://github.com/dojo/dojo/blob/c3ceb017cfa25b703f5662dc83d1c8aae9bc5d81/string.js#L163 source code] you can notice that the key can be suffixed with a colon (&amp;lt;code&amp;gt;:&amp;lt;/code&amp;gt;) followed by a function name. This will allow you to specify directly in the substitution string which keys need HTML injection.&lt;br /&gt;
&lt;br /&gt;
First of all, you need to define your formatting function in the ggg.js file:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
[[ggg.js]]&lt;br /&gt;
        getTokenDiv : function(value, key) {&lt;br /&gt;
            //This is only an example implementation, you need to write your own.&lt;br /&gt;
            //The method should return HTML code&lt;br /&gt;
            switch (key) {&lt;br /&gt;
                case &#039;html_injected_argument1&#039;:&lt;br /&gt;
                    return this.format_block(&#039;jstpl_HTMLLogElement1&#039;,{value: value});&lt;br /&gt;
                case &#039;html_injected_argument2&#039;:&lt;br /&gt;
                    return this.format_block(&#039;jstpl_HTMLLogElement2&#039;,{value: value});&lt;br /&gt;
                ...&lt;br /&gt;
            }&lt;br /&gt;
       }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Obviously you need to define the appropriate templates in the ggg_ggg.tpl file:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
[[ggg_ggg.tpl]]&lt;br /&gt;
let jstpl_HTMLLogElement1 = &#039;&amp;lt;div class=&amp;quot;log-element log-element-1-${value}&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&#039;;&lt;br /&gt;
let jstpl_HTMLLogElement2 = &#039;&amp;lt;div class=&amp;quot;log-element log-element-2-${value}&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&#039;;&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
And the appropriate classes in ggg.css.&lt;br /&gt;
&lt;br /&gt;
Then you need to add the &amp;lt;code&amp;gt;dojo/aspect&amp;lt;/code&amp;gt; module at the top of the ggg.js file:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;[[ggg.js]]&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
 define([&lt;br /&gt;
     &amp;quot;dojo&amp;quot;, &amp;quot;dojo/_base/declare&amp;quot;,&lt;br /&gt;
     &#039;&#039;&#039;&amp;lt;span style=&amp;quot;color:green;&amp;quot;&amp;gt;&amp;quot;dojo/aspect&amp;quot;,&amp;lt;/span&amp;gt;                 //MUST BE IN THIRD POSITION&#039;&#039;&#039; (see [[#Including your own JavaScript module (II)|below]])&lt;br /&gt;
     &amp;quot;ebg/core/gamegui&amp;quot;,&lt;br /&gt;
     &amp;quot;ebg/counter&amp;quot;,&lt;br /&gt;
 ], function (dojo, declare, &amp;lt;span style=&amp;quot;color:green;&amp;quot;&amp;gt;&#039;&#039;&#039;aspect&#039;&#039;&#039;&amp;lt;/span&amp;gt;) {&lt;br /&gt;
 ...&lt;br /&gt;
&lt;br /&gt;
And you also need to add the following code in your &amp;lt;code&amp;gt;contructor&amp;lt;/code&amp;gt; method in the ggg.js:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;[[ggg.js]]&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
         constructor: function(){&lt;br /&gt;
&lt;br /&gt;
             // ... skipped code ...&lt;br /&gt;
             let gameObject = this;            //Needed as the this object in aspect.before will not refer to the game object in which the formatting function resides&lt;br /&gt;
             aspect.before(dojo.string, &amp;quot;substitute&amp;quot;, function(template, map, transform) {      //This allows you to modify the arguments of the dojo.string.substitute method before they&#039;re actually passed to it&lt;br /&gt;
                 return [template, map, transform, gameObject];&lt;br /&gt;
             });&lt;br /&gt;
&lt;br /&gt;
Now you&#039;re all set to inject HTML in your logs. To actually achieve this, you must specify the function name with the key like so:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;[[ggg.game.php]]&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
 $this-&amp;gt;notifyAllPlayers(&amp;quot;notificationName&amp;quot;, clienttranslate(&amp;quot;This log message contains ${plainTextArgument} and the following will receive HTML injection: ${html_injected_argument1:getTokenDiv}&amp;quot;), [&lt;br /&gt;
     &amp;quot;plainTextArgument&amp;quot; =&amp;gt; &amp;quot;some plain text here&amp;quot;,&lt;br /&gt;
     &amp;quot;html_injected_argument1&amp;quot; =&amp;gt; &amp;quot;some value used by getTokenDiv&amp;quot;,&lt;br /&gt;
 ]);&lt;br /&gt;
&lt;br /&gt;
You&#039;re not limited writing only one function, you can write as many functions as you like, and have them each inject a specific type of HTML. You just need to specify the relevant function name after the column in the substitution key.&lt;br /&gt;
&lt;br /&gt;
===== Use &amp;lt;code&amp;gt;transform&amp;lt;/code&amp;gt; argument of &amp;lt;code&amp;gt;dojo.string.substitute&amp;lt;/code&amp;gt; =====&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Ingredients:&#039;&#039;&#039; ggg.js, ggg.game.php, ggg_ggg.tpl, ggg.css&lt;br /&gt;
&lt;br /&gt;
This method is also relying on the use of &amp;lt;code&amp;gt;dojo.string.substitute&amp;lt;/code&amp;gt; by the framework, and will use the &amp;lt;code&amp;gt;transform&amp;lt;/code&amp;gt; argument, which, accordting to [https://github.com/dojo/dojo/blob/c3ceb017cfa25b703f5662dc83d1c8aae9bc5d81/string.js#L163 source code] and [https://dojotoolkit.org/reference-guide/1.7/dojo/string.html#substitute documentation] will be run on all the messages going through dojo.string.substitute.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;WARNING:&#039;&#039;&#039; This method will be applied to all strings that go through dojo.string.substitute. As such you must take extra care not to substitute keys that may be used by the framework (i.e. ${id}). In order to do so, a good practise would be to prefix all keys that need substitution with a trigram of the game name.&lt;br /&gt;
&lt;br /&gt;
Since all the keys will be fed to the tranform function, by default, it must return the value, substituted or not per your needs. You can define the function like this in the ggg.js file:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;[[ggg.js]]&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
         getTokenDiv : function(value, key) {&lt;br /&gt;
             //This is only an example implementation, you need to write your own.&lt;br /&gt;
             //The method should return HTML code&lt;br /&gt;
             switch (key) {&lt;br /&gt;
                 case &#039;html_injected_argument1&#039;:&lt;br /&gt;
                     return this.format_block(&#039;jstpl_HTMLLogElement1&#039;,{value: value});&lt;br /&gt;
                 case &#039;html_injected_argument2&#039;:&lt;br /&gt;
                     return this.format_block(&#039;jstpl_HTMLLogElement2&#039;,{value: value});&lt;br /&gt;
                 ...&lt;br /&gt;
                 default:&lt;br /&gt;
                     return value; //Needed otherwise regular strings won&#039;t appear since since the value isn&#039;t returned by the function&lt;br /&gt;
             }&lt;br /&gt;
         }&lt;br /&gt;
&lt;br /&gt;
The templates must be defined in the ggg_ggg.tpl file and the corresponding CSS classes in the ggg.css file.&lt;br /&gt;
&lt;br /&gt;
You need to add the following code at the beginning of the ggg.js file:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;[[ggg.js]]&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
 define([&lt;br /&gt;
     &amp;quot;dojo&amp;quot;, &amp;quot;dojo/_base/declare&amp;quot;,&lt;br /&gt;
     &#039;&#039;&#039;&amp;lt;span style=&amp;quot;color:green;&amp;quot;&amp;gt;&amp;quot;dojo/aspect&amp;quot;,&amp;lt;/span&amp;gt;                 //MUST BE IN THIRD POSITION&#039;&#039;&#039; (see [[#Including your own JavaScript module (II)|below]])&lt;br /&gt;
     &amp;quot;ebg/core/gamegui&amp;quot;,&lt;br /&gt;
     &amp;quot;ebg/counter&amp;quot;,&lt;br /&gt;
 ], function (dojo, declare, &amp;lt;span style=&amp;quot;color:green;&amp;quot;&amp;gt;&#039;&#039;&#039;aspect&#039;&#039;&#039;&amp;lt;/span&amp;gt;) {&lt;br /&gt;
 ...&lt;br /&gt;
&lt;br /&gt;
And the following code to the &amp;lt;code&amp;gt;constructor&amp;lt;/code&amp;gt; method in ggg.js:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;[[ggg.js]]&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
         constructor: function(){&lt;br /&gt;
             // ... skipped code ...&lt;br /&gt;
             let transformFunction = dojo.hitch(this, &amp;quot;getTokenDiv&amp;quot;);          //Needed as the this object in aspect.before will not refer to the game object in which the formatting function resides&lt;br /&gt;
             aspect.before(dojo.string, &amp;quot;substitute&amp;quot;, function(template, map, transform) {&lt;br /&gt;
                 if (undefined === transform) {    //Check for a transform function presence, just in case&lt;br /&gt;
                     return [template, map, transformFunction];&lt;br /&gt;
                 }&lt;br /&gt;
             });&lt;br /&gt;
&lt;br /&gt;
Then you&#039;re all set for log injection, no need to change anything on the PHP side.&lt;br /&gt;
&lt;br /&gt;
==== Processing logs on re-loading ====&lt;br /&gt;
&lt;br /&gt;
You rarely need to process logs when reloading, but if you want to do something fancy you may have to do it after logs are loaded. &lt;br /&gt;
Logs are loaded asyncronously so you have to listen for logs to be fully loaded.&lt;br /&gt;
Unfortunately there is no direct way of doing it so this is the hack.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Hack alert&#039;&#039;&#039; - this extends undocumented function and may be broken when framework is updated&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Ingredients:&#039;&#039;&#039; ggg.js&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
			/*&lt;br /&gt;
  			* [Undocumented] Override BGA framework functions to call onLoadingLogsComplete when loading is done&lt;br /&gt;
                        @Override&lt;br /&gt;
   			*/&lt;br /&gt;
			setLoader: function(image_progress, logs_progress) {&lt;br /&gt;
				this.inherited(arguments); // required, this is &amp;quot;super()&amp;quot; call, do not remove&lt;br /&gt;
				//console.log(&amp;quot;loader&amp;quot;, image_progress, logs_progress)&lt;br /&gt;
				if (!this.isLoadingLogsComplete &amp;amp;&amp;amp; logs_progress &amp;gt;= 100) {&lt;br /&gt;
					this.isLoadingLogsComplete = true; // this is to prevent from calling this more then once&lt;br /&gt;
					this.onLoadingLogsComplete();&lt;br /&gt;
				}&lt;br /&gt;
			},&lt;br /&gt;
&lt;br /&gt;
			onLoadingLogsComplete: function() {&lt;br /&gt;
				console.log(&#039;Loading logs complete&#039;);&lt;br /&gt;
				// do something here&lt;br /&gt;
			},&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Player Panel ===&lt;br /&gt;
&lt;br /&gt;
==== Inserting non-player panel ====&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Ingredients:&#039;&#039;&#039; ggg.js, ggg_ggg.tpl&lt;br /&gt;
&lt;br /&gt;
If you want to insert non-player panel on the right side (for example to hold extra preferences, zooming controls, etc)&lt;br /&gt;
&lt;br /&gt;
this can go pretty much anywhere in template it will be moved later&lt;br /&gt;
&lt;br /&gt;
ggg_ggg.tpl:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
	&amp;lt;div class=&#039;player_board_config&#039; id=&amp;quot;player_board_config&amp;quot;&amp;gt;&lt;br /&gt;
        &amp;lt;!-- here is whatever you want, buttons just example --&amp;gt;&lt;br /&gt;
		&amp;lt;button id=&amp;quot;zoom-out&amp;quot; class=&amp;quot; fa fa-search-minus fa-2x config-control&amp;quot;&amp;gt;&amp;lt;/button&amp;gt;&lt;br /&gt;
		&amp;lt;button id=&amp;quot;zoom-in&amp;quot; class=&amp;quot; fa fa-search-plus fa-2x config-control&amp;quot;&amp;gt;&amp;lt;/button&amp;gt;&lt;br /&gt;
		&amp;lt;button id=&amp;quot;show-settings&amp;quot; class=&amp;quot;fa fa-cog fa-2x config-control &amp;quot;&amp;gt;&amp;lt;/button&amp;gt;&lt;br /&gt;
        &amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
some hackery required in js&lt;br /&gt;
&lt;br /&gt;
ggg.js:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
/* @Override */&lt;br /&gt;
	updatePlayerOrdering() {&lt;br /&gt;
		this.inherited(arguments);&lt;br /&gt;
		dojo.place(&#039;player_board_config&#039;, &#039;player_boards&#039;, &#039;first&#039;);&lt;br /&gt;
	},&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Images and Icons ===&lt;br /&gt;
&lt;br /&gt;
==== Accessing images from js ====&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Ingredients:&#039;&#039;&#039; ggg.js&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt; &lt;br /&gt;
     // your game resources&lt;br /&gt;
     &lt;br /&gt;
     var my_img = &#039;&amp;lt;img src=&amp;quot;&#039;+g_gamethemeurl+&#039;img/cards.jpg&amp;quot;/&amp;gt;&#039;;&lt;br /&gt;
     &lt;br /&gt;
     // shared resources&lt;br /&gt;
     var my_help_img = &amp;quot;&amp;lt;img class=&#039;imgtext&#039; src=&#039;&amp;quot; + g_themeurl + &amp;quot;img/layout/help_click.png&#039; alt=&#039;action&#039; /&amp;gt; &amp;lt;span class=&#039;tooltiptext&#039;&amp;gt;&amp;quot; +&lt;br /&gt;
                    text + &amp;quot;&amp;lt;/span&amp;gt;&amp;quot;;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== High-Definition Graphics ====&lt;br /&gt;
&lt;br /&gt;
Some users will have screens which can display text and images at a greater resolution than the usual 72 dpi, e.g. the &amp;quot;Retina&amp;quot; screens on the 5k iMac, all iPads, and high-DPI screens on laptops from many manufacturers. If you can get art assets at this size, they will make your game look extra beautiful. You &#039;&#039;could&#039;&#039; just use large graphics and scale them down, but that would increase the download time and bandwidth for users who can&#039;t display them. Instead, a good way is to prepare a separate graphics file at exactly twice the size you would use otherwise, and add &amp;quot;@2x&amp;quot; at the end of the filename, e.g. if pieces.png is 240x320, then pieces@2x.png is 480x640.&lt;br /&gt;
&lt;br /&gt;
There are two changes required in order to use the separate graphics files. First in your css, where you use a file, add a media query which overrides the original definition and uses the bigger version on devices which can display them. Ensuring that the &amp;quot;background-size&amp;quot; attribute is set means that the size of the displayed object doesn&#039;t change, but only is drawn at the improved dot pitch.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
.piece {&lt;br /&gt;
    position: absolute;&lt;br /&gt;
    background-image: url(&#039;img/pieces.png&#039;);&lt;br /&gt;
    background-size:240px 320px;&lt;br /&gt;
    z-index: 10;&lt;br /&gt;
}&lt;br /&gt;
@media (-webkit-min-device-pixel-ratio: 2), (min-device-pixel-ratio: 2), (min-resolution: 192dpi)&lt;br /&gt;
{&lt;br /&gt;
    .piece {&lt;br /&gt;
        background-image: url(&#039;img/pieces@2x.png&#039;);&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Secondly, in your setup function in javascript, you must ensure than only the appropriate one version of the file gets pre-loaded (otherwise you more than waste the bandwidth saved by maintaining the standard-resolution file). Note that the media query is the same in both cases:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
            var isRetina = &amp;quot;(-webkit-min-device-pixel-ratio: 2), (min-device-pixel-ratio: 2), (min-resolution: 192dpi)&amp;quot;;&lt;br /&gt;
            if (window.matchMedia(isRetina).matches)&lt;br /&gt;
            {&lt;br /&gt;
                this.dontPreloadImage( &#039;pieces.png&#039; );&lt;br /&gt;
                this.dontPreloadImage( &#039;board.jpg&#039; );&lt;br /&gt;
            }&lt;br /&gt;
            else&lt;br /&gt;
            {&lt;br /&gt;
                this.dontPreloadImage( &#039;pieces@2x.png&#039; );&lt;br /&gt;
                this.dontPreloadImage( &#039;board@2x.jpg&#039; );&lt;br /&gt;
            }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Using CSS to create different colors of game pieces if you have only white piece ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
background-color: #${color}; &lt;br /&gt;
background-blend-mode: multiply;&lt;br /&gt;
background-image: url( &#039;img/mypiece.png&#039;);&lt;br /&gt;
mask: url(&#039;img/mypiece.png&#039;);&lt;br /&gt;
-webkit-mask: url(&#039;img/mypiece.png&#039;);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
where ${color} - is color you want&lt;br /&gt;
&lt;br /&gt;
Note: piece has to be white (shades of gray). Sprite can be used too, just add add background-position as usual.&lt;br /&gt;
&lt;br /&gt;
==== Accessing player avatar URLs ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
      getPlayerAvatar(playerId) {&lt;br /&gt;
         let avatarURL = &#039;&#039;;&lt;br /&gt;
&lt;br /&gt;
         if (null != $(&#039;avatar_&#039; + playerId)) {&lt;br /&gt;
            let smallAvatarURL = dojo.attr(&#039;avatar_&#039; + playerId, &#039;src&#039;);&lt;br /&gt;
            avatarURL = smallAvatarURL.replace(&#039;_32.&#039;, &#039;_184.&#039;);&lt;br /&gt;
         }&lt;br /&gt;
         else {&lt;br /&gt;
            avatarURL = &#039;https://x.boardgamearena.net/data/data/avatar/default_184.jpg&#039;;&lt;br /&gt;
         }&lt;br /&gt;
&lt;br /&gt;
         return avatarURL;&lt;br /&gt;
      },&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note:  This gets avatar URLs at 184x184 resolution.  You can also use 92, 50, and 32 depending on which resolution you want.&lt;br /&gt;
&lt;br /&gt;
==== Adding Image buttons ====&lt;br /&gt;
&lt;br /&gt;
Its pretty trivial but just in case you need a working function:&lt;br /&gt;
&lt;br /&gt;
ggg.js:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
                addImageActionButton: function (id, div_html, handler) { // div_html is string not node&lt;br /&gt;
                    this.addActionButton(id, div_html, handler, &#039;&#039;, false, &#039;gray&#039;); &lt;br /&gt;
                    dojo.style(id, &amp;quot;border&amp;quot;, &amp;quot;none&amp;quot;); // remove ugly border&lt;br /&gt;
                    dojo.addClass(id, &amp;quot;bgaimagebutton&amp;quot;); // add css class to do more styling&lt;br /&gt;
                    return $(id); // return node for chaining&lt;br /&gt;
                },&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Example of usage:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    this.addImageActionButton(&#039;button_coin&#039;,&amp;quot;&amp;lt;div class=&#039;coin&#039;&amp;gt;&amp;lt;/div&amp;gt;&amp;quot;, ()=&amp;gt;{ alert(&#039;Ha!&#039;); });&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Other Fluff ===&lt;br /&gt;
&lt;br /&gt;
==== Use thematic fonts ====&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Ingredients:&#039;&#039;&#039; ggg.css&lt;br /&gt;
&lt;br /&gt;
Sometime game elements use specific fonts of text, if you want to match it up you can load some specific font (IMPORTANT: from some &#039;&#039;&#039;free font&#039;&#039;&#039; source. See notes below).&lt;br /&gt;
&lt;br /&gt;
[[File:Dragonline_font.png]]&lt;br /&gt;
&lt;br /&gt;
.css&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
/* latin-ext */&lt;br /&gt;
@font-face {&lt;br /&gt;
  font-family: &#039;Qwigley&#039;;&lt;br /&gt;
  font-style: normal;&lt;br /&gt;
  font-weight: 400;&lt;br /&gt;
  src: local(&#039;Qwigley&#039;), local(&#039;Qwigley-Regular&#039;), url(https://fonts.gstatic.com/s/qwigley/v6/2Dy1Unur1HJoklbsg4iPJ_Y6323mHUZFJMgTvxaG2iE.woff2) format(&#039;woff2&#039;);&lt;br /&gt;
  unicode-range: U+0100-024F, U+1E00-1EFF, U+20A0-20AB, U+20AD-20CF, U+2C60-2C7F, U+A720-A7FF;&lt;br /&gt;
}&lt;br /&gt;
/* latin */&lt;br /&gt;
@font-face {&lt;br /&gt;
  font-family: &#039;Qwigley&#039;;&lt;br /&gt;
  font-style: normal;&lt;br /&gt;
  font-weight: normal;&lt;br /&gt;
  src: local(&#039;Qwigley&#039;), local(&#039;Qwigley-Regular&#039;), url(https://fonts.gstatic.com/s/qwigley/v6/gThgNuQB0o5ITpgpLi4Zpw.woff2) format(&#039;woff2&#039;);&lt;br /&gt;
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2212, U+2215, U+E0FF, U+EFFD, U+F000;&lt;br /&gt;
}&lt;br /&gt;
@font-face {&lt;br /&gt;
  font-family: &#039;Qwigley&#039;;&lt;br /&gt;
  font-style: normal;&lt;br /&gt;
  font-weight: normal;&lt;br /&gt;
  src: local(&#039;Qwigley&#039;), local(&#039;Qwigley-Regular&#039;), url(http://ff.static.1001fonts.net/q/w/qwigley.regular.ttf) format(&#039;ttf&#039;);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.zone_title {&lt;br /&gt;
	display: inline-block;&lt;br /&gt;
	position: absolute;&lt;br /&gt;
	font: italic 32px/32px &amp;quot;Qwigley&amp;quot;, cursive;	   &lt;br /&gt;
	height: 32px;&lt;br /&gt;
	width: auto;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;NB:&#039;&#039;&#039; if you need to include a font that&#039;s not available online, an extra action will be needed from an admin. Please include the font file(s) in your img directory, and mention it to admins when requesting your game to be moved to alpha. &#039;&#039;&#039;Please remember that the font has to be free, and include a .txt with all appropriate license information about the font.&#039;&#039;&#039;&lt;br /&gt;
You can look for free fonts (for example) on https://fonts.google.com or https://www.fontsquirrel.com/)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Content Security Policy&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
BGA runs a Content Security Policy which will limit the origins from which you can load external fonts, in order to prevent license abuse.&lt;br /&gt;
&lt;br /&gt;
The CSP is a whitelist of allowed origins. To see the list, view the response headers of any page on Studio, and look for the &amp;quot;Content-Security-Policy&amp;quot; header.&lt;br /&gt;
&lt;br /&gt;
You will specifically want to check for the font-src token within these headers, and limit any external fonts to these sources.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;This list is subject to change&#039;&#039;&#039; but as of the time of writing, the only acceptabled external sites are use.typekit.net and fonts.gstatic.com.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Scale to fit for big boards ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Ingredients:&#039;&#039;&#039; ggg_ggg.tpl, ggg.js&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Lets say you have huge game board, and lets say you want it to be 1400px wide. Besides the board there will be side bar which is 240 and trim. &lt;br /&gt;
My display is 1920 wide so it fits, but there is big chance other people won&#039;t have that width. What do you do?&lt;br /&gt;
&lt;br /&gt;
You have to decide:&lt;br /&gt;
* If board does not fit you want scale whole thing down, the best way is probably use viewport (see https://en.doc.boardgamearena.com/Your_game_mobile_version)&lt;br /&gt;
* You can leave the board as is and make sure it is scrollable horizonatally&lt;br /&gt;
* You add custom scale just for the board (can add user controls  - and hook to transform: scale())&lt;br /&gt;
&lt;br /&gt;
I tried to auto-scale but this just does work, too many variables - browser zoom, 3d mode, viewport, custom bga scaling, devicePixelRatio - all create some impossible coctail of zooming...&lt;br /&gt;
Here is scaling functing for custom user scaling&lt;br /&gt;
&lt;br /&gt;
ggg_ggg.tpl:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
   &amp;lt;div id=&amp;quot;thething&amp;quot; class=&amp;quot;thething&amp;quot;&amp;gt;&lt;br /&gt;
            ... everything else you declare ...&lt;br /&gt;
   &amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
ggg.js:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    onZoomPlus: function() {&lt;br /&gt;
       this.setZoom(this.zoom + 0.1);&lt;br /&gt;
    },&lt;br /&gt;
    onZoomMinus: function() {&lt;br /&gt;
       this.setZoom(this.zoom - 0.1);&lt;br /&gt;
    },&lt;br /&gt;
&lt;br /&gt;
    setZoom: function (zoom) {&lt;br /&gt;
      zoom = parseInt(zoom) || 0;&lt;br /&gt;
      if (zoom === 0 || zoom &amp;lt; 0.1 || zoom &amp;gt; 10) {&lt;br /&gt;
        zoom = 1;&lt;br /&gt;
      }&lt;br /&gt;
      this.zoom = zoom;&lt;br /&gt;
      var inner = document.getElementById(&amp;quot;thething&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
      if (zoom == 1) {&lt;br /&gt;
        inner.style.removeProperty(&amp;quot;transform&amp;quot;);&lt;br /&gt;
        inner.style.removeProperty(&amp;quot;width&amp;quot;);&lt;br /&gt;
      } else {&lt;br /&gt;
        inner.style.transform = &amp;quot;scale(&amp;quot; + zoom + &amp;quot;)&amp;quot;;&lt;br /&gt;
        inner.style.transformOrigin = &amp;quot;0 0&amp;quot;;&lt;br /&gt;
        inner.style.width = 100 / zoom + &amp;quot;%&amp;quot;;&lt;br /&gt;
      }&lt;br /&gt;
      localStorage.setItem(`${this.game_name}_zoom`, &amp;quot;&amp;quot; + this.zoom);&lt;br /&gt;
      this.onScreenWidthChange();&lt;br /&gt;
    },&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Dynamic tooltips ===&lt;br /&gt;
&lt;br /&gt;
If you really need a dynamic tooltip you can use this technique. (Only use it if the static tooltips provided by the BGA framework are not sufficient.)&lt;br /&gt;
&lt;br /&gt;
            new dijit.Tooltip({&lt;br /&gt;
                connectId: [&amp;quot;divItemId&amp;quot;],&lt;br /&gt;
                getContent: function(matchedNode){&lt;br /&gt;
                    return &amp;quot;... calculated ...&amp;quot;; &lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
This is an out-of-the-box djit.Tooltip. It has a &#039;&#039;getContent&#039;&#039; method which is called dynamically.&lt;br /&gt;
&lt;br /&gt;
The string returned by getContent() becomes the innerHTML of the tooltip, so it can be anything. In this example matchedNode is a dojo node representing dom object with id of &amp;quot;divItemId&amp;quot; but there are more parameters which I am not posting here which allows more sophisticated subnode queries (i.e. you can attach tooltip to all nodes with class or whatever).&lt;br /&gt;
&lt;br /&gt;
[https://dojotoolkit.org/reference-guide/1.10/dijit/Tooltip.html dijit.Tooltip]&lt;br /&gt;
&lt;br /&gt;
It&#039;s not part of the BGA API so use at your own risk.&lt;br /&gt;
&lt;br /&gt;
=== Rendering text with players color and proper background ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Ingredients:&#039;&#039;&#039; ggg.js&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        /* Implementation of proper colored You with background in case of white or light colors  */&lt;br /&gt;
 &lt;br /&gt;
        divYou: function() {&lt;br /&gt;
            var color = this.gamedatas.players[this.player_id].color;&lt;br /&gt;
            var color_bg = &amp;quot;&amp;quot;;&lt;br /&gt;
            if (this.gamedatas.players[this.player_id] &amp;amp;&amp;amp; this.gamedatas.players[this.player_id].color_back) {&lt;br /&gt;
                color_bg = &amp;quot;background-color:#&amp;quot; + this.gamedatas.players[this.player_id].color_back + &amp;quot;;&amp;quot;;&lt;br /&gt;
            }&lt;br /&gt;
            var you = &amp;quot;&amp;lt;span style=\&amp;quot;font-weight:bold;color:#&amp;quot; + color + &amp;quot;;&amp;quot; + color_bg + &amp;quot;\&amp;quot;&amp;gt;&amp;quot; + __(&amp;quot;lang_mainsite&amp;quot;, &amp;quot;You&amp;quot;) + &amp;quot;&amp;lt;/span&amp;gt;&amp;quot;;&lt;br /&gt;
            return you;&lt;br /&gt;
        },&lt;br /&gt;
&lt;br /&gt;
        /* Implementation of proper colored player name with background in case of white or light colors  */&lt;br /&gt;
&lt;br /&gt;
        divColoredPlayer: function(player_id) {&lt;br /&gt;
            var color = this.gamedatas.players[player_id].color;&lt;br /&gt;
            var color_bg = &amp;quot;&amp;quot;;&lt;br /&gt;
            if (this.gamedatas.players[player_id] &amp;amp;&amp;amp; this.gamedatas.players[player_id].color_back) {&lt;br /&gt;
                color_bg = &amp;quot;background-color:#&amp;quot; + this.gamedatas.players[player_id].color_back + &amp;quot;;&amp;quot;;&lt;br /&gt;
            }&lt;br /&gt;
            var div = &amp;quot;&amp;lt;span style=\&amp;quot;color:#&amp;quot; + color + &amp;quot;;&amp;quot; + color_bg + &amp;quot;\&amp;quot;&amp;gt;&amp;quot; + this.gamedatas.players[player_id].name + &amp;quot;&amp;lt;/span&amp;gt;&amp;quot;;&lt;br /&gt;
            return div;&lt;br /&gt;
        },&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Cool realistic shadow effect with CSS ===&lt;br /&gt;
&lt;br /&gt;
==== Rectangles and circles ====&lt;br /&gt;
&lt;br /&gt;
It is often nice to have a drop shadow around tiles and tokens, to separate them from the table visually. It is very easy to add a shadow to rectangular elements, just add this to your css:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
.xxx-tile {&lt;br /&gt;
    box-shadow: 3px 3px 3px #000000a0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
box-shadow obeys &#039;&#039;&#039;border-radius&#039;&#039;&#039; of the element, so it will look good for rounded rectangles, and hence also circles (if border-radius is set appropriately).&lt;br /&gt;
&lt;br /&gt;
box-shadow also supports various other parameters and can be used to achieve effects such as glowing, borders, inner shadows etc. If you need to animate a box-shadow, you may be able to get better performance (avoiding redraws) if you attach the shadow to another element (possibly an ::after pseudo-element) and change only the &#039;&#039;&#039;opacity&#039;&#039;&#039; of that element.&lt;br /&gt;
&lt;br /&gt;
==== Irregular Shapes ====&lt;br /&gt;
&lt;br /&gt;
If you wish to make a shadow effect for game pieces that are not a rectangle, but your game pieces are drawn from rectangles in a PNG image, you can apply the shadow to the piece using any art package and save it inside the image. This usually will yield the best performance. Remember to account for the size of the shadow when you lay out images in the sprite sheet.&lt;br /&gt;
&lt;br /&gt;
However that sometimes will not be an option, for example if the image needs to be rotated while the shadow remains offset in the same direction. In this case, one option is to not use box-shadow but use filter, which is supported by recent major browsers.  This way, you can use the alpha channel of your element to drop a shadow.  This even work for transparent backgrounds, so that if you are using the &amp;quot;CSS-sprite&amp;quot; method, it will work!&lt;br /&gt;
&lt;br /&gt;
For instance:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
.xxx-token {&lt;br /&gt;
    filter: drop-shadow(0px 0px 1px #000000);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Beware that some browsers still do not always draw drop-shadow correctly. In particular, Safari frequently leaves bits of shadow behind when objects move around the screen. In Chrome, shadows sometimes flicker badly if another element is animating close by. Some of these correctness issues can be solved by adding &#039;&#039;&#039;isolation: isolate; will-change: filter;&#039;&#039;&#039; to affected elements, but this significantly affects redraw performance.&lt;br /&gt;
&lt;br /&gt;
Beware of performance issues - particularly on Safari (MacOS, iPhone and iPad). Keep in mind that drop-shadow are very GPU intensive. This becomes noticeable once you have about 40 components with drop-shadow filter. If that is your case, you can quite easily implement a user preference to disable shadows for users on slower machines:&lt;br /&gt;
&lt;br /&gt;
gameoptions.inc.php&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
100 =&amp;gt; array(&lt;br /&gt;
			&#039;name&#039; =&amp;gt; totranslate(&#039;Shadows&#039;),&lt;br /&gt;
			&#039;needReload&#039; =&amp;gt; true, // after user changes this preference game interface would auto-reload&lt;br /&gt;
			&#039;values&#039; =&amp;gt; array(&lt;br /&gt;
					1 =&amp;gt; array( &#039;name&#039; =&amp;gt; totranslate( &#039;Enabled&#039; ), &#039;cssPref&#039; =&amp;gt; &#039;&#039; ),&lt;br /&gt;
					2 =&amp;gt; array( &#039;name&#039; =&amp;gt; totranslate( &#039;Disabled&#039; ), &#039;cssPref&#039; =&amp;gt; &#039;no-shadow&#039; )&lt;br /&gt;
			)&lt;br /&gt;
	),&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[game].css&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
.no-shadow * {&lt;br /&gt;
	filter: none !important; &lt;br /&gt;
} &lt;br /&gt;
&amp;lt;/pre&amp;gt;For Safari, it is usually better to simply disable drop-shadow completely: [[Game interface stylesheet: yourgamename.css#Warning: using drop-shadow]].&lt;br /&gt;
&lt;br /&gt;
==== Shadows with clip-path ====&lt;br /&gt;
&lt;br /&gt;
For some reason, a shadow will not work together with clip-path on one element. To use both clip-path (when for example using .svg to cut out cardboard components from your .jpg spritesheet) and drop-shadow, you need to wrap the element into another one, and apply drop-shadow to the outer one, and clip-path to the inner one.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;div class=&#039;my-token-wrap&#039;&amp;gt;&lt;br /&gt;
  &amp;lt;div class=&#039;my-token&#039;&amp;gt;&lt;br /&gt;
  &amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
.my-token-wrap {&lt;br /&gt;
    filter: drop-shadow(0px 0px 1px #000000);&lt;br /&gt;
}&lt;br /&gt;
.my-token-wrap .my-token {&lt;br /&gt;
    clip-path: url(#my-token-path);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Using the CSS classes from the state machine ===&lt;br /&gt;
&lt;br /&gt;
If you need to hide or show stuff depending on the state of your game, you can of course use javascript, but CSS is hand enough for that.  The #overall-content element does change class depending on the game state.  For instance, if you are in state &#039;&#039;playerTurn&#039;&#039;, it will have the class &#039;&#039;gamestate_playerTurn&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
So now, if you want to show the discard pile only during player turns, you may use:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#discard_pile { display: none }&lt;br /&gt;
.gamestate_playerTurn #discard_pile { display: block }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This can be used if you want to change sizing of elements, position, layout or visual appearance.&lt;br /&gt;
&lt;br /&gt;
== Game Model and Database design ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Database for The euro game ===&lt;br /&gt;
Lets say we have a game with workers, dice, tokens, board, resources, money and vp. Workers and dice can be placed in various zones on the board, and you can get resources, money, tokens and vp in your home zone. Also tokens can be flipped or not flipped.&lt;br /&gt;
&lt;br /&gt;
[[File:Madeira board.png]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Now lets try to map it, we have&lt;br /&gt;
* (meeple,zone)&lt;br /&gt;
* (die, zone, sideup)&lt;br /&gt;
* (resource cube/money token/vp token,player home zone)&lt;br /&gt;
* (token, player home zone, flip state)&lt;br /&gt;
We can notice that resource and money are uncountable, and don&#039;t need to be track individually so we can replace our mapping to&lt;br /&gt;
* (resource type/money,player home zone, count)&lt;br /&gt;
And vp stored already for us in player table, so we can remove it from that list.&lt;br /&gt;
&lt;br /&gt;
Now when we get to encode it we can see that everything can be encoded as (object,zone,state) form, where object and zone is string and state is integer. The resource mapping is slightly different semantically so you can go with two table, or counting using same table with state been used as count for resources.&lt;br /&gt;
&lt;br /&gt;
So the piece mapping for non-grid based games can be in most case represented by (string: token_key, string: token_location, int: token_state), example of such database schema can be found here: [https://github.com/elaskavaia/bga-sharedcode/blob/master/dbmodel.sql dbmodel.sql] and class implementing access to it here [https://github.com/elaskavaia/bga-sharedcode/blob/master/modules/tokens.php table.game.php].&lt;br /&gt;
&lt;br /&gt;
Variant 1: Minimalistic&lt;br /&gt;
&lt;br /&gt;
 CREATE TABLE IF NOT EXISTS `token` (&lt;br /&gt;
  `token_key` varchar(32) NOT NULL,&lt;br /&gt;
  `token_location` varchar(32) NOT NULL,&lt;br /&gt;
  `token_state` int(10),&lt;br /&gt;
  PRIMARY KEY (`token_key`)&lt;br /&gt;
 ) ENGINE=InnoDB DEFAULT CHARSET=utf8;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+token&lt;br /&gt;
! token_key&lt;br /&gt;
! token_location&lt;br /&gt;
! token_state&lt;br /&gt;
|-&lt;br /&gt;
|meeple_red_1&lt;br /&gt;
|home_red&lt;br /&gt;
|0&lt;br /&gt;
|-&lt;br /&gt;
|dice_black_2&lt;br /&gt;
|board_guard&lt;br /&gt;
|1&lt;br /&gt;
|-&lt;br /&gt;
|dice_green_1&lt;br /&gt;
|board_action_mayor&lt;br /&gt;
|3&lt;br /&gt;
|-&lt;br /&gt;
|bread&lt;br /&gt;
|home_red&lt;br /&gt;
|5&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Now how we represent resource counters such as bread?&lt;br /&gt;
Using same table from we simply add special counter token for bread and use state to indicate the count. Note to keep first column unique we have to add player identification for that counter, i.e. ff0000 is red player.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+token&lt;br /&gt;
! token_key&lt;br /&gt;
! token_location&lt;br /&gt;
! token_state&lt;br /&gt;
|-&lt;br /&gt;
|bread_ff0000&lt;br /&gt;
|tableau_ff0000&lt;br /&gt;
|5&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
See php module for this table here https://github.com/elaskavaia/bga-sharedcode/blob/master/modules/tokens.php&lt;br /&gt;
&lt;br /&gt;
Variant 2: Additional resource table, resource count for each player id&lt;br /&gt;
&lt;br /&gt;
 CREATE TABLE IF NOT EXISTS `resource` (&lt;br /&gt;
  `player_id` int(10) unsigned NOT NULL,&lt;br /&gt;
  `resource_key` varchar(32) NOT NULL,&lt;br /&gt;
  `resource_count` int(10) signed NOT NULL,&lt;br /&gt;
  PRIMARY KEY (`player_id`,`resource_key`)&lt;br /&gt;
 ) ENGINE=InnoDB DEFAULT CHARSET=utf8;&lt;br /&gt;
&lt;br /&gt;
 ALTER TABLE resource ADD CONSTRAINT fk_player_id FOREIGN KEY (player_id) REFERENCES player(player_id);&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+resource&lt;br /&gt;
! player_id&lt;br /&gt;
! resource_key&lt;br /&gt;
! resource_count&lt;br /&gt;
|-&lt;br /&gt;
|123456&lt;br /&gt;
|bread&lt;br /&gt;
|5&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Variant 3: More normalised&lt;br /&gt;
&lt;br /&gt;
This version is similar to &amp;quot;card&amp;quot; table from hearts tutorial, you can also use exact cards database schema and Deck implementation for most purposes (even you not dealing with cards). &lt;br /&gt;
&lt;br /&gt;
 CREATE TABLE IF NOT EXISTS `token` (&lt;br /&gt;
  `token_id` int(10) unsigned NOT NULL AUTO_INCREMENT,&lt;br /&gt;
  `token_type` varchar(16) NOT NULL,&lt;br /&gt;
  `token_arg` int(11) NOT NULL,&lt;br /&gt;
  `token_location` varchar(32) NOT NULL,&lt;br /&gt;
  `token_state` int(10),&lt;br /&gt;
  PRIMARY KEY (`token_id`)&lt;br /&gt;
 ) ENGINE=InnoDB DEFAULT CHARSET=utf8;&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+token&lt;br /&gt;
! token_id&lt;br /&gt;
! token_type&lt;br /&gt;
! token_arg&lt;br /&gt;
! token_location&lt;br /&gt;
! token_state&lt;br /&gt;
|-&lt;br /&gt;
|22&lt;br /&gt;
|meeple&lt;br /&gt;
|123456&lt;br /&gt;
|home_123456&lt;br /&gt;
|0&lt;br /&gt;
|-&lt;br /&gt;
|23&lt;br /&gt;
|dice&lt;br /&gt;
|2&lt;br /&gt;
|board_guard&lt;br /&gt;
|1&lt;br /&gt;
|-&lt;br /&gt;
|26&lt;br /&gt;
|dice&lt;br /&gt;
|1&lt;br /&gt;
|board_action_mayor&lt;br /&gt;
|3&lt;br /&gt;
|-&lt;br /&gt;
|49&lt;br /&gt;
|bread&lt;br /&gt;
|0&lt;br /&gt;
|home_123456&lt;br /&gt;
|5&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Advantages of this would be is a bit more straightforward to do some queries in db, disadvantage its hard to read (as you can compare with previous example, you&lt;br /&gt;
cannot just look at say, ah I know what it means). Another questionable advantage is it allows you to do id randomisation, so it hard to do crafted queries to &lt;br /&gt;
cheat, the down side of that you cannot understand it either, and handcraft db states for debugging or testing.&lt;br /&gt;
&lt;br /&gt;
=== Database for The card game ===&lt;br /&gt;
&lt;br /&gt;
Lets say you have a standard card game, player have hidden cards in hand, you can draw card from draw deck, play card on tableau and discard to discard pile.&lt;br /&gt;
We have to design database for such game.&lt;br /&gt;
&lt;br /&gt;
In real word to &amp;quot;save&amp;quot; the game we take a picture a play area, save cards from it, then put away draw deck, discard and hand of each player separately and mark it, also we will record current scoring (if any) and who&#039;s turn was it.&lt;br /&gt;
&lt;br /&gt;
* Framework handles state machine transition, so you don&#039;t have to worry about database design for that (i.e. who&#039;s turn it is, what phase of the game we are at, you still have to design it but part of state machine step)&lt;br /&gt;
* Also framework supports basic player information, color, order around the table, basic scoring, etc, so you don&#039;t have to worry about it either&lt;br /&gt;
* The only thing you need in our database is state of the &amp;quot;board&amp;quot;, which is &amp;quot;where each pieces is, and in what state&amp;quot;, or (position,rotation) pair.&lt;br /&gt;
&lt;br /&gt;
Lets see what we have for that:&lt;br /&gt;
* The card state is very simple, its usually &amp;quot;face up/face down&amp;quot;, &amp;quot;tapped/untapped&amp;quot;, &amp;quot;right side up/up side down&amp;quot;&lt;br /&gt;
* As position go we never need real coordinates x,y,z. We need to know what &amp;quot;zone&amp;quot; card was, and depending on the zone it may sometimes need an extra &amp;quot;z&amp;quot; or &amp;quot;x&amp;quot; as card order. The zone position usually static or irrelevant.&lt;br /&gt;
* So our model is: we have cards, which have some attributes, at any given point in time they belong to a &amp;quot;zone&amp;quot;, and can also have order and state&lt;br /&gt;
* Now for mapping we should consider what information changes and what information is static, later is always candidate for material file&lt;br /&gt;
* For dynamic information we should try to reduce amount of fields we need&lt;br /&gt;
**  we need at least a field for card, so its one&lt;br /&gt;
**  we need to know what zone cards belong to, its 2&lt;br /&gt;
**  and we have possibly few other fields, if you look closely at you game you may find out that most of the zone only need one attribute at a time, i.e. draw pile always have cards face down, hand always face up, also for hand and discard order does not matter at all (but for draw it does matter). So in majority of cases we can get away with one single extra integer field representing state or order&lt;br /&gt;
* In real database both card and zone will be integers as primary keys referring to additional tables, but in our case its total overkill, so they can be strings as easily&lt;br /&gt;
&lt;br /&gt;
Variant 1: Minimalistic&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
CREATE TABLE IF NOT EXISTS `card` (&lt;br /&gt;
  `card_key` varchar(32) unsigned NOT NULL,&lt;br /&gt;
  `card_location` varchar(32) NOT NULL,&lt;br /&gt;
  `card_state` int(11) NOT NULL,&lt;br /&gt;
  PRIMARY KEY (`card_id`)&lt;br /&gt;
) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=1 ;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Variant 2: More normalised&lt;br /&gt;
&lt;br /&gt;
This version supported by Deck php class, so unless you want to rewrite db access layer go with this one&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
CREATE TABLE IF NOT EXISTS `card` (&lt;br /&gt;
  `card_id` int(10) unsigned NOT NULL AUTO_INCREMENT,&lt;br /&gt;
  `card_type` varchar(16) NOT NULL,&lt;br /&gt;
  `card_type_arg` int(11) NOT NULL,&lt;br /&gt;
  `card_location` varchar(16) NOT NULL,&lt;br /&gt;
  `card_location_arg` int(11) NOT NULL,&lt;br /&gt;
  PRIMARY KEY (`card_id`)&lt;br /&gt;
) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=1 ;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note: if you using this schema, some zones/locations have special semantic. The &#039;hand&#039; location is actually multiple locations - one per player, but player id is encoded as card_location_arg. If &#039;hand&#039; in your game is ordered, visible or can have some other card states, you cannot use hand location (replacement is hand_&amp;lt;player_id&amp;gt; or hand_&amp;lt;color_id&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
== Code Organization ==&lt;br /&gt;
&lt;br /&gt;
=== Including your own JavaScript module ===&lt;br /&gt;
&#039;&#039;&#039;Ingredients:&#039;&#039;&#039; ggg.js, modules/ggg_other.js&lt;br /&gt;
&lt;br /&gt;
* Create ggg_other.js in modules/ folder and sync&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
define([&lt;br /&gt;
    &amp;quot;dojo&amp;quot;, &amp;quot;dojo/_base/declare&amp;quot;&lt;br /&gt;
], function( dojo, declare )&lt;br /&gt;
{&lt;br /&gt;
return declare(&amp;quot;bgagame.other&amp;quot;, null, { // null here if we don&#039;t want to inherit from anything&lt;br /&gt;
        constructor: function(){},&lt;br /&gt;
        mystuff: function(){},&lt;br /&gt;
    });&lt;br /&gt;
        &lt;br /&gt;
});&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
* Modify ggg.js to include it&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
  define([ &amp;quot;dojo&amp;quot;, &amp;quot;dojo/_base/declare&amp;quot;, &amp;quot;ebg/core/gamegui&amp;quot;, &amp;quot;ebg/counter&amp;quot;,&lt;br /&gt;
    g_gamethemeurl + &amp;quot;modules/ggg_other.js&amp;quot;     // load my own module!!!&lt;br /&gt;
  ], function(dojo,&lt;br /&gt;
        declare) {&lt;br /&gt;
     &lt;br /&gt;
&lt;br /&gt;
use it&lt;br /&gt;
&lt;br /&gt;
  foo = new bgagame.other();&lt;br /&gt;
&lt;br /&gt;
=== Including your own JavaScript module (II) ===&lt;br /&gt;
&lt;br /&gt;
* Create ggg_other.js in modules/ folder and sync&lt;br /&gt;
&lt;br /&gt;
  define([], function () {&lt;br /&gt;
    return &amp;quot;value&amp;quot;;&lt;br /&gt;
  });&lt;br /&gt;
&lt;br /&gt;
* Modify ggg.js to include it&lt;br /&gt;
&lt;br /&gt;
  define([ &lt;br /&gt;
    &amp;quot;dojo&amp;quot;, &lt;br /&gt;
    &amp;quot;dojo/_base/declare&amp;quot;, &lt;br /&gt;
    &amp;quot;bgagame/modules/ggg_other&amp;quot;, &lt;br /&gt;
    &amp;quot;ebg/core/gamegui&amp;quot;, &lt;br /&gt;
    &amp;quot;ebg/counter&amp;quot;&lt;br /&gt;
  ], function(dojo, declare, other) {&lt;br /&gt;
  &lt;br /&gt;
  });&lt;br /&gt;
&lt;br /&gt;
  &lt;br /&gt;
This is maybe a little bit more the idea of the AMD Loader than the first option, although the first option should work as well.&lt;br /&gt;
&lt;br /&gt;
A little explanation to this:&lt;br /&gt;
The define function loads all the modules listed in the array and calls the following function with these loaded modules as parameters.&lt;br /&gt;
By putting your module at the third position in the array it is passed as the third parameter to the function. Be aware that the modules are resolved by position only, not by name. So you can load the module &#039;&#039;&#039;ggg_other&#039;&#039;&#039; and pass it as a parameter with the name &#039;&#039;&#039;other&#039;&#039;&#039;. &#039;&#039;&#039;gamegui&#039;&#039;&#039; and &#039;&#039;&#039;counter&#039;&#039;&#039; are passed in as well, but when the parameters are not defined they are just skipped. Because these modules put their content into the global scope it does not matter and you can use them from there.&lt;br /&gt;
&lt;br /&gt;
In the example above the string &amp;quot;value&amp;quot; is passed for the parameter &#039;&#039;&#039;other&#039;&#039;&#039;, but the function in your module can return whatever you want. It can be an object, an array, something you declared with dojo.declare, you can return even functions. &lt;br /&gt;
Your module can load other modules. Just put them in the array at the beginning and pass them as parameters to your function.&lt;br /&gt;
The advantage of passing the values as parameter is that you do not need to put these values in the global scope, so they can&#039;t be collisions with values defined in other scripts or the BGA Framework.&lt;br /&gt;
&lt;br /&gt;
The dojo toolkit provides good documentation to all of its components, the complete documentation for the AMD-Loader is here:&lt;br /&gt;
https://dojotoolkit.org/documentation/tutorials/1.10/modules/index.html It should be still correct, even as it seems to be only for version 1.10&lt;br /&gt;
&lt;br /&gt;
=== Including your own PHP module ===&lt;br /&gt;
&#039;&#039;&#039;Ingredients:&#039;&#039;&#039; ggg.game.php, modules/ggg_other.php&lt;br /&gt;
&lt;br /&gt;
* Create ggg_other.php in modules/ folder and sync&lt;br /&gt;
* Modify ggg.game.php to include it&lt;br /&gt;
&lt;br /&gt;
 require_once (&#039;modules/ggg_other.php&#039;);&lt;br /&gt;
&lt;br /&gt;
=== Creating a test class to run PHP locally ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Ingredients:&#039;&#039;&#039; ggg.game.php, stubs&lt;br /&gt;
For this you need stubs of other method you can use this for example&lt;br /&gt;
https://github.com/elaskavaia/bga-sharedcode/raw/master/misc/module/table/table.game.php&lt;br /&gt;
&lt;br /&gt;
Create another php files, i.e ggg_test.php&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;?php&lt;br /&gt;
define(&amp;quot;APP_GAMEMODULE_PATH&amp;quot;, &amp;quot;misc/&amp;quot;); // include path to stubs, which defines &amp;quot;table.game.php&amp;quot; and other classes&lt;br /&gt;
require_once (&#039;eminentdomaine.game.php&#039;);&lt;br /&gt;
&lt;br /&gt;
class MyGameTest1 extends MyGame { // this is your game class defined in ggg.game.php&lt;br /&gt;
    function __construct() {&lt;br /&gt;
        parent::__construct();&lt;br /&gt;
        include &#039;../material.inc.php&#039;;// this is how this normally included, from constructor&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // override/stub methods here that access db and stuff&lt;br /&gt;
    function getGameStateValue($var) {&lt;br /&gt;
        if ($var == &#039;round&#039;)&lt;br /&gt;
            return 3;&lt;br /&gt;
        return 0;&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
$x = new MyGameTest1(); // instantiate your class&lt;br /&gt;
$p = $x-&amp;gt;getGameProgression(); // call one of the methods to test&lt;br /&gt;
if ($p != 50)&lt;br /&gt;
    echo &amp;quot;Test1: FAILED&amp;quot;;&lt;br /&gt;
else&lt;br /&gt;
    echo &amp;quot;Test1: PASSED&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Run from command line like&lt;br /&gt;
 php7 ggg_test.php&lt;br /&gt;
&lt;br /&gt;
If you do it this way - you can also use local php debugger (i.e. integrated with IDE or command line).&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Avoiding code in dojo declare style ===&lt;br /&gt;
Dojo class declarations are rather bizzare and do not work with most IDEs.&lt;br /&gt;
If you want to write in plain JS with classes, you can stub all the dojo define/declare stuff&lt;br /&gt;
and hook your class into that, so the classes are outside of this mess.&lt;br /&gt;
&lt;br /&gt;
NOTE: this technique is for experienced developers, do not try it if you do not understand&lt;br /&gt;
the consequences.&lt;br /&gt;
&lt;br /&gt;
This is complete example of game .js class&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  // Testla is game name is has to be changed&lt;br /&gt;
class Testla {&lt;br /&gt;
	constructor(game) {&lt;br /&gt;
		console.log(&#039;game constructor&#039;);&lt;br /&gt;
		this.game = game;&lt;br /&gt;
		this.varfoo = new MyFoo(); // this example of class from custom module&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	setup(gamedatas) {&lt;br /&gt;
		console.log(&amp;quot;Starting game setup&amp;quot;, this.varfoo);&lt;br /&gt;
		this.gamedatas = gamedatas;&lt;br /&gt;
		this.dojo.create(&amp;quot;div&amp;quot;, { class: &#039;whiteblock&#039;, innerHTML: _(&amp;quot;hello&amp;quot;) }, &#039;thething&#039;);&lt;br /&gt;
		console.log(&amp;quot;Ending game setup&amp;quot;);&lt;br /&gt;
	};&lt;br /&gt;
	onEnteringState(stateName, args) {&lt;br /&gt;
		console.log(&#039;onEnteringState : &#039; + stateName, args);&lt;br /&gt;
		this.game.addActionButton(&#039;b1&#039;,_(&#039;Click Me&#039;), (e)=&amp;gt;this.onButtonClick(e));&lt;br /&gt;
	};&lt;br /&gt;
	onLeavingState(stateName) {&lt;br /&gt;
		console.log(&#039;onLeavingState : &#039; + stateName, args);&lt;br /&gt;
	};&lt;br /&gt;
	onUpdateActionButtons(stateName, args) {&lt;br /&gt;
		console.log(&#039;onUpdateActionButtons : &#039; + stateName, args);&lt;br /&gt;
	};&lt;br /&gt;
	onButtonClick(event) {&lt;br /&gt;
		console.log(&#039;onButtonClick&#039;,event);&lt;br /&gt;
	};&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
define([&lt;br /&gt;
	&amp;quot;dojo&amp;quot;, &amp;quot;dojo/_base/declare&amp;quot;,&lt;br /&gt;
	&amp;quot;ebg/core/gamegui&amp;quot;,&lt;br /&gt;
	&amp;quot;ebg/counter&amp;quot;,&lt;br /&gt;
	g_gamethemeurl + &#039;/modules/foo.js&#039; // custom module if needed&lt;br /&gt;
],&lt;br /&gt;
	function(dojo, declare) {&lt;br /&gt;
                // testla is game name is has to be changed&lt;br /&gt;
		return declare(&amp;quot;bgagame.testla&amp;quot;, ebg.core.gamegui, {&lt;br /&gt;
			constructor: function() {&lt;br /&gt;
				this.xapp = new Testla(this);&lt;br /&gt;
				this.xapp.dojo = dojo;&lt;br /&gt;
			},&lt;br /&gt;
			setup: function(gamedatas) {&lt;br /&gt;
				this.xapp.setup(gamedatas);&lt;br /&gt;
			},&lt;br /&gt;
			onEnteringState: function(stateName, args) {&lt;br /&gt;
				this.xapp.onEnteringState(stateName, args?.args);&lt;br /&gt;
			},&lt;br /&gt;
			onLeavingState: function(stateName) {&lt;br /&gt;
				this.xapp.onLeavingState(stateName, args);&lt;br /&gt;
			},&lt;br /&gt;
			onUpdateActionButtons: function(stateName, args) {&lt;br /&gt;
				this.xapp.onUpdateActionButtons(stateName, args);&lt;br /&gt;
			},&lt;br /&gt;
		});&lt;br /&gt;
	});&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== More readable JS: onEnteringState ===&lt;br /&gt;
&lt;br /&gt;
If you have a lot of states in onEnteringState or onUpdateActionButtons and friends - it becomes rather wild, you can do this trick to call some methods dynamically.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
     onEnteringState: function(stateName, args) {&lt;br /&gt;
       console.log(&#039;Entering state: &#039; + stateName, args);&lt;br /&gt;
&lt;br /&gt;
       // Call appropriate method&lt;br /&gt;
       var methodName = &amp;quot;onEnteringState_&amp;quot; + stateName;&lt;br /&gt;
       if (this[methodName] !== undefined) {             &lt;br /&gt;
          console.log(&#039;Calling &#039; + methodName, args.args);&lt;br /&gt;
          this[methodName](args.args);&lt;br /&gt;
       }&lt;br /&gt;
     },&lt;br /&gt;
&lt;br /&gt;
     onEnteringState_playerTurn: function(args) { // this is args directly, not args.args &lt;br /&gt;
         // process&lt;br /&gt;
     },&lt;br /&gt;
&lt;br /&gt;
     onEnteringState_playerSomethingElse: function(args) { &lt;br /&gt;
         // process&lt;br /&gt;
     },&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note: since its ignores the undefined functions you don&#039;t have define function for each state, but on the other hand you cannot make typos.&lt;br /&gt;
Same applies to onUpdateActionButtons except you pass &#039;args&#039; to method, not args.args, and for onLeavingState where you don&#039;t pass anything.&lt;br /&gt;
&lt;br /&gt;
=== Frameworks and Preprocessors ===&lt;br /&gt;
&lt;br /&gt;
* [[BGA Type Safe Template]] - Setting up a fully typed project using typescript and more!&lt;br /&gt;
* [[Using Vue]] - work-in-progress guide on using the modern framework Vue.js to create a game&lt;br /&gt;
* [[Using Typescript and Scss]] - How to auto-build Typescript and SCSS files to make your code cleaner&lt;br /&gt;
&lt;br /&gt;
== Backend ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Assigning Player Order ===&lt;br /&gt;
Normally when game starts there is &amp;quot;natural&amp;quot; player order assigned randomly.&lt;br /&gt;
&lt;br /&gt;
If you want to deliberatly assign player order at the start of the game (for example, in a game with teams options), you can do so by retrieving the initialization-only player attribute &#039;&#039;&#039;player_table_order&#039;&#039;&#039; and using it to assign values to &#039;&#039;&#039;player_no&#039;&#039;&#039; (which is normally assigned at the start of a game in the order in which players come to the table). (See [https://en.doc.boardgamearena.com/Game_database_model:_dbmodel.sql#The_player_table Game database model] for more details.)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Example:&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
                // Retrieve inital player order ([0=&amp;gt;playerId1, 1=&amp;gt;playerId2, ...])&lt;br /&gt;
		$playerInitialOrder = [];&lt;br /&gt;
		foreach ($players as $playerId =&amp;gt; $player) {&lt;br /&gt;
			$playerInitialOrder[$player[&#039;player_table_order&#039;]] = $playerId;&lt;br /&gt;
		}&lt;br /&gt;
		ksort($playerInitialOrder);&lt;br /&gt;
		$playerInitialOrder = array_flip(array_values($playerInitialOrder));&lt;br /&gt;
&lt;br /&gt;
		// Player order based on &#039;playerTeams&#039; option&lt;br /&gt;
		$playerOrder = [0, 1, 2, 3];&lt;br /&gt;
		switch ($this-&amp;gt;getGameStateValue(&#039;playerTeams&#039;)) {&lt;br /&gt;
			case $this-&amp;gt;TEAM_1_2:&lt;br /&gt;
				$playerOrder = [0, 2, 1, 3];&lt;br /&gt;
				break;&lt;br /&gt;
			case $this-&amp;gt;TEAM_1_4:&lt;br /&gt;
				$playerOrder = [0, 1, 3, 2];&lt;br /&gt;
				break;&lt;br /&gt;
			case $this-&amp;gt;TEAM_RANDOM:&lt;br /&gt;
				shuffle($playerOrder);&lt;br /&gt;
				break;&lt;br /&gt;
			default:&lt;br /&gt;
			case $this-&amp;gt;TEAM_1_3:&lt;br /&gt;
				// Default order&lt;br /&gt;
				break;&lt;br /&gt;
		}&lt;br /&gt;
&lt;br /&gt;
                // Create players&lt;br /&gt;
		// Note: if you added some extra field on &amp;quot;player&amp;quot; table in the database (dbmodel.sql), you can initialize it there.&lt;br /&gt;
		$sql =&lt;br /&gt;
			&#039;INSERT INTO player (player_id, player_color, player_canal, player_name, player_avatar, player_no) VALUES &#039;;&lt;br /&gt;
		$values = [];&lt;br /&gt;
&lt;br /&gt;
		foreach ($players as $playerId =&amp;gt; $player) {&lt;br /&gt;
			$color = array_shift($default_colors);&lt;br /&gt;
			$values[] =&lt;br /&gt;
				&amp;quot;(&#039;&amp;quot; .&lt;br /&gt;
				$playerId .&lt;br /&gt;
				&amp;quot;&#039;,&#039;$color&#039;,&#039;&amp;quot; .&lt;br /&gt;
				$player[&#039;player_canal&#039;] .&lt;br /&gt;
				&amp;quot;&#039;,&#039;&amp;quot; .&lt;br /&gt;
				addslashes($player[&#039;player_name&#039;]) .&lt;br /&gt;
				&amp;quot;&#039;,&#039;&amp;quot; .&lt;br /&gt;
				addslashes($player[&#039;player_avatar&#039;]) .&lt;br /&gt;
				&amp;quot;&#039;,&#039;&amp;quot; .&lt;br /&gt;
				$playerOrder[$playerInitialOrder[$playerId]] .&lt;br /&gt;
				&amp;quot;&#039;)&amp;quot;;&lt;br /&gt;
		}&lt;br /&gt;
		$sql .= implode(&#039;,&#039;, $values);&lt;br /&gt;
		$this-&amp;gt;DbQuery($sql);&lt;br /&gt;
		$this-&amp;gt;reattributeColorsBasedOnPreferences(&lt;br /&gt;
			$players,&lt;br /&gt;
			$gameinfos[&#039;player_colors&#039;]&lt;br /&gt;
		);&lt;br /&gt;
		$this-&amp;gt;reloadPlayersBasicInfos();&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Send different notifications to active player vs everybody else ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Ingredients:&#039;&#039;&#039; ggg.js&lt;br /&gt;
&lt;br /&gt;
Hack alert. This is a hack. We were hoping for proper solution by bga framework.&lt;br /&gt;
&lt;br /&gt;
This will allow you to send notification with two message one for specific player and one for everybody else including spectators.&lt;br /&gt;
Note that this does not split the data - all data must be shared.&lt;br /&gt;
&lt;br /&gt;
Add this to .js file (if you already overriding it merge obviously)&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
/** @Override */&lt;br /&gt;
format_string_recursive: function(log, args) {&lt;br /&gt;
   if (typeof args.log_others != &#039;undefined&#039; &amp;amp;&amp;amp; typeof args.player_id != &#039;undefined&#039; &amp;amp;&amp;amp; this.player_id != args.player_id)&lt;br /&gt;
	log = args.log_others;&lt;br /&gt;
   return this.inherited(arguments); // you must call this to call super &lt;br /&gt;
},&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Example of usage (from eminentdomain)&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    $this-&amp;gt;notifyAllPlayers(&#039;tokenMoved&#039;, &lt;br /&gt;
             clienttranslate(&#039;${player_name} adds +2 Colonies to ${place_name}&#039;), // notification with show for player with player_id&lt;br /&gt;
             [&#039;player_id&#039;=&amp;gt;$player_id, // this is mandatory&lt;br /&gt;
             &#039;log_others&#039;=&amp;gt;clienttranslate(&#039;${player_name} adds +2 Colonies to an unknown planet&#039;), // notification will show for others&lt;br /&gt;
              ...&lt;br /&gt;
             ]);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Send transient notifications without incrementing move ID ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Ingredients:&#039;&#039;&#039; ggg.php&lt;br /&gt;
&lt;br /&gt;
Hack alert. This is a hack.&lt;br /&gt;
&lt;br /&gt;
Use this if you need to send some transient notification that should not create a new move ID. The notification should be idempotent -- it should have no practical effect on the game state and would be &#039;&#039;&#039;safe to drop&#039;&#039;&#039; (e.g., it would not matter if a player never received this notification). For example, in a co-op game you want all players to see a real-time preview of some action, before the active player commits their turn.&lt;br /&gt;
&lt;br /&gt;
Doing this mainly affects the instant replay &amp;amp; archive modes. During replay, the BGA framework automatically inserts a 1.5-second pause between each &amp;quot;move&amp;quot;. With this hack, your transient notifications are not considered to be a &amp;quot;move&amp;quot;, so no pause gets added.&lt;br /&gt;
&lt;br /&gt;
; In ggg.php&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$this-&amp;gt;not_a_move_notification = true; // note: do not increase the move counter&lt;br /&gt;
$this-&amp;gt;notifyAllPlayers(&#039;cardsPreview&#039;, &#039;&#039;, $args);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note: you cannot have code that send notification or even changes state after this, and you cannot reset this variable back either because it only takes effect when you exit action handling function&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Assorted Stuff ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Out-of-turn actions: Un-pass ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Ingredients:&#039;&#039;&#039; ggg.js, ggg.game.php, ggg.action.php, states.inc.php&lt;br /&gt;
&lt;br /&gt;
In multiplayer game sometimes players passes but than they think more and want to un-Pass and redo their choice. &lt;br /&gt;
To re-active a player who passes some trickery required.&lt;br /&gt;
&lt;br /&gt;
Define a special action that does that and hook it up.&lt;br /&gt;
&lt;br /&gt;
In states.inc.php add an action to multipleactiveplayer state to &amp;quot;unpass&amp;quot;, lets call it &amp;quot;actionCancel&amp;quot;&lt;br /&gt;
&lt;br /&gt;
In ggg.action.php add action hook&lt;br /&gt;
    public function actionCancel() {&lt;br /&gt;
        $this-&amp;gt;setAjaxMode();&lt;br /&gt;
        $this-&amp;gt;game-&amp;gt;actionCancel();&lt;br /&gt;
        $this-&amp;gt;ajaxResponse();&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
In ggg.game.php add action handler&lt;br /&gt;
    function actionCancel() {&lt;br /&gt;
        $this-&amp;gt;gamestate-&amp;gt;checkPossibleAction(&#039;actionCancel&#039;);&lt;br /&gt;
        $this-&amp;gt;gamestate-&amp;gt;setPlayersMultiactive(array ($this-&amp;gt;getCurrentPlayerId() ), &#039;error&#039;, false);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
Finally to call this in client ggg.js you would do something like:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 onUpdateActionButtons:  function(stateName, args) {&lt;br /&gt;
   if (this.isCurrentPlayerActive()) { &lt;br /&gt;
     // ...&lt;br /&gt;
   } else if (!this.isSpectator) { // player is NOT active but not spectator&lt;br /&gt;
       switch (stateName) {&lt;br /&gt;
          case &#039;playerTurnMultiPlayerState&#039;:&lt;br /&gt;
		this.addActionButton(&#039;button_unpass&#039;, _(&#039;Oh no!&#039;), &#039;onUnpass&#039;);&lt;br /&gt;
		break;&lt;br /&gt;
	}&lt;br /&gt;
   }&lt;br /&gt;
 }&lt;br /&gt;
				&lt;br /&gt;
 onUnpass: function(e) {&lt;br /&gt;
    this.bgaPerformAction(&amp;quot;actionCancel&amp;quot;, null, { checkAction: false }); // no checkAction!&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Although be careful that if the turn comes back to the player while he is about to click cancel, the action buttons will be updated and the player will misclick which can be quite frustrating. To avoid this, move the cancel button to another position, like to the left of pagemaintitletext:&lt;br /&gt;
  dojo.place(&#039;button_unpass&#039;, &#039;pagemaintitletext&#039;, &#039;before&#039;);&lt;br /&gt;
Being out of the generalactions div, it won&#039;t be automatically destroyed like normal buttons, so you&#039;ll have to handle that yourself in onLeavingState. You might also want to change the button color to red (blue buttons for active player only, red buttons also for inactive players?)&lt;br /&gt;
&lt;br /&gt;
Note: same technique can be used to do other out-of-turn actions, such as re-arranging cards in hand, exchanging resources, etc (i.e. if permitted by rules, such as &amp;quot;at any time player can...&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
=== Multi Step Interactions: Select Worker/Place Worker - Using Selection ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Ingredients:&#039;&#039;&#039; ggg.js&lt;br /&gt;
&lt;br /&gt;
Simple way to implement something like that without extra states is to use &amp;quot;selection&amp;quot; mechanism. When user click on worker add some sort of class into that element i.e. &#039;selected&#039; (which also have to have some indication by css i.e. outline).&lt;br /&gt;
&lt;br /&gt;
Than user can click on placement zone, you can use dojo.query for &amp;quot;selected&amp;quot; element and use it along with zone id to send data to server. If proper worker is not selected yet can give a error message using this.showMessage(...) function.&lt;br /&gt;
&lt;br /&gt;
Extra code required to properly cleanup selection between states.&lt;br /&gt;
Also when you do that sometimes you want to change the state prompt, see below &#039;Change state prompt&#039;&lt;br /&gt;
&lt;br /&gt;
=== Multi Step Interactions: Select Worker/Place Worker - Using Client States ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Ingredients:&#039;&#039;&#039; ggg.js&lt;br /&gt;
&lt;br /&gt;
I don&#039;t think its documented feature but there is a way to do client-only states, which is absolutely wonderful for few reasons&lt;br /&gt;
* When player interaction is two step process, such as select worker, place worker, or place worker, pick one of two resources of your choice&lt;br /&gt;
* When multi-step process can result of impossible situation and has to be undone (by rules)&lt;br /&gt;
* When multi-step process is triggered from multiple states (such as you can do same thing as activated card action, pass action or main action)&lt;br /&gt;
&lt;br /&gt;
So lets do Select Worker/Place Worker&lt;br /&gt;
&lt;br /&gt;
Define your server state as usual, i.e. playerMainTurn -&amp;gt; &amp;quot;You must pick up a worker&amp;quot;.&lt;br /&gt;
Now define a client state, we only need &amp;quot;name&amp;quot; and &amp;quot;descriptionmyturn&amp;quot;, lets say &amp;quot;client_playerPicksLocation&amp;quot;. Always prefix names of client state with &amp;quot;client_&amp;quot; to avoid confusion. Now we have to do the following:&lt;br /&gt;
* Have a handler for onUpdateActionButtons for playerMainTurn to activate all possible workers he can pick&lt;br /&gt;
* When player clicks workers, remember the worker in one of the members of the main class, I usually use one called this.clientStateArgs.&lt;br /&gt;
* Transition to new client state&lt;br /&gt;
  onWorker: function(e) {&lt;br /&gt;
      var id = event.currentTarget.id;&lt;br /&gt;
      dojo.stopEvent(event);&lt;br /&gt;
      ... // do validity checks&lt;br /&gt;
      this.clientStateArgs.worker_id = id;&lt;br /&gt;
      this.setClientState(&amp;quot;client_playerPicksLocation&amp;quot;, {&lt;br /&gt;
                                descriptionmyturn : _(&amp;quot;${you} must select location&amp;quot;),&lt;br /&gt;
                            });&lt;br /&gt;
   }&lt;br /&gt;
* Have a handler for onUpdateActionButtons for client_playerPicksLocation to activate all possible locations this worker can go AND add Cancel button (see below)&lt;br /&gt;
* Have a location handler which will eventually send a server request, using stored this.clientStateArgs.worker_id as worker id&lt;br /&gt;
* The cancel button should call a method to restore server state, also if you doing it for more than one state you can add this universally using this.on_client_state check&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
        if (this.isCurrentPlayerActive()) {&lt;br /&gt;
          if (this.on_client_state &amp;amp;&amp;amp; !$(&#039;button_cancel&#039;)) {&lt;br /&gt;
               this.addActionButton(&#039;button_cancel&#039;, _(&#039;Cancel&#039;), dojo.hitch(this, function() {&lt;br /&gt;
                                             this.restoreServerGameState();&lt;br /&gt;
               }));&lt;br /&gt;
          }&lt;br /&gt;
        } &lt;br /&gt;
Note: usually I call my own function call this.cancelLocalStateEffects() which will do more stuff first then call restoreServerGameState(), same function is usually needs to be called when server request has failed (i.e. invalid move)&lt;br /&gt;
&lt;br /&gt;
Note: If you need more than 2 steps, you may have to do client side animation to reflect the new state, which gets trickier because you have to undo that also on cancellation.&lt;br /&gt;
&lt;br /&gt;
Code is available here [https://github.com/elaskavaia/bga-sharedcode/blob/master/sharedcode.js sharedcode.js] (its using playerTurnPlayCubes and client_selectCubeLocation).&lt;br /&gt;
&lt;br /&gt;
=== Action Stack - Using Client States ===&lt;br /&gt;
&lt;br /&gt;
Action stack required where game is very complex and use triggered effects that can &amp;quot;stack&amp;quot;. It not always actual stack, it can be queue or random access.&lt;br /&gt;
&lt;br /&gt;
Examples:&lt;br /&gt;
* Magic the Gathering - classic card game where effects go on Stack, that allows to counter spell and counter spell of counter spell (not on bga - it just example of mechanics)&lt;br /&gt;
* Ultimate Railroads - action taking game where effects can be executed in any order&lt;br /&gt;
* Lewis and Clark - card game where actions executed as queue&lt;br /&gt;
&lt;br /&gt;
There is two ways of implementing it - on the server or the client.&lt;br /&gt;
For the server see article below.&lt;br /&gt;
The requirement for client side stack implementation is - all action can be undone, which means&lt;br /&gt;
* No dice rolls&lt;br /&gt;
* No card drawn&lt;br /&gt;
* No other players interaction&lt;br /&gt;
&lt;br /&gt;
No snippets are here, as this will be too complex but basically flow is:&lt;br /&gt;
* You have a action/effect stack (queue/list) as js object attached to &amp;quot;this&amp;quot;, i.e. this.unprocessed_actions&lt;br /&gt;
* When player plays a card, worker, etc, you read the effect of that card from the material file (client copy), and place into stack&lt;br /&gt;
* Then we call dispatch method which pulls the next action from the stack and change client state accordinly, i.e. this.setClientState(&amp;quot;client_playerGainsCubes&amp;quot;)&lt;br /&gt;
* When players acts on it - the action is removed from the stack and added to &amp;quot;server action arguments&amp;quot; list, this is another object which be used to send ajax call, i.e. this.clientStateArgs&lt;br /&gt;
* If nothing left in stack we can submit the ajax call assembling parameters from collected arguments (that can include action name)&lt;br /&gt;
* This method allows cheap undo - by restoring server state you will wipe out all user actions (but if you need intermediate aninmation you have to handle it yourself)&lt;br /&gt;
&lt;br /&gt;
Code can be found in Ultimate Railroads game (but it is random access list - so it a bit complex) and Lewis and Clark (complexity - user can always deny part of any effect)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Action Stack - Using Server States ===&lt;br /&gt;
&lt;br /&gt;
See definition of Action Stack above.&lt;br /&gt;
&lt;br /&gt;
To implement you usually need another db table that has the following fields: index of effect - which is used for sorted access, type - which is essense of the effect (i.e. collect resource), some extra arguments (i.e. resource type and resource count), and usually owner of the effect (i.e. player id)&lt;br /&gt;
The flow is:&lt;br /&gt;
* There is some initial player state, where player can play card for example&lt;br /&gt;
* Player main action - pushes the card effect on stack, which also can cause triggered effects which also go on stack&lt;br /&gt;
* After action processing is finished switch to game state which is &amp;quot;dispatcher&amp;quot;&lt;br /&gt;
* Dispatcher pulls the top effect (whatever definition of the top is), changes the active player and changes the state to appropriate player state to collect response. The &amp;quot;top&amp;quot; can be choice of multiple actions, in this case player has to chose one before resolving the effect.&lt;br /&gt;
* Player state knows about the stack and pulls arguments (argX) from the effect arguments of the db&lt;br /&gt;
* Player action should clear up the top effect, and can possibly add more effects, then switch to &amp;quot;dispatcher&amp;quot; state again&lt;br /&gt;
* If stack is empty, dispatcher can either pick next player itself or use another game state which responsible for picking next player&lt;br /&gt;
&lt;br /&gt;
Code can be found in Tapestry and Terraforming Mars.&lt;br /&gt;
=== Custom error/exception handling in JavaScript ===&lt;br /&gt;
&lt;br /&gt;
; In ggg.php&lt;br /&gt;
Throw BgaUserException with some easy-to-identify prefix such as &amp;quot;!!!&amp;quot; and a custom error code. DO NOT TRANSLATE this message text. The exception will rollback database transaction and cancel all changes (including any notifications).&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    function foo(bool $didConfirm = false): void&lt;br /&gt;
    {&lt;br /&gt;
        // do processing for the user&#039;s move&lt;br /&gt;
        // afterwards, you determine this move will end the game&lt;br /&gt;
        // so you want to rollback the transaction and require the user to confirm the move first&lt;br /&gt;
&lt;br /&gt;
        if ($gameIsEnding &amp;amp;&amp;amp; !$didConfirm) {&lt;br /&gt;
            throw new BgaUserException(&#039;!!!endGameConfirm&#039;, 9001);&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
; In ggg.js&lt;br /&gt;
Override framework function showMessage to suppress the red banner message and gamelog message when you detect the &amp;quot;!!!&amp;quot; prefix&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    /* @Override */&lt;br /&gt;
    showMessage: function (msg, type) {&lt;br /&gt;
      if (type == &amp;quot;error&amp;quot; &amp;amp;&amp;amp; msg &amp;amp;&amp;amp; msg.startsWith(&amp;quot;!!!&amp;quot;)) {&lt;br /&gt;
        return; // suppress red banner and gamelog message&lt;br /&gt;
      }&lt;br /&gt;
      this.inherited(arguments);&lt;br /&gt;
    },&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Deal with the error in your callback:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    fooAction: function (didConfirm) {&lt;br /&gt;
      var data = {&lt;br /&gt;
        foo: &amp;quot;bar&amp;quot;,&lt;br /&gt;
        didConfirm: !!didConfirm,&lt;br /&gt;
      };&lt;br /&gt;
      this.bgaPerformAction(&amp;quot;fooAction&amp;quot;, data).catch((error, errorMsg) =&amp;gt; {&lt;br /&gt;
        if (error &amp;amp;&amp;amp; errorMsg == &amp;quot;!!!endGameConfirm&amp;quot;) {&lt;br /&gt;
          // your custom error handling goes here&lt;br /&gt;
          // for example, show a confirmation dialog and repeat the action with additional param&lt;br /&gt;
          this.confirmationDialog(&lt;br /&gt;
            _(&amp;quot;Doing the foo action now will end the game&amp;quot;),&lt;br /&gt;
            () =&amp;gt; this.fooAction(true)&lt;br /&gt;
          );&lt;br /&gt;
        }&lt;br /&gt;
      });&lt;br /&gt;
    },&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
For custom global error handling, you could modify ajaxcallwrapper:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  ajaxcallwrapper: function (action, args, handler) {&lt;br /&gt;
    if (!args) args = {};&lt;br /&gt;
    args.lock = true;&lt;br /&gt;
    args.version = this.gamedatas.version;&lt;br /&gt;
    if (this.checkAction(action)) {&lt;br /&gt;
      this.bgaPerformAction(&lt;br /&gt;
        action,&lt;br /&gt;
        args&lt;br /&gt;
      ).catch((error, errorMsg, errorCode) =&amp;gt; {&lt;br /&gt;
          if (error &amp;amp;&amp;amp; errorMsg == &amp;quot;!!!checkVersion&amp;quot;) {&lt;br /&gt;
            this.infoDialog(&lt;br /&gt;
              _(&amp;quot;A new version of this game is now available&amp;quot;),&lt;br /&gt;
              _(&amp;quot;Reload Required&amp;quot;),&lt;br /&gt;
              () =&amp;gt; {&lt;br /&gt;
                window.location.reload();&lt;br /&gt;
              },&lt;br /&gt;
              true&lt;br /&gt;
            );&lt;br /&gt;
          } else {&lt;br /&gt;
            if (handler) handler(error, errorMsg, errorCode);&lt;br /&gt;
          }&lt;br /&gt;
        }&lt;br /&gt;
      );&lt;br /&gt;
    }&lt;br /&gt;
  },&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Force players to refresh after new deploy ===&lt;br /&gt;
&lt;br /&gt;
When you deploy a new version of your game, the PHP backend code is immediately updated but the JavaScript/HTML/CSS frontend code *does not update* for active players until they manually refresh the page (F5) in their browser. Obviously this is not ideal. In the best case, real-time tables don&#039;t see your shiny new enhancements. In the worst case, your old JS code isn&#039;t compatible with your new PHP code and the game breaks in strange ways (any bug reports filed will be false positives and unable to reproduce). To avoid any problems, you should force all players to immediately reload the page following a new deploy.&lt;br /&gt;
&lt;br /&gt;
By throwing a &amp;quot;visible&amp;quot; exception (simplest solution), you&#039;ll get something like this which instructs the user to reload:&lt;br /&gt;
&lt;br /&gt;
[[File:Force-refresh.png|950x950px]]&lt;br /&gt;
&lt;br /&gt;
Or, if you combine this technique with the above custom error handling technique, you could do something a bit nicer. You could show a dialog box and automatically refresh the page when the user clicks &amp;quot;OK&amp;quot;:&lt;br /&gt;
&lt;br /&gt;
[[File:Reload-required.png|500x500px]]&lt;br /&gt;
; In ggg.php&lt;br /&gt;
Transmit the server version number in &amp;lt;code&amp;gt;getAllDatas()&amp;lt;/code&amp;gt;.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    protected function getAllDatas(): array&lt;br /&gt;
    {&lt;br /&gt;
        $players = $this-&amp;gt;getCollectionFromDb(&amp;quot;SELECT player_id id, player_score score FROM player&amp;quot;);&lt;br /&gt;
        return [&lt;br /&gt;
            &#039;players&#039; =&amp;gt; $players,&lt;br /&gt;
            &#039;version&#039; =&amp;gt; intval($this-&amp;gt;gamestate-&amp;gt;table_globals[300]), // &amp;lt;-- ADD HERE&lt;br /&gt;
            ...&lt;br /&gt;
        ];&lt;br /&gt;
    }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Create a helper function to fail if the client and server versions mismatch. Note the version check uses &amp;lt;code&amp;gt;!=&amp;lt;/code&amp;gt; instead of &amp;lt;code&amp;gt;&amp;amp;lt;&amp;lt;/code&amp;gt; so it can support rollback to a previous deploy as well. ;-)&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    public function checkVersion(int $clientVersion): void&lt;br /&gt;
    {&lt;br /&gt;
        if ($clientVersion != intval($this-&amp;gt;gamestate-&amp;gt;table_globals[300])) {&lt;br /&gt;
            // Simplest way is to throw a &amp;quot;visible&amp;quot; exception&lt;br /&gt;
            // It&#039;s ugly but comes with a &amp;quot;click here&amp;quot; link to refresh&lt;br /&gt;
            throw new BgaVisibleSystemException($this-&amp;gt;_(&amp;quot;A new version of this game is now available. Please reload the page (F5).&amp;quot;));&lt;br /&gt;
&lt;br /&gt;
            // For something prettier, throw a &amp;quot;user&amp;quot; exception and handle in JS&lt;br /&gt;
            // (see BGA cookbook section above on custom error handling)&lt;br /&gt;
            throw new BgaUserException(&#039;!!!checkVersion&#039;);&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
; In ggg.action.php&lt;br /&gt;
Create a helper function for actions:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  private function checkVersion()&lt;br /&gt;
  {&lt;br /&gt;
    $clientVersion = (int) $this-&amp;gt;getArg(&#039;version&#039;, AT_int, false);&lt;br /&gt;
    $this-&amp;gt;game-&amp;gt;checkVersion($clientVersion);&lt;br /&gt;
  }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Call &amp;lt;code&amp;gt;$this-&amp;gt;checkVersion()&amp;lt;/code&amp;gt; at the top of &amp;lt;b&amp;gt;every action function&amp;lt;/b&amp;gt;, immediately after &amp;lt;code&amp;gt;$this-&amp;gt;setAjaxMode()&amp;lt;/code&amp;gt;:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  public function move()&lt;br /&gt;
  {&lt;br /&gt;
    $this-&amp;gt;setAjaxMode();&lt;br /&gt;
    $this-&amp;gt;checkVersion(); // &amp;lt;-- ADD HERE&lt;br /&gt;
    ...&lt;br /&gt;
    $this-&amp;gt;ajaxResponse();&lt;br /&gt;
  }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
; In ggg.js&lt;br /&gt;
Transmit the version (from gamedatas) as a parameter with every ajax call. For example, if you&#039;re already using a wrapper function for every ajax call, add it like this:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  ajaxcallwrapper: function (action, args) {&lt;br /&gt;
    if (!args) args = {};&lt;br /&gt;
    args.version = this.gamedatas.version; // &amp;lt;-- ADD HERE&lt;br /&gt;
    this.bgaPerformAction(action, args);&lt;br /&gt;
  },&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Disable / lock table creation for new deploy ===&lt;br /&gt;
&lt;br /&gt;
If you are deploying a major new game version, especially if it involves upgrading production game databases, you may have a lot of angry players if you break their tables.  Depending on your changes, you may be able to restore the previous version and fix the tables easily.&lt;br /&gt;
&lt;br /&gt;
However, if a new deploy turns out bad and players created turn-based tables while it was live, it may be quite difficult to fix those tables, since they were created from a bad deploy.&lt;br /&gt;
&lt;br /&gt;
The solution?  You can announce in your game group that you are locking table creation, and then in your new version, add an impossible startcondition to an existing option.  &lt;br /&gt;
Note: This only makes sense if you have a few games running in real time mode in the time of deployment, otherwise it won&#039;t achieve much, unless you wait at least a day for other turn based games to break (or not)&lt;br /&gt;
&lt;br /&gt;
Here is an example of an option with only 2 values (if you don&#039;t have options at all you have to create a fake option to use this method, if you have more values - you have to list them all):&lt;br /&gt;
&lt;br /&gt;
; In gameoptions.json&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        &amp;quot;startcondition&amp;quot;: {&lt;br /&gt;
            &amp;quot;0&amp;quot;: [ { &amp;quot;type&amp;quot;: &amp;quot;minplayers&amp;quot;, &amp;quot;value&amp;quot;: 32, &amp;quot;message&amp;quot;: &amp;quot;Maintenance in progress.  Table creation is disabled.&amp;quot; } ],&lt;br /&gt;
            &amp;quot;1&amp;quot;: [ { &amp;quot;type&amp;quot;: &amp;quot;minplayers&amp;quot;, &amp;quot;value&amp;quot;: 32, &amp;quot;message&amp;quot;: &amp;quot;Maintenance in progress.  Table creation is disabled.&amp;quot; } ]&lt;br /&gt;
        },&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
; In gameoptions.inc.php (older method if you have it in php)&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
// TODO NEXT remove after testing deploy to upgrade, here 0 and 1 - replace with values of your option!&lt;br /&gt;
&#039;startcondition&#039; =&amp;gt; [&lt;br /&gt;
   0 =&amp;gt; [ [ &#039;type&#039; =&amp;gt; &#039;minplayers&#039;, &#039;value&#039; =&amp;gt; 32, &#039;message&#039; =&amp;gt; totranslate(&#039;Maintenance in progress.  Table creation is disabled.&#039;) ] ],&lt;br /&gt;
   1 =&amp;gt; [ [ &#039;type&#039; =&amp;gt; &#039;minplayers&#039;, &#039;value&#039; =&amp;gt; 32, &#039;message&#039; =&amp;gt; totranslate(&#039;Maintenance in progress.  Table creation is disabled.&#039;) ] ],&lt;br /&gt;
],&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Be sure to click &amp;quot;Reload game options configuration&amp;quot; after making this change, then test in studio (test that you cannot create any table)&lt;br /&gt;
* Deploy to production&lt;br /&gt;
* Now, when a player attempts to create a new table, they will see a red error bar with your &amp;quot;Maintenance in progress&amp;quot; message.  &lt;br /&gt;
* Wait for screaming (if you have real times games in progress waiting 15 min probably ok, if you have only turn based games, probably a day)&lt;br /&gt;
* Once you confirm the new deploy looks good, you can revert the change in gameoptions.inc.php and do another deploy.&lt;br /&gt;
&lt;br /&gt;
=== Local Storage ===&lt;br /&gt;
&lt;br /&gt;
There is not much you can store in localStorage (https://developer.mozilla.org/docs/Web/API/Window/localStorage), since most stuff should be stored either in game db or in user prefrences,&lt;br /&gt;
but some stuff makes sense to store there, for example &amp;quot;zoom&amp;quot; level (if you use custom zooming). This setting really affect this specific host and specific browser, setting it localStorage makes most sense.&lt;br /&gt;
&lt;br /&gt;
game.js&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
   setup: function (gamedatas) {&lt;br /&gt;
        let zoom = localStorage.getItem(`${this.game_name}_zoom`);&lt;br /&gt;
        this.setZoom(zoom);&lt;br /&gt;
...&lt;br /&gt;
   },&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
In this case setZoom is custom function to actually set it.&lt;br /&gt;
When zoom changed, for example when some buttons pressed, store current value (but sanitize it so it never so bad that game cannot be viewed&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    setZoom: function (zoom) {&lt;br /&gt;
      zoom = parseInt(zoom) || 0;&lt;br /&gt;
      if (zoom === 0 || zoom &amp;lt; 0.1 || zoom &amp;gt; 10) {&lt;br /&gt;
        zoom = 1;&lt;br /&gt;
      }&lt;br /&gt;
      this.zoom = zoom;&lt;br /&gt;
      localStorage.setItem(`${this.game_name}_zoom`, &amp;quot;&amp;quot; + this.zoom);&lt;br /&gt;
... do actual zooming stuff&lt;br /&gt;
    },&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Capture client JavaScript errors in the &amp;quot;unexpected error&amp;quot; log ===&lt;br /&gt;
&lt;br /&gt;
PHP (backend) errors are recorded in the &amp;quot;unexpected error&amp;quot; log, but JavaScript (frontend) errors are only available in the browser itself. This means you have no visibility about things that go wrong in the client... unless you make clients report their errors to the server.&lt;br /&gt;
&lt;br /&gt;
; In actions.php:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  public function jsError()&lt;br /&gt;
  {&lt;br /&gt;
    $this-&amp;gt;setAjaxMode(false);&lt;br /&gt;
    $this-&amp;gt;game-&amp;gt;jsError($_POST[&#039;userAgent&#039;], $_POST[&#039;msg&#039;]);&lt;br /&gt;
    $this-&amp;gt;ajaxResponse();&lt;br /&gt;
  }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
; In game.php:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    public function jsError($userAgent, $msg): void&lt;br /&gt;
    {&lt;br /&gt;
        $this-&amp;gt;error(&amp;quot;JavaScript error from User-Agent: $userAgent\n$msg // &amp;quot;);&lt;br /&gt;
    }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
; In game.js:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
define([&amp;quot;dojo&amp;quot;, &amp;quot;dojo/_base/declare&amp;quot;, &amp;quot;ebg/core/gamegui&amp;quot;, &amp;quot;ebg/counter&amp;quot;], function (dojo, declare) {&lt;br /&gt;
  const uniqJsError = {};&lt;br /&gt;
  ...&lt;br /&gt;
&lt;br /&gt;
  return declare(&amp;quot;bgagame.nowboarding&amp;quot;, ebg.core.gamegui, {&lt;br /&gt;
    ...&lt;br /&gt;
    /* @Override */&lt;br /&gt;
    onScriptError(msg) {&lt;br /&gt;
      if (!uniqJsError[msg]) {&lt;br /&gt;
        uniqJsError[msg] = true;&lt;br /&gt;
        console.error(&amp;quot;⛔ Reporting JavaScript error&amp;quot;, msg);&lt;br /&gt;
        this.ajaxcall(&lt;br /&gt;
          &amp;quot;/&amp;quot; + this.game_name + &amp;quot;/&amp;quot; + this.game_name + &amp;quot;/jsError.html&amp;quot;,&lt;br /&gt;
          {&lt;br /&gt;
            msg,&lt;br /&gt;
            userAgent: navigator.userAgent,&lt;br /&gt;
          },&lt;br /&gt;
          this,&lt;br /&gt;
          () =&amp;gt; {},&lt;br /&gt;
          () =&amp;gt; {},&lt;br /&gt;
          &amp;quot;post&amp;quot;&lt;br /&gt;
        );&lt;br /&gt;
      }&lt;br /&gt;
      this.inherited(arguments);&lt;br /&gt;
    },&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Algorithms ==&lt;br /&gt;
&lt;br /&gt;
=== Generate permutations in lexicographic order ===&lt;br /&gt;
&lt;br /&gt;
Use this when you have an array like [1, 2, 3, 4] and need to loop over some/all 24 permutations of possible ordering. This type of [https://www.php.net/manual/en/language.generators.syntax.php generator function] computes each possibility one at a time, making it vastly more efficient than either a normal iteration or recursive function that produce all possibilities up front.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
function generatePermutations(array $array): Generator&lt;br /&gt;
{&lt;br /&gt;
    // https://en.wikipedia.org/wiki/Permutation#Generation_in_lexicographic_order&lt;br /&gt;
    // Sort the array and this is the first permutation&lt;br /&gt;
    sort($array);&lt;br /&gt;
    yield $array;&lt;br /&gt;
&lt;br /&gt;
    $count = count($array);&lt;br /&gt;
    do {&lt;br /&gt;
        // Find the largest index k where a[k] &amp;lt; a[k + 1]&lt;br /&gt;
        // End when no such index exists&lt;br /&gt;
        $found = false;&lt;br /&gt;
        for ($k = $count - 2; $k &amp;gt;= 0; $k--) {&lt;br /&gt;
            $kvalue = $array[$k];&lt;br /&gt;
            $knext = $array[$k + 1];&lt;br /&gt;
            if ($kvalue &amp;lt; $knext) {&lt;br /&gt;
                // Find the largest index l greater than k where a[k] &amp;lt; a[l]&lt;br /&gt;
                for ($l = $count - 1; $l &amp;gt; $k; $l--) {&lt;br /&gt;
                    $lvalue = $array[$l];&lt;br /&gt;
                    if ($kvalue &amp;lt; $lvalue) {&lt;br /&gt;
                        // Swap a[k] and a[l]&lt;br /&gt;
                        [$array[$k], $array[$l]] = [$array[$l], $array[$k]];&lt;br /&gt;
&lt;br /&gt;
                        // Reverse the sequence from a[k + 1] up to and including the final element&lt;br /&gt;
                        $reverse = array_reverse(array_slice($array, $k + 1));&lt;br /&gt;
                        array_splice($array, $k + 1, $count, $reverse);&lt;br /&gt;
                        yield $array;&lt;br /&gt;
&lt;br /&gt;
                        // Restart with the new array to find the next permutation&lt;br /&gt;
                        $found = true;&lt;br /&gt;
                        break 2;&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    } while ($found);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Usage:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$cash = [4, 1, 2, 3, 4];&lt;br /&gt;
foreach ($this-&amp;gt;generatePermutations($cash) as $p) {&lt;br /&gt;
    // your code here to evaluate permutation $p&lt;br /&gt;
    // first iteration: $p = [1, 2, 3, 4, 4]&lt;br /&gt;
    // last (60th) iteration: $p = [4, 4, 3, 2, 1]&lt;br /&gt;
    // break from loop once you achieve your goal&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Category:Studio]]&lt;/div&gt;</summary>
		<author><name>Sguzzer Gunayer</name></author>
	</entry>
	<entry>
		<id>https://en.doc.boardgamearena.com/index.php?title=BGA_Studio_Cookbook&amp;diff=22706</id>
		<title>BGA Studio Cookbook</title>
		<link rel="alternate" type="text/html" href="https://en.doc.boardgamearena.com/index.php?title=BGA_Studio_Cookbook&amp;diff=22706"/>
		<updated>2024-09-24T14:37:28Z</updated>

		<summary type="html">&lt;p&gt;Sguzzer Gunayer: /* Assorted Stuff */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;br /&gt;
&lt;br /&gt;
This page is a cookbook of design and implementation recipes for BGA Studio framework.&lt;br /&gt;
For tooling and usage recipes see [[Tools and tips of BGA Studio]].&lt;br /&gt;
If you have your own recipes feel free to edit this page.&lt;br /&gt;
&lt;br /&gt;
__TOC__&lt;br /&gt;
&lt;br /&gt;
== Visual Effects, Layout and Animation ==&lt;br /&gt;
&lt;br /&gt;
=== DOM manipulatons ===&lt;br /&gt;
&lt;br /&gt;
==== Create pieces dynamically (using template) ====&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Ingredients:&#039;&#039;&#039; ggg_ggg.tpl, ggg.js&lt;br /&gt;
&lt;br /&gt;
Note: this method is recommended by BGA guildlines&lt;br /&gt;
&lt;br /&gt;
Declared js template with variables in .tpl file, like this&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;script type=&amp;quot;text/javascript&amp;quot;&amp;gt;&lt;br /&gt;
    // Javascript HTML templates&lt;br /&gt;
    var jstpl_ipiece = &#039;&amp;lt;div class=&amp;quot;${type} ${type}_${color} inlineblock&amp;quot; aria-label=&amp;quot;${name}&amp;quot; title=&amp;quot;${name}&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&#039;;&lt;br /&gt;
&amp;lt;/script&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Use it like this in .js file&lt;br /&gt;
  div = this.format_block(&#039;jstpl_ipiece&#039;, {&lt;br /&gt;
                                type : &#039;meeple&#039;,&lt;br /&gt;
                                color : &#039;ff0000&#039;,&lt;br /&gt;
                                name : &#039;Bob&#039;,&lt;br /&gt;
                            });&lt;br /&gt;
  &lt;br /&gt;
Then you do whatever you need to do with that div, this one specifically design to go to log entries, because it has embedded title (otherwise its a picture only) and no id.&lt;br /&gt;
&lt;br /&gt;
Note: you could have place this variable in js itself, but keeping it in .tpl allows you to have your js code be free of HTML. Normally it never happens but&lt;br /&gt;
it is good to strive for it.&lt;br /&gt;
Note: you can also use string concatenation, its less readable. You can also use dojo dom object creation api&#039;s but its brutally verbose and its more unreadable.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Create pieces dynamically (using string concatenation) ====&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Ingredients:&#039;&#039;&#039; ggg.js&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  div = &amp;quot;&amp;lt;div class=&#039;meeple_&amp;quot;+color+&amp;quot;&#039;&amp;gt;&amp;lt;/div&amp;gt;&amp;quot;;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
or modern way&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  div = `&amp;lt;div class=&#039;meeple_${color}&#039;&amp;gt;&amp;lt;/div&amp;gt;`;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Create all pieces statically ====&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Ingredients:&#039;&#039;&#039; ggg_ggg.tpl, ggg.css, ggg.view.php (optional) &lt;br /&gt;
&lt;br /&gt;
* Create ALL game pieces in html template (.tpl)&lt;br /&gt;
* ALL pieces should have unique id, and it should be meaningful, i.e. meeple_red_1&lt;br /&gt;
* Do not use inline styling&lt;br /&gt;
* Id of player&#039;s specific pieces should use some sort of &#039;color&#039; identification, since player id cannot be used in static layout, you can use english color name, hex 6 char value, or color &amp;quot;number&amp;quot; (1,2,3...)&lt;br /&gt;
* Pieces should have separated class for its color, type, etc, so it can be easily styled in groups. In example below you now can style all meeples, all red meeples or all red tokens, or all &amp;quot;first&amp;quot; meeples&lt;br /&gt;
&lt;br /&gt;
ggg.tpl:&lt;br /&gt;
&amp;lt;pre&amp;gt; &lt;br /&gt;
  &amp;lt;div id=&amp;quot;home_red&amp;quot; class=&amp;quot;home_red home&amp;quot;&amp;gt;&lt;br /&gt;
     &amp;lt;div id=&amp;quot;meeple_red_1&amp;quot; class=&amp;quot;meeple red n1&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
     &amp;lt;div id=&amp;quot;meeple_red_2&amp;quot; class=&amp;quot;meeple red n2&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
  &amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
ggg.css:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
.meeple {&lt;br /&gt;
	width: 32px;&lt;br /&gt;
	height: 39px;&lt;br /&gt;
	background-image: url(img/78_64_stand_meeples.png);&lt;br /&gt;
	background-size: 352px;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.meeple.red {&lt;br /&gt;
	background-position: 30% 0%;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* There should be straight forward mapping between server id and js id (or 1:1)&lt;br /&gt;
* You place objects in different zones of the layout, and setup css to take care of layout&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
.home .meeple{&lt;br /&gt;
   display: inline-block;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
* If you need to have a temporary object that look like original you can use dojo.clone (and change id to some temp id)&lt;br /&gt;
* If there is lots of repetition or zone grid you can use template generator, but inject style declaration in css instead of inline style for flexibility&lt;br /&gt;
&lt;br /&gt;
Note:&lt;br /&gt;
* If you use this model you cannot use premade js components such as Stock and Zone&lt;br /&gt;
* You have to use alternative methods of animation (slightly altered) since default method will leave object with inline style attributes which you don&#039;t need&lt;br /&gt;
&lt;br /&gt;
==== Use player color in template ====&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Ingredients:&#039;&#039;&#039; ggg_ggg.tpl, ggg.view.php&lt;br /&gt;
&lt;br /&gt;
.view.php:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    function build_page($viewArgs) {&lt;br /&gt;
        // Get players &amp;amp; players number&lt;br /&gt;
        $players = $this-&amp;gt;game-&amp;gt;loadPlayersBasicInfos();&lt;br /&gt;
        $players_nbr = count($players);&lt;br /&gt;
        /**&lt;br /&gt;
         * ********* Place your code below: ***********&lt;br /&gt;
         */&lt;br /&gt;
        &lt;br /&gt;
        // Set PCOLOR to the current player color hex&lt;br /&gt;
        global $g_user;&lt;br /&gt;
        $cplayer = $g_user-&amp;gt;get_id();&lt;br /&gt;
        if (array_key_exists($cplayer, $players)) { // may be not set if spectator&lt;br /&gt;
            $player_color = $players [$cplayer] [&#039;player_color&#039;];&lt;br /&gt;
        } else {&lt;br /&gt;
            $player_color = &#039;ffffff&#039;; // spectator&lt;br /&gt;
        }&lt;br /&gt;
        $this-&amp;gt;tpl [&#039;PCOLOR&#039;] = $player_color;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Status bar ===&lt;br /&gt;
&lt;br /&gt;
==== Changing state prompt ====&lt;br /&gt;
&lt;br /&gt;
State prompt is message displayed for player which usually comes from state description.&lt;br /&gt;
Sometimes you want to change it without changing state (one way is change state but locally, see client states above).&lt;br /&gt;
&lt;br /&gt;
Simple way just change the html&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        setMainTitle: function(text) {&lt;br /&gt;
            $(&#039;pagemaintitletext&#039;).innerHTML = text;&lt;br /&gt;
        },&lt;br /&gt;
         // usage&lt;br /&gt;
        onMeeple: function(event) {&lt;br /&gt;
              //... &lt;br /&gt;
              this.setMainTitle(_(&#039;You must select where meeple is going&#039;));&lt;br /&gt;
        },&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This however will not work with parameters and will not draw You in color, if you want this its more sophisticated:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        setDescriptionOnMyTurn : function(text) {&lt;br /&gt;
            this.gamedatas.gamestate.descriptionmyturn = text;&lt;br /&gt;
            var tpl = dojo.clone(this.gamedatas.gamestate.args);&lt;br /&gt;
            if (tpl === null) {&lt;br /&gt;
                tpl = {};&lt;br /&gt;
            }&lt;br /&gt;
            var title = &amp;quot;&amp;quot;;&lt;br /&gt;
            if (this.isCurrentPlayerActive() &amp;amp;&amp;amp; text !== null) {&lt;br /&gt;
                tpl.you = this.divYou(); &lt;br /&gt;
            }&lt;br /&gt;
            title = this.format_string_recursive(text, tpl);&lt;br /&gt;
&lt;br /&gt;
            if (!title) {&lt;br /&gt;
                this.setMainTitle(&amp;quot;&amp;amp;nbsp;&amp;quot;);&lt;br /&gt;
            } else {&lt;br /&gt;
                this.setMainTitle(title);&lt;br /&gt;
            }&lt;br /&gt;
        },&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note: this method uses &#039;&#039;&#039;setMainTitle&#039;&#039;&#039; defined above and &#039;&#039;&#039;divYou&#039;&#039;&#039; defined in another section of this wiki.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Animation ===&lt;br /&gt;
&lt;br /&gt;
==== Attach to new parent without destroying the object ====&lt;br /&gt;
&lt;br /&gt;
BGA function attachToNewParent for some reason destroys the original, if you want similar function that does not you can use this&lt;br /&gt;
ggg.js&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        /**&lt;br /&gt;
         * This method will attach mobile to a new_parent without destroying, unlike original attachToNewParent which destroys mobile and&lt;br /&gt;
         * all its connectors (onClick, etc)&lt;br /&gt;
         */&lt;br /&gt;
        attachToNewParentNoDestroy: function (mobile_in, new_parent_in, relation, place_position) {&lt;br /&gt;
&lt;br /&gt;
            const mobile = $(mobile_in);&lt;br /&gt;
            const new_parent = $(new_parent_in);&lt;br /&gt;
&lt;br /&gt;
            var src = dojo.position(mobile);&lt;br /&gt;
            if (place_position)&lt;br /&gt;
                mobile.style.position = place_position;&lt;br /&gt;
            dojo.place(mobile, new_parent, relation);&lt;br /&gt;
            mobile.offsetTop;//force re-flow&lt;br /&gt;
            var tgt = dojo.position(mobile);&lt;br /&gt;
            var box = dojo.marginBox(mobile);&lt;br /&gt;
            var cbox = dojo.contentBox(mobile);&lt;br /&gt;
            var left = box.l + src.x - tgt.x;&lt;br /&gt;
            var top = box.t + src.y - tgt.y;&lt;br /&gt;
&lt;br /&gt;
            mobile.style.position = &amp;quot;absolute&amp;quot;;&lt;br /&gt;
            mobile.style.left = left + &amp;quot;px&amp;quot;;&lt;br /&gt;
            mobile.style.top = top + &amp;quot;px&amp;quot;;&lt;br /&gt;
            box.l += box.w - cbox.w;&lt;br /&gt;
            box.t += box.h - cbox.h;&lt;br /&gt;
            mobile.offsetTop;//force re-flow&lt;br /&gt;
            return box;&lt;br /&gt;
        },&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Animation on oversurface ====&lt;br /&gt;
If you use non-absolute position for your game elements (i.e you use layouts) - you cannot really use BGA animation functions. After years of fidding with different options I use&lt;br /&gt;
techique which I call animation on oversurface that works when parents use different zoom, rotation, etc&lt;br /&gt;
&lt;br /&gt;
* You need another layer on top of everything - oversurface&lt;br /&gt;
* We create copy of the object on oversurface - to move&lt;br /&gt;
* We move the real object on final position - but make it invisible for now&lt;br /&gt;
* We move the phantom to final position applying required zoom and rotation (using css animation), then destroy it&lt;br /&gt;
* When animation is done we make original object visible in new position&lt;br /&gt;
&lt;br /&gt;
The code is bit complex it can be found here&lt;br /&gt;
&lt;br /&gt;
https://codepen.io/VictoriaLa/pen/gORvdJo&lt;br /&gt;
&lt;br /&gt;
Game using it: century, ultimaterailroads&lt;br /&gt;
&lt;br /&gt;
==== Scroll element into view ====&lt;br /&gt;
Ingredients: game.js&lt;br /&gt;
&lt;br /&gt;
This function will scroll given node (div) into view and respect replays and archive mode&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    scrollIntoViewAfter: function (node, delay) {&lt;br /&gt;
      if (this.instantaneousMode || this.inSetup) {&lt;br /&gt;
        return;&lt;br /&gt;
      }&lt;br /&gt;
      if (typeof g_replayFrom != &amp;quot;undefined&amp;quot;) {&lt;br /&gt;
        $(node).scrollIntoView();&lt;br /&gt;
        return;&lt;br /&gt;
      }&lt;br /&gt;
      if (!delay) delay = 0;&lt;br /&gt;
      setTimeout(() =&amp;gt; {&lt;br /&gt;
        $(node).scrollIntoView({ behavior: &amp;quot;smooth&amp;quot;, block: &amp;quot;center&amp;quot; });&lt;br /&gt;
      }, delay);&lt;br /&gt;
    },&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Logs ===&lt;br /&gt;
&lt;br /&gt;
==== Inject icon images in the log ====&lt;br /&gt;
&lt;br /&gt;
Here is an example of what was done for Terra Mystica which is simple and straightforward:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
//Define the proper message&lt;br /&gt;
		$message = clienttranslate(&#039;${player_name} gets ${power_income} via Structures&#039;);&lt;br /&gt;
		if ($price &amp;gt; 0) {&lt;br /&gt;
			$this-&amp;gt;DbQuery(&amp;quot;UPDATE player SET player_score = player_score - $price WHERE player_id = $player_id&amp;quot;);&lt;br /&gt;
			$message = clienttranslate(&#039;${player_name} pays ${vp_price} and gets ${power_income} via Structures&#039;);&lt;br /&gt;
		}&lt;br /&gt;
&lt;br /&gt;
// Notify&lt;br /&gt;
		$this-&amp;gt;notifyAllPlayers( &amp;quot;powerViaStructures&amp;quot;, $message, array(&lt;br /&gt;
			&#039;i18n&#039; =&amp;gt; array( ),&lt;br /&gt;
			&#039;player_id&#039; =&amp;gt; $player_id,&lt;br /&gt;
			&#039;player_name&#039; =&amp;gt; $this-&amp;gt;getUniqueValueFromDb( &amp;quot;SELECT player_name FROM player WHERE player_id = $player_id&amp;quot; ),&lt;br /&gt;
			&#039;power_tokens&#039; =&amp;gt; $power_tokens,&lt;br /&gt;
			&#039;vp_price&#039; =&amp;gt; $this-&amp;gt;getLogsVPAmount($price),&lt;br /&gt;
			&#039;power_income&#039; =&amp;gt; $this-&amp;gt;getLogsPowerAmount($power_income),&lt;br /&gt;
			&#039;newScore&#039; =&amp;gt; $this-&amp;gt;getUniqueValueFromDb( &amp;quot;SELECT player_score FROM player WHERE player_id = $player_id&amp;quot; ),&lt;br /&gt;
			&#039;counters&#039; =&amp;gt; $this-&amp;gt;getGameCounters(null),&lt;br /&gt;
		) );&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
With some functions to have the needed html added inside the substitution variable, such as:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
function getLogsPowerAmount( $amount ) {&lt;br /&gt;
		return &amp;quot;&amp;lt;div class=&#039;tmlogs_icon&#039; title=&#039;Power&#039;&amp;gt;&amp;lt;div class=&#039;power_amount&#039;&amp;gt;$amount&amp;lt;/div&amp;gt;&amp;lt;/div&amp;gt;&amp;quot;;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Note: injecting html from php is not ideal but easy, if you want more clean solution, use method below but it is a lot more sophisticated.&lt;br /&gt;
&lt;br /&gt;
==== Inject images and styled html in the log ====&lt;br /&gt;
&lt;br /&gt;
{{InfoBox|title=Warning — Translation|maxWidth=500|color=#c00|body=&#039;&#039;&#039;In order to prevent interference with the translation process, keep in mind that you must only apply modifications to the args object, and not try to substitute the keys (the &amp;lt;code&amp;gt;${player_name}&amp;lt;/code&amp;gt; parts of your string) in the log string.&#039;&#039;&#039;}}&lt;br /&gt;
&lt;br /&gt;
So you want nice pictures in the game log. What do you do? The first idea that comes to mind is to send html from php in notifications (see method above). &lt;br /&gt;
&lt;br /&gt;
This is a bad idea for many reasons:&lt;br /&gt;
&lt;br /&gt;
* It&#039;s bad architecture. ui elements leak into the server, and now you have to manage the ui in multiple places.&lt;br /&gt;
* If you decided to change something in the ui in future version, replay logs for old games and tutorials may not work, since they use stored notifications.&lt;br /&gt;
* Log previews for old games become unreadable. (This is the log state before you enter the game replay, which is useful for troubleshooting and game analysis.)&lt;br /&gt;
* It&#039;s more data to transfer and store in the db.&lt;br /&gt;
* It&#039;s a nightmare for translators.&lt;br /&gt;
&lt;br /&gt;
So what else can you do? You can use client side log injection to intercept log arguments (which come from the server) and replace them with html on the client side. Here are three different method you can use to achieve this.&lt;br /&gt;
&lt;br /&gt;
===== Override &amp;lt;code&amp;gt;this.format_string_recursive()&amp;lt;/code&amp;gt; method =====&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Ingredients:&#039;&#039;&#039; ggg.js, ggg.game.php&lt;br /&gt;
&lt;br /&gt;
I use this recipe for &#039;&#039;&#039;client side log injection&#039;&#039;&#039; to intercept log arguments (which come from the server) and replace them with html on the client side.&lt;br /&gt;
&lt;br /&gt;
[[File:clientloginjection.png|left]] &lt;br /&gt;
&lt;br /&gt;
ggg.js&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt; &lt;br /&gt;
&lt;br /&gt;
        /** Override this function to inject html into log items. This is a built-in BGA method.  */&lt;br /&gt;
&lt;br /&gt;
        /* @Override */&lt;br /&gt;
        format_string_recursive : function format_string_recursive(log, args) {&lt;br /&gt;
            try {&lt;br /&gt;
                if (log &amp;amp;&amp;amp; args &amp;amp;&amp;amp; !args.processed) {&lt;br /&gt;
                    args.processed = true;&lt;br /&gt;
                    &lt;br /&gt;
&lt;br /&gt;
                    // list of special keys we want to replace with images&lt;br /&gt;
                    var keys = [&#039;place_name&#039;,&#039;token_name&#039;];&lt;br /&gt;
                    &lt;br /&gt;
                  &lt;br /&gt;
                    for ( var i in keys) {&lt;br /&gt;
                        var key = keys[i];&lt;br /&gt;
                        key in args &amp;amp;&amp;amp; args[key] = this.getTokenDiv(key, args);                            &lt;br /&gt;
&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            } catch (e) {&lt;br /&gt;
                console.error(log,args,&amp;quot;Exception thrown&amp;quot;, e.stack);&lt;br /&gt;
            }&lt;br /&gt;
            return this.inherited({callee: format_string_recursive}, arguments);&lt;br /&gt;
        },&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Important:&#039;&#039;&#039; In the &#039;&#039;format_string_recursive&#039;&#039; method, the &#039;args&#039; parameter will only contain arguments passed to it from the notify method in ggg.game.php (see below).&lt;br /&gt;
&lt;br /&gt;
The &#039;log&#039; parameter is the actual string that is inserted into the logs. You can perform additional js string manipulation on it.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        getTokenDiv : function(key, args) {&lt;br /&gt;
            // ... implement whatever html you want here, example from sharedcode.js&lt;br /&gt;
            var token_id = args[key];&lt;br /&gt;
            var item_type = getPart(token_id,0);&lt;br /&gt;
            var logid = &amp;quot;log&amp;quot; + (this.globalid++) + &amp;quot;_&amp;quot; + token_id;&lt;br /&gt;
            switch (item_type) {&lt;br /&gt;
                case &#039;wcube&#039;:&lt;br /&gt;
                    var tokenDiv = this.format_block(&#039;jstpl_resource_log&#039;, {&lt;br /&gt;
                        &amp;quot;id&amp;quot; : logid,&lt;br /&gt;
                        &amp;quot;type&amp;quot; : &amp;quot;wcube&amp;quot;,&lt;br /&gt;
                        &amp;quot;color&amp;quot; : getPart(token_id,1),&lt;br /&gt;
                    });&lt;br /&gt;
                    return tokenDiv;&lt;br /&gt;
             &lt;br /&gt;
                case &#039;meeple&#039;:&lt;br /&gt;
                    if ($(token_id)) {&lt;br /&gt;
                        var clone = dojo.clone($(token_id));&lt;br /&gt;
    &lt;br /&gt;
                        dojo.attr(clone, &amp;quot;id&amp;quot;, logid);&lt;br /&gt;
                        this.stripPosition(clone);&lt;br /&gt;
                        dojo.addClass(clone, &amp;quot;logitem&amp;quot;);&lt;br /&gt;
                        return clone.outerHTML;&lt;br /&gt;
                    }&lt;br /&gt;
                    break;&lt;br /&gt;
     &lt;br /&gt;
                default:&lt;br /&gt;
                    break;&lt;br /&gt;
            }&lt;br /&gt;
&lt;br /&gt;
            return &amp;quot;&#039;&amp;quot; + this.clienttranslate_string(this.getTokenName(token_id)) + &amp;quot;&#039;&amp;quot;;&lt;br /&gt;
       },&lt;br /&gt;
       getTokenName : function(key) {&lt;br /&gt;
           return this.gamedatas.token_types[key].name; // get name for the key, from static table for example&lt;br /&gt;
       },&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note that in this case the server simply injects token_id as a name, and the client substitutes it for the translated name or the picture.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
ggg.game.php:&lt;br /&gt;
&lt;br /&gt;
           $this-&amp;gt;notifyAllPlayers(&#039;playerLog&#039;,clienttranslate(&#039;Game moves ${token_name}&#039;),[&#039;token_name&#039;=&amp;gt;$token_id]);&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Important:&#039;&#039;&#039; As noted above, only arguments actually passed by this method are available to the args parameter received in the client-side &#039;&#039;format_string_recursive&#039;&#039; method.&lt;br /&gt;
&lt;br /&gt;
Sometimes it is the case that you want to pass arguments that are not actually included in the output message. For example, suppose we have a method like this:&lt;br /&gt;
&lt;br /&gt;
           $this-&amp;gt;notifyAllPlayers(&#039;tokenPlaced&#039;,clienttranslate(&#039;Player placed ${token_name}&#039;),array(&lt;br /&gt;
              &#039;token_name&#039; =&amp;gt; $token_id,&lt;br /&gt;
              &#039;zone_played&#039; =&amp;gt; $zone);&lt;br /&gt;
&lt;br /&gt;
This will output &amp;quot;Player placed ${token_name}&amp;quot; in the log, and if we subscribe to a notification method activated by the &amp;quot;tokenPlaced&amp;quot; event in the client-side code, that method can make use of the &#039;zone_played&#039; argument. &lt;br /&gt;
&lt;br /&gt;
Now if you want to make some really cool things with game log, most probably you would need more arguments than are included in log message. The problem with that,&lt;br /&gt;
it will work at first, but if you reload game using F5 or when the game loads in turn based mode, you will loose your additional parameters, why? Because when game reloads it does not actually send same notifications, it sends special &amp;quot;hitstorical_log&amp;quot; notification where all  parameters not listed in the message are removed. In example above, field zone_played would be removed from historical log as it is not included in message of the notification. You can till preserve specific arguments in historical log by adding special field preserve to notification arguments like this:&lt;br /&gt;
 &lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
           $this-&amp;gt;notifyAllPlayers(&#039;tokenPlaced&#039;,clienttranslate(&#039;Player placed ${token_name}&#039;),array(&lt;br /&gt;
              &#039;token_name&#039; =&amp;gt; $token_id,&lt;br /&gt;
              &#039;zone_played&#039; =&amp;gt; $zone,&lt;br /&gt;
              &#039;preserve&#039; =&amp;gt; [ &#039;zone_played&#039; ]&lt;br /&gt;
           );&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Now you can use zone_played in format_string_recursive even in historical logs.&lt;br /&gt;
&lt;br /&gt;
===== Use &amp;lt;code&amp;gt;:formatFunction&amp;lt;/code&amp;gt; option provided by &amp;lt;code&amp;gt;dojo.string.substitute&amp;lt;/code&amp;gt; =====&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Ingredients:&#039;&#039;&#039; ggg.js, ggg.game.php, ggg_ggg.tpl, ggg.css&lt;br /&gt;
&lt;br /&gt;
The above method will work in most of the cases, but if you use dotted keys such as &amp;lt;code&amp;gt;${card.name}&amp;lt;/code&amp;gt; (which is supported by the framework, for private state args), the key won&#039;t be substituted because the &amp;lt;code&amp;gt;key in arg&amp;lt;/code&amp;gt; test will fail. If so you need to rely either on this way, or the one after.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;WARNING:&#039;&#039;&#039; using this method on an already advanced project will require you to go through all your notifications to change keys !&lt;br /&gt;
&lt;br /&gt;
Under the hood, the &#039;&#039;&#039;this.format_string_recursive()&#039;&#039;&#039; function calls the &#039;&#039;&#039;dojo.string.substitute&#039;&#039;&#039; method which substitutes &amp;lt;code&amp;gt;${keys}&amp;lt;/code&amp;gt; with the value provided. If you take a look at the [https://dojotoolkit.org/reference-guide/1.7/dojo/string.html#substitute documentation] and [https://github.com/dojo/dojo/blob/c3ceb017cfa25b703f5662dc83d1c8aae9bc5d81/string.js#L163 source code] you can notice that the key can be suffixed with a colon (&amp;lt;code&amp;gt;:&amp;lt;/code&amp;gt;) followed by a function name. This will allow you to specify directly in the substitution string which keys need HTML injection.&lt;br /&gt;
&lt;br /&gt;
First of all, you need to define your formatting function in the ggg.js file:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
[[ggg.js]]&lt;br /&gt;
        getTokenDiv : function(value, key) {&lt;br /&gt;
            //This is only an example implementation, you need to write your own.&lt;br /&gt;
            //The method should return HTML code&lt;br /&gt;
            switch (key) {&lt;br /&gt;
                case &#039;html_injected_argument1&#039;:&lt;br /&gt;
                    return this.format_block(&#039;jstpl_HTMLLogElement1&#039;,{value: value});&lt;br /&gt;
                case &#039;html_injected_argument2&#039;:&lt;br /&gt;
                    return this.format_block(&#039;jstpl_HTMLLogElement2&#039;,{value: value});&lt;br /&gt;
                ...&lt;br /&gt;
            }&lt;br /&gt;
       }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Obviously you need to define the appropriate templates in the ggg_ggg.tpl file:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
[[ggg_ggg.tpl]]&lt;br /&gt;
let jstpl_HTMLLogElement1 = &#039;&amp;lt;div class=&amp;quot;log-element log-element-1-${value}&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&#039;;&lt;br /&gt;
let jstpl_HTMLLogElement2 = &#039;&amp;lt;div class=&amp;quot;log-element log-element-2-${value}&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&#039;;&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
And the appropriate classes in ggg.css.&lt;br /&gt;
&lt;br /&gt;
Then you need to add the &amp;lt;code&amp;gt;dojo/aspect&amp;lt;/code&amp;gt; module at the top of the ggg.js file:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;[[ggg.js]]&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
 define([&lt;br /&gt;
     &amp;quot;dojo&amp;quot;, &amp;quot;dojo/_base/declare&amp;quot;,&lt;br /&gt;
     &#039;&#039;&#039;&amp;lt;span style=&amp;quot;color:green;&amp;quot;&amp;gt;&amp;quot;dojo/aspect&amp;quot;,&amp;lt;/span&amp;gt;                 //MUST BE IN THIRD POSITION&#039;&#039;&#039; (see [[#Including your own JavaScript module (II)|below]])&lt;br /&gt;
     &amp;quot;ebg/core/gamegui&amp;quot;,&lt;br /&gt;
     &amp;quot;ebg/counter&amp;quot;,&lt;br /&gt;
 ], function (dojo, declare, &amp;lt;span style=&amp;quot;color:green;&amp;quot;&amp;gt;&#039;&#039;&#039;aspect&#039;&#039;&#039;&amp;lt;/span&amp;gt;) {&lt;br /&gt;
 ...&lt;br /&gt;
&lt;br /&gt;
And you also need to add the following code in your &amp;lt;code&amp;gt;contructor&amp;lt;/code&amp;gt; method in the ggg.js:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;[[ggg.js]]&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
         constructor: function(){&lt;br /&gt;
&lt;br /&gt;
             // ... skipped code ...&lt;br /&gt;
             let gameObject = this;            //Needed as the this object in aspect.before will not refer to the game object in which the formatting function resides&lt;br /&gt;
             aspect.before(dojo.string, &amp;quot;substitute&amp;quot;, function(template, map, transform) {      //This allows you to modify the arguments of the dojo.string.substitute method before they&#039;re actually passed to it&lt;br /&gt;
                 return [template, map, transform, gameObject];&lt;br /&gt;
             });&lt;br /&gt;
&lt;br /&gt;
Now you&#039;re all set to inject HTML in your logs. To actually achieve this, you must specify the function name with the key like so:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;[[ggg.game.php]]&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
 $this-&amp;gt;notifyAllPlayers(&amp;quot;notificationName&amp;quot;, clienttranslate(&amp;quot;This log message contains ${plainTextArgument} and the following will receive HTML injection: ${html_injected_argument1:getTokenDiv}&amp;quot;), [&lt;br /&gt;
     &amp;quot;plainTextArgument&amp;quot; =&amp;gt; &amp;quot;some plain text here&amp;quot;,&lt;br /&gt;
     &amp;quot;html_injected_argument1&amp;quot; =&amp;gt; &amp;quot;some value used by getTokenDiv&amp;quot;,&lt;br /&gt;
 ]);&lt;br /&gt;
&lt;br /&gt;
You&#039;re not limited writing only one function, you can write as many functions as you like, and have them each inject a specific type of HTML. You just need to specify the relevant function name after the column in the substitution key.&lt;br /&gt;
&lt;br /&gt;
===== Use &amp;lt;code&amp;gt;transform&amp;lt;/code&amp;gt; argument of &amp;lt;code&amp;gt;dojo.string.substitute&amp;lt;/code&amp;gt; =====&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Ingredients:&#039;&#039;&#039; ggg.js, ggg.game.php, ggg_ggg.tpl, ggg.css&lt;br /&gt;
&lt;br /&gt;
This method is also relying on the use of &amp;lt;code&amp;gt;dojo.string.substitute&amp;lt;/code&amp;gt; by the framework, and will use the &amp;lt;code&amp;gt;transform&amp;lt;/code&amp;gt; argument, which, accordting to [https://github.com/dojo/dojo/blob/c3ceb017cfa25b703f5662dc83d1c8aae9bc5d81/string.js#L163 source code] and [https://dojotoolkit.org/reference-guide/1.7/dojo/string.html#substitute documentation] will be run on all the messages going through dojo.string.substitute.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;WARNING:&#039;&#039;&#039; This method will be applied to all strings that go through dojo.string.substitute. As such you must take extra care not to substitute keys that may be used by the framework (i.e. ${id}). In order to do so, a good practise would be to prefix all keys that need substitution with a trigram of the game name.&lt;br /&gt;
&lt;br /&gt;
Since all the keys will be fed to the tranform function, by default, it must return the value, substituted or not per your needs. You can define the function like this in the ggg.js file:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;[[ggg.js]]&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
         getTokenDiv : function(value, key) {&lt;br /&gt;
             //This is only an example implementation, you need to write your own.&lt;br /&gt;
             //The method should return HTML code&lt;br /&gt;
             switch (key) {&lt;br /&gt;
                 case &#039;html_injected_argument1&#039;:&lt;br /&gt;
                     return this.format_block(&#039;jstpl_HTMLLogElement1&#039;,{value: value});&lt;br /&gt;
                 case &#039;html_injected_argument2&#039;:&lt;br /&gt;
                     return this.format_block(&#039;jstpl_HTMLLogElement2&#039;,{value: value});&lt;br /&gt;
                 ...&lt;br /&gt;
                 default:&lt;br /&gt;
                     return value; //Needed otherwise regular strings won&#039;t appear since since the value isn&#039;t returned by the function&lt;br /&gt;
             }&lt;br /&gt;
         }&lt;br /&gt;
&lt;br /&gt;
The templates must be defined in the ggg_ggg.tpl file and the corresponding CSS classes in the ggg.css file.&lt;br /&gt;
&lt;br /&gt;
You need to add the following code at the beginning of the ggg.js file:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;[[ggg.js]]&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
 define([&lt;br /&gt;
     &amp;quot;dojo&amp;quot;, &amp;quot;dojo/_base/declare&amp;quot;,&lt;br /&gt;
     &#039;&#039;&#039;&amp;lt;span style=&amp;quot;color:green;&amp;quot;&amp;gt;&amp;quot;dojo/aspect&amp;quot;,&amp;lt;/span&amp;gt;                 //MUST BE IN THIRD POSITION&#039;&#039;&#039; (see [[#Including your own JavaScript module (II)|below]])&lt;br /&gt;
     &amp;quot;ebg/core/gamegui&amp;quot;,&lt;br /&gt;
     &amp;quot;ebg/counter&amp;quot;,&lt;br /&gt;
 ], function (dojo, declare, &amp;lt;span style=&amp;quot;color:green;&amp;quot;&amp;gt;&#039;&#039;&#039;aspect&#039;&#039;&#039;&amp;lt;/span&amp;gt;) {&lt;br /&gt;
 ...&lt;br /&gt;
&lt;br /&gt;
And the following code to the &amp;lt;code&amp;gt;constructor&amp;lt;/code&amp;gt; method in ggg.js:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;[[ggg.js]]&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
         constructor: function(){&lt;br /&gt;
             // ... skipped code ...&lt;br /&gt;
             let transformFunction = dojo.hitch(this, &amp;quot;getTokenDiv&amp;quot;);          //Needed as the this object in aspect.before will not refer to the game object in which the formatting function resides&lt;br /&gt;
             aspect.before(dojo.string, &amp;quot;substitute&amp;quot;, function(template, map, transform) {&lt;br /&gt;
                 if (undefined === transform) {    //Check for a transform function presence, just in case&lt;br /&gt;
                     return [template, map, transformFunction];&lt;br /&gt;
                 }&lt;br /&gt;
             });&lt;br /&gt;
&lt;br /&gt;
Then you&#039;re all set for log injection, no need to change anything on the PHP side.&lt;br /&gt;
&lt;br /&gt;
==== Processing logs on re-loading ====&lt;br /&gt;
&lt;br /&gt;
You rarely need to process logs when reloading, but if you want to do something fancy you may have to do it after logs are loaded. &lt;br /&gt;
Logs are loaded asyncronously so you have to listen for logs to be fully loaded.&lt;br /&gt;
Unfortunately there is no direct way of doing it so this is the hack.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Hack alert&#039;&#039;&#039; - this extends undocumented function and may be broken when framework is updated&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Ingredients:&#039;&#039;&#039; ggg.js&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
			/*&lt;br /&gt;
  			* [Undocumented] Override BGA framework functions to call onLoadingLogsComplete when loading is done&lt;br /&gt;
                        @Override&lt;br /&gt;
   			*/&lt;br /&gt;
			setLoader: function(image_progress, logs_progress) {&lt;br /&gt;
				this.inherited(arguments); // required, this is &amp;quot;super()&amp;quot; call, do not remove&lt;br /&gt;
				//console.log(&amp;quot;loader&amp;quot;, image_progress, logs_progress)&lt;br /&gt;
				if (!this.isLoadingLogsComplete &amp;amp;&amp;amp; logs_progress &amp;gt;= 100) {&lt;br /&gt;
					this.isLoadingLogsComplete = true; // this is to prevent from calling this more then once&lt;br /&gt;
					this.onLoadingLogsComplete();&lt;br /&gt;
				}&lt;br /&gt;
			},&lt;br /&gt;
&lt;br /&gt;
			onLoadingLogsComplete: function() {&lt;br /&gt;
				console.log(&#039;Loading logs complete&#039;);&lt;br /&gt;
				// do something here&lt;br /&gt;
			},&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Player Panel ===&lt;br /&gt;
&lt;br /&gt;
==== Inserting non-player panel ====&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Ingredients:&#039;&#039;&#039; ggg.js, ggg_ggg.tpl&lt;br /&gt;
&lt;br /&gt;
If you want to insert non-player panel on the right side (for example to hold extra preferences, zooming controls, etc)&lt;br /&gt;
&lt;br /&gt;
this can go pretty much anywhere in template it will be moved later&lt;br /&gt;
&lt;br /&gt;
ggg_ggg.tpl:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
	&amp;lt;div class=&#039;player_board_config&#039; id=&amp;quot;player_board_config&amp;quot;&amp;gt;&lt;br /&gt;
        &amp;lt;!-- here is whatever you want, buttons just example --&amp;gt;&lt;br /&gt;
		&amp;lt;button id=&amp;quot;zoom-out&amp;quot; class=&amp;quot; fa fa-search-minus fa-2x config-control&amp;quot;&amp;gt;&amp;lt;/button&amp;gt;&lt;br /&gt;
		&amp;lt;button id=&amp;quot;zoom-in&amp;quot; class=&amp;quot; fa fa-search-plus fa-2x config-control&amp;quot;&amp;gt;&amp;lt;/button&amp;gt;&lt;br /&gt;
		&amp;lt;button id=&amp;quot;show-settings&amp;quot; class=&amp;quot;fa fa-cog fa-2x config-control &amp;quot;&amp;gt;&amp;lt;/button&amp;gt;&lt;br /&gt;
        &amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
some hackery required in js&lt;br /&gt;
&lt;br /&gt;
ggg.js:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
/* @Override */&lt;br /&gt;
	updatePlayerOrdering() {&lt;br /&gt;
		this.inherited(arguments);&lt;br /&gt;
		dojo.place(&#039;player_board_config&#039;, &#039;player_boards&#039;, &#039;first&#039;);&lt;br /&gt;
	},&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Images and Icons ===&lt;br /&gt;
&lt;br /&gt;
==== Accessing images from js ====&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Ingredients:&#039;&#039;&#039; ggg.js&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt; &lt;br /&gt;
     // your game resources&lt;br /&gt;
     &lt;br /&gt;
     var my_img = &#039;&amp;lt;img src=&amp;quot;&#039;+g_gamethemeurl+&#039;img/cards.jpg&amp;quot;/&amp;gt;&#039;;&lt;br /&gt;
     &lt;br /&gt;
     // shared resources&lt;br /&gt;
     var my_help_img = &amp;quot;&amp;lt;img class=&#039;imgtext&#039; src=&#039;&amp;quot; + g_themeurl + &amp;quot;img/layout/help_click.png&#039; alt=&#039;action&#039; /&amp;gt; &amp;lt;span class=&#039;tooltiptext&#039;&amp;gt;&amp;quot; +&lt;br /&gt;
                    text + &amp;quot;&amp;lt;/span&amp;gt;&amp;quot;;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== High-Definition Graphics ====&lt;br /&gt;
&lt;br /&gt;
Some users will have screens which can display text and images at a greater resolution than the usual 72 dpi, e.g. the &amp;quot;Retina&amp;quot; screens on the 5k iMac, all iPads, and high-DPI screens on laptops from many manufacturers. If you can get art assets at this size, they will make your game look extra beautiful. You &#039;&#039;could&#039;&#039; just use large graphics and scale them down, but that would increase the download time and bandwidth for users who can&#039;t display them. Instead, a good way is to prepare a separate graphics file at exactly twice the size you would use otherwise, and add &amp;quot;@2x&amp;quot; at the end of the filename, e.g. if pieces.png is 240x320, then pieces@2x.png is 480x640.&lt;br /&gt;
&lt;br /&gt;
There are two changes required in order to use the separate graphics files. First in your css, where you use a file, add a media query which overrides the original definition and uses the bigger version on devices which can display them. Ensuring that the &amp;quot;background-size&amp;quot; attribute is set means that the size of the displayed object doesn&#039;t change, but only is drawn at the improved dot pitch.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
.piece {&lt;br /&gt;
    position: absolute;&lt;br /&gt;
    background-image: url(&#039;img/pieces.png&#039;);&lt;br /&gt;
    background-size:240px 320px;&lt;br /&gt;
    z-index: 10;&lt;br /&gt;
}&lt;br /&gt;
@media (-webkit-min-device-pixel-ratio: 2), (min-device-pixel-ratio: 2), (min-resolution: 192dpi)&lt;br /&gt;
{&lt;br /&gt;
    .piece {&lt;br /&gt;
        background-image: url(&#039;img/pieces@2x.png&#039;);&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Secondly, in your setup function in javascript, you must ensure than only the appropriate one version of the file gets pre-loaded (otherwise you more than waste the bandwidth saved by maintaining the standard-resolution file). Note that the media query is the same in both cases:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
            var isRetina = &amp;quot;(-webkit-min-device-pixel-ratio: 2), (min-device-pixel-ratio: 2), (min-resolution: 192dpi)&amp;quot;;&lt;br /&gt;
            if (window.matchMedia(isRetina).matches)&lt;br /&gt;
            {&lt;br /&gt;
                this.dontPreloadImage( &#039;pieces.png&#039; );&lt;br /&gt;
                this.dontPreloadImage( &#039;board.jpg&#039; );&lt;br /&gt;
            }&lt;br /&gt;
            else&lt;br /&gt;
            {&lt;br /&gt;
                this.dontPreloadImage( &#039;pieces@2x.png&#039; );&lt;br /&gt;
                this.dontPreloadImage( &#039;board@2x.jpg&#039; );&lt;br /&gt;
            }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Using CSS to create different colors of game pieces if you have only white piece ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
background-color: #${color}; &lt;br /&gt;
background-blend-mode: multiply;&lt;br /&gt;
background-image: url( &#039;img/mypiece.png&#039;);&lt;br /&gt;
mask: url(&#039;img/mypiece.png&#039;);&lt;br /&gt;
-webkit-mask: url(&#039;img/mypiece.png&#039;);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
where ${color} - is color you want&lt;br /&gt;
&lt;br /&gt;
Note: piece has to be white (shades of gray). Sprite can be used too, just add add background-position as usual.&lt;br /&gt;
&lt;br /&gt;
==== Accessing player avatar URLs ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
      getPlayerAvatar(playerId) {&lt;br /&gt;
         let avatarURL = &#039;&#039;;&lt;br /&gt;
&lt;br /&gt;
         if (null != $(&#039;avatar_&#039; + playerId)) {&lt;br /&gt;
            let smallAvatarURL = dojo.attr(&#039;avatar_&#039; + playerId, &#039;src&#039;);&lt;br /&gt;
            avatarURL = smallAvatarURL.replace(&#039;_32.&#039;, &#039;_184.&#039;);&lt;br /&gt;
         }&lt;br /&gt;
         else {&lt;br /&gt;
            avatarURL = &#039;https://x.boardgamearena.net/data/data/avatar/default_184.jpg&#039;;&lt;br /&gt;
         }&lt;br /&gt;
&lt;br /&gt;
         return avatarURL;&lt;br /&gt;
      },&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note:  This gets avatar URLs at 184x184 resolution.  You can also use 92, 50, and 32 depending on which resolution you want.&lt;br /&gt;
&lt;br /&gt;
==== Adding Image buttons ====&lt;br /&gt;
&lt;br /&gt;
Its pretty trivial but just in case you need a working function:&lt;br /&gt;
&lt;br /&gt;
ggg.js:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
                addImageActionButton: function (id, div_html, handler) { // div_html is string not node&lt;br /&gt;
                    this.addActionButton(id, div_html, handler, &#039;&#039;, false, &#039;gray&#039;); &lt;br /&gt;
                    dojo.style(id, &amp;quot;border&amp;quot;, &amp;quot;none&amp;quot;); // remove ugly border&lt;br /&gt;
                    dojo.addClass(id, &amp;quot;bgaimagebutton&amp;quot;); // add css class to do more styling&lt;br /&gt;
                    return $(id); // return node for chaining&lt;br /&gt;
                },&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Example of usage:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    this.addImageActionButton(&#039;button_coin&#039;,&amp;quot;&amp;lt;div class=&#039;coin&#039;&amp;gt;&amp;lt;/div&amp;gt;&amp;quot;, ()=&amp;gt;{ alert(&#039;Ha!&#039;); });&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Other Fluff ===&lt;br /&gt;
&lt;br /&gt;
==== Use thematic fonts ====&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Ingredients:&#039;&#039;&#039; ggg.css&lt;br /&gt;
&lt;br /&gt;
Sometime game elements use specific fonts of text, if you want to match it up you can load some specific font (IMPORTANT: from some &#039;&#039;&#039;free font&#039;&#039;&#039; source. See notes below).&lt;br /&gt;
&lt;br /&gt;
[[File:Dragonline_font.png]]&lt;br /&gt;
&lt;br /&gt;
.css&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
/* latin-ext */&lt;br /&gt;
@font-face {&lt;br /&gt;
  font-family: &#039;Qwigley&#039;;&lt;br /&gt;
  font-style: normal;&lt;br /&gt;
  font-weight: 400;&lt;br /&gt;
  src: local(&#039;Qwigley&#039;), local(&#039;Qwigley-Regular&#039;), url(https://fonts.gstatic.com/s/qwigley/v6/2Dy1Unur1HJoklbsg4iPJ_Y6323mHUZFJMgTvxaG2iE.woff2) format(&#039;woff2&#039;);&lt;br /&gt;
  unicode-range: U+0100-024F, U+1E00-1EFF, U+20A0-20AB, U+20AD-20CF, U+2C60-2C7F, U+A720-A7FF;&lt;br /&gt;
}&lt;br /&gt;
/* latin */&lt;br /&gt;
@font-face {&lt;br /&gt;
  font-family: &#039;Qwigley&#039;;&lt;br /&gt;
  font-style: normal;&lt;br /&gt;
  font-weight: normal;&lt;br /&gt;
  src: local(&#039;Qwigley&#039;), local(&#039;Qwigley-Regular&#039;), url(https://fonts.gstatic.com/s/qwigley/v6/gThgNuQB0o5ITpgpLi4Zpw.woff2) format(&#039;woff2&#039;);&lt;br /&gt;
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2212, U+2215, U+E0FF, U+EFFD, U+F000;&lt;br /&gt;
}&lt;br /&gt;
@font-face {&lt;br /&gt;
  font-family: &#039;Qwigley&#039;;&lt;br /&gt;
  font-style: normal;&lt;br /&gt;
  font-weight: normal;&lt;br /&gt;
  src: local(&#039;Qwigley&#039;), local(&#039;Qwigley-Regular&#039;), url(http://ff.static.1001fonts.net/q/w/qwigley.regular.ttf) format(&#039;ttf&#039;);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.zone_title {&lt;br /&gt;
	display: inline-block;&lt;br /&gt;
	position: absolute;&lt;br /&gt;
	font: italic 32px/32px &amp;quot;Qwigley&amp;quot;, cursive;	   &lt;br /&gt;
	height: 32px;&lt;br /&gt;
	width: auto;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;NB:&#039;&#039;&#039; if you need to include a font that&#039;s not available online, an extra action will be needed from an admin. Please include the font file(s) in your img directory, and mention it to admins when requesting your game to be moved to alpha. &#039;&#039;&#039;Please remember that the font has to be free, and include a .txt with all appropriate license information about the font.&#039;&#039;&#039;&lt;br /&gt;
You can look for free fonts (for example) on https://fonts.google.com or https://www.fontsquirrel.com/)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Content Security Policy&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
BGA runs a Content Security Policy which will limit the origins from which you can load external fonts, in order to prevent license abuse.&lt;br /&gt;
&lt;br /&gt;
The CSP is a whitelist of allowed origins. To see the list, view the response headers of any page on Studio, and look for the &amp;quot;Content-Security-Policy&amp;quot; header.&lt;br /&gt;
&lt;br /&gt;
You will specifically want to check for the font-src token within these headers, and limit any external fonts to these sources.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;This list is subject to change&#039;&#039;&#039; but as of the time of writing, the only acceptabled external sites are use.typekit.net and fonts.gstatic.com.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Scale to fit for big boards ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Ingredients:&#039;&#039;&#039; ggg_ggg.tpl, ggg.js&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Lets say you have huge game board, and lets say you want it to be 1400px wide. Besides the board there will be side bar which is 240 and trim. &lt;br /&gt;
My display is 1920 wide so it fits, but there is big chance other people won&#039;t have that width. What do you do?&lt;br /&gt;
&lt;br /&gt;
You have to decide:&lt;br /&gt;
* If board does not fit you want scale whole thing down, the best way is probably use viewport (see https://en.doc.boardgamearena.com/Your_game_mobile_version)&lt;br /&gt;
* You can leave the board as is and make sure it is scrollable horizonatally&lt;br /&gt;
* You add custom scale just for the board (can add user controls  - and hook to transform: scale())&lt;br /&gt;
&lt;br /&gt;
I tried to auto-scale but this just does work, too many variables - browser zoom, 3d mode, viewport, custom bga scaling, devicePixelRatio - all create some impossible coctail of zooming...&lt;br /&gt;
Here is scaling functing for custom user scaling&lt;br /&gt;
&lt;br /&gt;
ggg_ggg.tpl:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
   &amp;lt;div id=&amp;quot;thething&amp;quot; class=&amp;quot;thething&amp;quot;&amp;gt;&lt;br /&gt;
            ... everything else you declare ...&lt;br /&gt;
   &amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
ggg.js:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    onZoomPlus: function() {&lt;br /&gt;
       this.setZoom(this.zoom + 0.1);&lt;br /&gt;
    },&lt;br /&gt;
    onZoomMinus: function() {&lt;br /&gt;
       this.setZoom(this.zoom - 0.1);&lt;br /&gt;
    },&lt;br /&gt;
&lt;br /&gt;
    setZoom: function (zoom) {&lt;br /&gt;
      zoom = parseInt(zoom) || 0;&lt;br /&gt;
      if (zoom === 0 || zoom &amp;lt; 0.1 || zoom &amp;gt; 10) {&lt;br /&gt;
        zoom = 1;&lt;br /&gt;
      }&lt;br /&gt;
      this.zoom = zoom;&lt;br /&gt;
      var inner = document.getElementById(&amp;quot;thething&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
      if (zoom == 1) {&lt;br /&gt;
        inner.style.removeProperty(&amp;quot;transform&amp;quot;);&lt;br /&gt;
        inner.style.removeProperty(&amp;quot;width&amp;quot;);&lt;br /&gt;
      } else {&lt;br /&gt;
        inner.style.transform = &amp;quot;scale(&amp;quot; + zoom + &amp;quot;)&amp;quot;;&lt;br /&gt;
        inner.style.transformOrigin = &amp;quot;0 0&amp;quot;;&lt;br /&gt;
        inner.style.width = 100 / zoom + &amp;quot;%&amp;quot;;&lt;br /&gt;
      }&lt;br /&gt;
      localStorage.setItem(`${this.game_name}_zoom`, &amp;quot;&amp;quot; + this.zoom);&lt;br /&gt;
      this.onScreenWidthChange();&lt;br /&gt;
    },&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Dynamic tooltips ===&lt;br /&gt;
&lt;br /&gt;
If you really need a dynamic tooltip you can use this technique. (Only use it if the static tooltips provided by the BGA framework are not sufficient.)&lt;br /&gt;
&lt;br /&gt;
            new dijit.Tooltip({&lt;br /&gt;
                connectId: [&amp;quot;divItemId&amp;quot;],&lt;br /&gt;
                getContent: function(matchedNode){&lt;br /&gt;
                    return &amp;quot;... calculated ...&amp;quot;; &lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
This is an out-of-the-box djit.Tooltip. It has a &#039;&#039;getContent&#039;&#039; method which is called dynamically.&lt;br /&gt;
&lt;br /&gt;
The string returned by getContent() becomes the innerHTML of the tooltip, so it can be anything. In this example matchedNode is a dojo node representing dom object with id of &amp;quot;divItemId&amp;quot; but there are more parameters which I am not posting here which allows more sophisticated subnode queries (i.e. you can attach tooltip to all nodes with class or whatever).&lt;br /&gt;
&lt;br /&gt;
[https://dojotoolkit.org/reference-guide/1.10/dijit/Tooltip.html dijit.Tooltip]&lt;br /&gt;
&lt;br /&gt;
It&#039;s not part of the BGA API so use at your own risk.&lt;br /&gt;
&lt;br /&gt;
=== Rendering text with players color and proper background ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Ingredients:&#039;&#039;&#039; ggg.js&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        /* Implementation of proper colored You with background in case of white or light colors  */&lt;br /&gt;
 &lt;br /&gt;
        divYou: function() {&lt;br /&gt;
            var color = this.gamedatas.players[this.player_id].color;&lt;br /&gt;
            var color_bg = &amp;quot;&amp;quot;;&lt;br /&gt;
            if (this.gamedatas.players[this.player_id] &amp;amp;&amp;amp; this.gamedatas.players[this.player_id].color_back) {&lt;br /&gt;
                color_bg = &amp;quot;background-color:#&amp;quot; + this.gamedatas.players[this.player_id].color_back + &amp;quot;;&amp;quot;;&lt;br /&gt;
            }&lt;br /&gt;
            var you = &amp;quot;&amp;lt;span style=\&amp;quot;font-weight:bold;color:#&amp;quot; + color + &amp;quot;;&amp;quot; + color_bg + &amp;quot;\&amp;quot;&amp;gt;&amp;quot; + __(&amp;quot;lang_mainsite&amp;quot;, &amp;quot;You&amp;quot;) + &amp;quot;&amp;lt;/span&amp;gt;&amp;quot;;&lt;br /&gt;
            return you;&lt;br /&gt;
        },&lt;br /&gt;
&lt;br /&gt;
        /* Implementation of proper colored player name with background in case of white or light colors  */&lt;br /&gt;
&lt;br /&gt;
        divColoredPlayer: function(player_id) {&lt;br /&gt;
            var color = this.gamedatas.players[player_id].color;&lt;br /&gt;
            var color_bg = &amp;quot;&amp;quot;;&lt;br /&gt;
            if (this.gamedatas.players[player_id] &amp;amp;&amp;amp; this.gamedatas.players[player_id].color_back) {&lt;br /&gt;
                color_bg = &amp;quot;background-color:#&amp;quot; + this.gamedatas.players[player_id].color_back + &amp;quot;;&amp;quot;;&lt;br /&gt;
            }&lt;br /&gt;
            var div = &amp;quot;&amp;lt;span style=\&amp;quot;color:#&amp;quot; + color + &amp;quot;;&amp;quot; + color_bg + &amp;quot;\&amp;quot;&amp;gt;&amp;quot; + this.gamedatas.players[player_id].name + &amp;quot;&amp;lt;/span&amp;gt;&amp;quot;;&lt;br /&gt;
            return div;&lt;br /&gt;
        },&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Cool realistic shadow effect with CSS ===&lt;br /&gt;
&lt;br /&gt;
==== Rectangles and circles ====&lt;br /&gt;
&lt;br /&gt;
It is often nice to have a drop shadow around tiles and tokens, to separate them from the table visually. It is very easy to add a shadow to rectangular elements, just add this to your css:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
.xxx-tile {&lt;br /&gt;
    box-shadow: 3px 3px 3px #000000a0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
box-shadow obeys &#039;&#039;&#039;border-radius&#039;&#039;&#039; of the element, so it will look good for rounded rectangles, and hence also circles (if border-radius is set appropriately).&lt;br /&gt;
&lt;br /&gt;
box-shadow also supports various other parameters and can be used to achieve effects such as glowing, borders, inner shadows etc. If you need to animate a box-shadow, you may be able to get better performance (avoiding redraws) if you attach the shadow to another element (possibly an ::after pseudo-element) and change only the &#039;&#039;&#039;opacity&#039;&#039;&#039; of that element.&lt;br /&gt;
&lt;br /&gt;
==== Irregular Shapes ====&lt;br /&gt;
&lt;br /&gt;
If you wish to make a shadow effect for game pieces that are not a rectangle, but your game pieces are drawn from rectangles in a PNG image, you can apply the shadow to the piece using any art package and save it inside the image. This usually will yield the best performance. Remember to account for the size of the shadow when you lay out images in the sprite sheet.&lt;br /&gt;
&lt;br /&gt;
However that sometimes will not be an option, for example if the image needs to be rotated while the shadow remains offset in the same direction. In this case, one option is to not use box-shadow but use filter, which is supported by recent major browsers.  This way, you can use the alpha channel of your element to drop a shadow.  This even work for transparent backgrounds, so that if you are using the &amp;quot;CSS-sprite&amp;quot; method, it will work!&lt;br /&gt;
&lt;br /&gt;
For instance:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
.xxx-token {&lt;br /&gt;
    filter: drop-shadow(0px 0px 1px #000000);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Beware that some browsers still do not always draw drop-shadow correctly. In particular, Safari frequently leaves bits of shadow behind when objects move around the screen. In Chrome, shadows sometimes flicker badly if another element is animating close by. Some of these correctness issues can be solved by adding &#039;&#039;&#039;isolation: isolate; will-change: filter;&#039;&#039;&#039; to affected elements, but this significantly affects redraw performance.&lt;br /&gt;
&lt;br /&gt;
Beware of performance issues - particularly on Safari (MacOS, iPhone and iPad). Keep in mind that drop-shadow are very GPU intensive. This becomes noticeable once you have about 40 components with drop-shadow filter. If that is your case, you can quite easily implement a user preference to disable shadows for users on slower machines:&lt;br /&gt;
&lt;br /&gt;
gameoptions.inc.php&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
100 =&amp;gt; array(&lt;br /&gt;
			&#039;name&#039; =&amp;gt; totranslate(&#039;Shadows&#039;),&lt;br /&gt;
			&#039;needReload&#039; =&amp;gt; true, // after user changes this preference game interface would auto-reload&lt;br /&gt;
			&#039;values&#039; =&amp;gt; array(&lt;br /&gt;
					1 =&amp;gt; array( &#039;name&#039; =&amp;gt; totranslate( &#039;Enabled&#039; ), &#039;cssPref&#039; =&amp;gt; &#039;&#039; ),&lt;br /&gt;
					2 =&amp;gt; array( &#039;name&#039; =&amp;gt; totranslate( &#039;Disabled&#039; ), &#039;cssPref&#039; =&amp;gt; &#039;no-shadow&#039; )&lt;br /&gt;
			)&lt;br /&gt;
	),&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[game].css&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
.no-shadow * {&lt;br /&gt;
	filter: none !important; &lt;br /&gt;
} &lt;br /&gt;
&amp;lt;/pre&amp;gt;For Safari, it is usually better to simply disable drop-shadow completely: [[Game interface stylesheet: yourgamename.css#Warning: using drop-shadow]].&lt;br /&gt;
&lt;br /&gt;
==== Shadows with clip-path ====&lt;br /&gt;
&lt;br /&gt;
For some reason, a shadow will not work together with clip-path on one element. To use both clip-path (when for example using .svg to cut out cardboard components from your .jpg spritesheet) and drop-shadow, you need to wrap the element into another one, and apply drop-shadow to the outer one, and clip-path to the inner one.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;div class=&#039;my-token-wrap&#039;&amp;gt;&lt;br /&gt;
  &amp;lt;div class=&#039;my-token&#039;&amp;gt;&lt;br /&gt;
  &amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
.my-token-wrap {&lt;br /&gt;
    filter: drop-shadow(0px 0px 1px #000000);&lt;br /&gt;
}&lt;br /&gt;
.my-token-wrap .my-token {&lt;br /&gt;
    clip-path: url(#my-token-path);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Using the CSS classes from the state machine ===&lt;br /&gt;
&lt;br /&gt;
If you need to hide or show stuff depending on the state of your game, you can of course use javascript, but CSS is hand enough for that.  The #overall-content element does change class depending on the game state.  For instance, if you are in state &#039;&#039;playerTurn&#039;&#039;, it will have the class &#039;&#039;gamestate_playerTurn&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
So now, if you want to show the discard pile only during player turns, you may use:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#discard_pile { display: none }&lt;br /&gt;
.gamestate_playerTurn #discard_pile { display: block }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This can be used if you want to change sizing of elements, position, layout or visual appearance.&lt;br /&gt;
&lt;br /&gt;
== Game Model and Database design ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Database for The euro game ===&lt;br /&gt;
Lets say we have a game with workers, dice, tokens, board, resources, money and vp. Workers and dice can be placed in various zones on the board, and you can get resources, money, tokens and vp in your home zone. Also tokens can be flipped or not flipped.&lt;br /&gt;
&lt;br /&gt;
[[File:Madeira board.png]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Now lets try to map it, we have&lt;br /&gt;
* (meeple,zone)&lt;br /&gt;
* (die, zone, sideup)&lt;br /&gt;
* (resource cube/money token/vp token,player home zone)&lt;br /&gt;
* (token, player home zone, flip state)&lt;br /&gt;
We can notice that resource and money are uncountable, and don&#039;t need to be track individually so we can replace our mapping to&lt;br /&gt;
* (resource type/money,player home zone, count)&lt;br /&gt;
And vp stored already for us in player table, so we can remove it from that list.&lt;br /&gt;
&lt;br /&gt;
Now when we get to encode it we can see that everything can be encoded as (object,zone,state) form, where object and zone is string and state is integer. The resource mapping is slightly different semantically so you can go with two table, or counting using same table with state been used as count for resources.&lt;br /&gt;
&lt;br /&gt;
So the piece mapping for non-grid based games can be in most case represented by (string: token_key, string: token_location, int: token_state), example of such database schema can be found here: [https://github.com/elaskavaia/bga-sharedcode/blob/master/dbmodel.sql dbmodel.sql] and class implementing access to it here [https://github.com/elaskavaia/bga-sharedcode/blob/master/modules/tokens.php table.game.php].&lt;br /&gt;
&lt;br /&gt;
Variant 1: Minimalistic&lt;br /&gt;
&lt;br /&gt;
 CREATE TABLE IF NOT EXISTS `token` (&lt;br /&gt;
  `token_key` varchar(32) NOT NULL,&lt;br /&gt;
  `token_location` varchar(32) NOT NULL,&lt;br /&gt;
  `token_state` int(10),&lt;br /&gt;
  PRIMARY KEY (`token_key`)&lt;br /&gt;
 ) ENGINE=InnoDB DEFAULT CHARSET=utf8;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+token&lt;br /&gt;
! token_key&lt;br /&gt;
! token_location&lt;br /&gt;
! token_state&lt;br /&gt;
|-&lt;br /&gt;
|meeple_red_1&lt;br /&gt;
|home_red&lt;br /&gt;
|0&lt;br /&gt;
|-&lt;br /&gt;
|dice_black_2&lt;br /&gt;
|board_guard&lt;br /&gt;
|1&lt;br /&gt;
|-&lt;br /&gt;
|dice_green_1&lt;br /&gt;
|board_action_mayor&lt;br /&gt;
|3&lt;br /&gt;
|-&lt;br /&gt;
|bread&lt;br /&gt;
|home_red&lt;br /&gt;
|5&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Now how we represent resource counters such as bread?&lt;br /&gt;
Using same table from we simply add special counter token for bread and use state to indicate the count. Note to keep first column unique we have to add player identification for that counter, i.e. ff0000 is red player.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+token&lt;br /&gt;
! token_key&lt;br /&gt;
! token_location&lt;br /&gt;
! token_state&lt;br /&gt;
|-&lt;br /&gt;
|bread_ff0000&lt;br /&gt;
|tableau_ff0000&lt;br /&gt;
|5&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
See php module for this table here https://github.com/elaskavaia/bga-sharedcode/blob/master/modules/tokens.php&lt;br /&gt;
&lt;br /&gt;
Variant 2: Additional resource table, resource count for each player id&lt;br /&gt;
&lt;br /&gt;
 CREATE TABLE IF NOT EXISTS `resource` (&lt;br /&gt;
  `player_id` int(10) unsigned NOT NULL,&lt;br /&gt;
  `resource_key` varchar(32) NOT NULL,&lt;br /&gt;
  `resource_count` int(10) signed NOT NULL,&lt;br /&gt;
  PRIMARY KEY (`player_id`,`resource_key`)&lt;br /&gt;
 ) ENGINE=InnoDB DEFAULT CHARSET=utf8;&lt;br /&gt;
&lt;br /&gt;
 ALTER TABLE resource ADD CONSTRAINT fk_player_id FOREIGN KEY (player_id) REFERENCES player(player_id);&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+resource&lt;br /&gt;
! player_id&lt;br /&gt;
! resource_key&lt;br /&gt;
! resource_count&lt;br /&gt;
|-&lt;br /&gt;
|123456&lt;br /&gt;
|bread&lt;br /&gt;
|5&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Variant 3: More normalised&lt;br /&gt;
&lt;br /&gt;
This version is similar to &amp;quot;card&amp;quot; table from hearts tutorial, you can also use exact cards database schema and Deck implementation for most purposes (even you not dealing with cards). &lt;br /&gt;
&lt;br /&gt;
 CREATE TABLE IF NOT EXISTS `token` (&lt;br /&gt;
  `token_id` int(10) unsigned NOT NULL AUTO_INCREMENT,&lt;br /&gt;
  `token_type` varchar(16) NOT NULL,&lt;br /&gt;
  `token_arg` int(11) NOT NULL,&lt;br /&gt;
  `token_location` varchar(32) NOT NULL,&lt;br /&gt;
  `token_state` int(10),&lt;br /&gt;
  PRIMARY KEY (`token_id`)&lt;br /&gt;
 ) ENGINE=InnoDB DEFAULT CHARSET=utf8;&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+token&lt;br /&gt;
! token_id&lt;br /&gt;
! token_type&lt;br /&gt;
! token_arg&lt;br /&gt;
! token_location&lt;br /&gt;
! token_state&lt;br /&gt;
|-&lt;br /&gt;
|22&lt;br /&gt;
|meeple&lt;br /&gt;
|123456&lt;br /&gt;
|home_123456&lt;br /&gt;
|0&lt;br /&gt;
|-&lt;br /&gt;
|23&lt;br /&gt;
|dice&lt;br /&gt;
|2&lt;br /&gt;
|board_guard&lt;br /&gt;
|1&lt;br /&gt;
|-&lt;br /&gt;
|26&lt;br /&gt;
|dice&lt;br /&gt;
|1&lt;br /&gt;
|board_action_mayor&lt;br /&gt;
|3&lt;br /&gt;
|-&lt;br /&gt;
|49&lt;br /&gt;
|bread&lt;br /&gt;
|0&lt;br /&gt;
|home_123456&lt;br /&gt;
|5&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Advantages of this would be is a bit more straightforward to do some queries in db, disadvantage its hard to read (as you can compare with previous example, you&lt;br /&gt;
cannot just look at say, ah I know what it means). Another questionable advantage is it allows you to do id randomisation, so it hard to do crafted queries to &lt;br /&gt;
cheat, the down side of that you cannot understand it either, and handcraft db states for debugging or testing.&lt;br /&gt;
&lt;br /&gt;
=== Database for The card game ===&lt;br /&gt;
&lt;br /&gt;
Lets say you have a standard card game, player have hidden cards in hand, you can draw card from draw deck, play card on tableau and discard to discard pile.&lt;br /&gt;
We have to design database for such game.&lt;br /&gt;
&lt;br /&gt;
In real word to &amp;quot;save&amp;quot; the game we take a picture a play area, save cards from it, then put away draw deck, discard and hand of each player separately and mark it, also we will record current scoring (if any) and who&#039;s turn was it.&lt;br /&gt;
&lt;br /&gt;
* Framework handles state machine transition, so you don&#039;t have to worry about database design for that (i.e. who&#039;s turn it is, what phase of the game we are at, you still have to design it but part of state machine step)&lt;br /&gt;
* Also framework supports basic player information, color, order around the table, basic scoring, etc, so you don&#039;t have to worry about it either&lt;br /&gt;
* The only thing you need in our database is state of the &amp;quot;board&amp;quot;, which is &amp;quot;where each pieces is, and in what state&amp;quot;, or (position,rotation) pair.&lt;br /&gt;
&lt;br /&gt;
Lets see what we have for that:&lt;br /&gt;
* The card state is very simple, its usually &amp;quot;face up/face down&amp;quot;, &amp;quot;tapped/untapped&amp;quot;, &amp;quot;right side up/up side down&amp;quot;&lt;br /&gt;
* As position go we never need real coordinates x,y,z. We need to know what &amp;quot;zone&amp;quot; card was, and depending on the zone it may sometimes need an extra &amp;quot;z&amp;quot; or &amp;quot;x&amp;quot; as card order. The zone position usually static or irrelevant.&lt;br /&gt;
* So our model is: we have cards, which have some attributes, at any given point in time they belong to a &amp;quot;zone&amp;quot;, and can also have order and state&lt;br /&gt;
* Now for mapping we should consider what information changes and what information is static, later is always candidate for material file&lt;br /&gt;
* For dynamic information we should try to reduce amount of fields we need&lt;br /&gt;
**  we need at least a field for card, so its one&lt;br /&gt;
**  we need to know what zone cards belong to, its 2&lt;br /&gt;
**  and we have possibly few other fields, if you look closely at you game you may find out that most of the zone only need one attribute at a time, i.e. draw pile always have cards face down, hand always face up, also for hand and discard order does not matter at all (but for draw it does matter). So in majority of cases we can get away with one single extra integer field representing state or order&lt;br /&gt;
* In real database both card and zone will be integers as primary keys referring to additional tables, but in our case its total overkill, so they can be strings as easily&lt;br /&gt;
&lt;br /&gt;
Variant 1: Minimalistic&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
CREATE TABLE IF NOT EXISTS `card` (&lt;br /&gt;
  `card_key` varchar(32) unsigned NOT NULL,&lt;br /&gt;
  `card_location` varchar(32) NOT NULL,&lt;br /&gt;
  `card_state` int(11) NOT NULL,&lt;br /&gt;
  PRIMARY KEY (`card_id`)&lt;br /&gt;
) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=1 ;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Variant 2: More normalised&lt;br /&gt;
&lt;br /&gt;
This version supported by Deck php class, so unless you want to rewrite db access layer go with this one&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
CREATE TABLE IF NOT EXISTS `card` (&lt;br /&gt;
  `card_id` int(10) unsigned NOT NULL AUTO_INCREMENT,&lt;br /&gt;
  `card_type` varchar(16) NOT NULL,&lt;br /&gt;
  `card_type_arg` int(11) NOT NULL,&lt;br /&gt;
  `card_location` varchar(16) NOT NULL,&lt;br /&gt;
  `card_location_arg` int(11) NOT NULL,&lt;br /&gt;
  PRIMARY KEY (`card_id`)&lt;br /&gt;
) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=1 ;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note: if you using this schema, some zones/locations have special semantic. The &#039;hand&#039; location is actually multiple locations - one per player, but player id is encoded as card_location_arg. If &#039;hand&#039; in your game is ordered, visible or can have some other card states, you cannot use hand location (replacement is hand_&amp;lt;player_id&amp;gt; or hand_&amp;lt;color_id&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
== Code Organization ==&lt;br /&gt;
&lt;br /&gt;
=== Including your own JavaScript module ===&lt;br /&gt;
&#039;&#039;&#039;Ingredients:&#039;&#039;&#039; ggg.js, modules/ggg_other.js&lt;br /&gt;
&lt;br /&gt;
* Create ggg_other.js in modules/ folder and sync&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
define([&lt;br /&gt;
    &amp;quot;dojo&amp;quot;, &amp;quot;dojo/_base/declare&amp;quot;&lt;br /&gt;
], function( dojo, declare )&lt;br /&gt;
{&lt;br /&gt;
return declare(&amp;quot;bgagame.other&amp;quot;, null, { // null here if we don&#039;t want to inherit from anything&lt;br /&gt;
        constructor: function(){},&lt;br /&gt;
        mystuff: function(){},&lt;br /&gt;
    });&lt;br /&gt;
        &lt;br /&gt;
});&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
* Modify ggg.js to include it&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
  define([ &amp;quot;dojo&amp;quot;, &amp;quot;dojo/_base/declare&amp;quot;, &amp;quot;ebg/core/gamegui&amp;quot;, &amp;quot;ebg/counter&amp;quot;,&lt;br /&gt;
    g_gamethemeurl + &amp;quot;modules/ggg_other.js&amp;quot;     // load my own module!!!&lt;br /&gt;
  ], function(dojo,&lt;br /&gt;
        declare) {&lt;br /&gt;
     &lt;br /&gt;
&lt;br /&gt;
use it&lt;br /&gt;
&lt;br /&gt;
  foo = new bgagame.other();&lt;br /&gt;
&lt;br /&gt;
=== Including your own JavaScript module (II) ===&lt;br /&gt;
&lt;br /&gt;
* Create ggg_other.js in modules/ folder and sync&lt;br /&gt;
&lt;br /&gt;
  define([], function () {&lt;br /&gt;
    return &amp;quot;value&amp;quot;;&lt;br /&gt;
  });&lt;br /&gt;
&lt;br /&gt;
* Modify ggg.js to include it&lt;br /&gt;
&lt;br /&gt;
  define([ &lt;br /&gt;
    &amp;quot;dojo&amp;quot;, &lt;br /&gt;
    &amp;quot;dojo/_base/declare&amp;quot;, &lt;br /&gt;
    &amp;quot;bgagame/modules/ggg_other&amp;quot;, &lt;br /&gt;
    &amp;quot;ebg/core/gamegui&amp;quot;, &lt;br /&gt;
    &amp;quot;ebg/counter&amp;quot;&lt;br /&gt;
  ], function(dojo, declare, other) {&lt;br /&gt;
  &lt;br /&gt;
  });&lt;br /&gt;
&lt;br /&gt;
  &lt;br /&gt;
This is maybe a little bit more the idea of the AMD Loader than the first option, although the first option should work as well.&lt;br /&gt;
&lt;br /&gt;
A little explanation to this:&lt;br /&gt;
The define function loads all the modules listed in the array and calls the following function with these loaded modules as parameters.&lt;br /&gt;
By putting your module at the third position in the array it is passed as the third parameter to the function. Be aware that the modules are resolved by position only, not by name. So you can load the module &#039;&#039;&#039;ggg_other&#039;&#039;&#039; and pass it as a parameter with the name &#039;&#039;&#039;other&#039;&#039;&#039;. &#039;&#039;&#039;gamegui&#039;&#039;&#039; and &#039;&#039;&#039;counter&#039;&#039;&#039; are passed in as well, but when the parameters are not defined they are just skipped. Because these modules put their content into the global scope it does not matter and you can use them from there.&lt;br /&gt;
&lt;br /&gt;
In the example above the string &amp;quot;value&amp;quot; is passed for the parameter &#039;&#039;&#039;other&#039;&#039;&#039;, but the function in your module can return whatever you want. It can be an object, an array, something you declared with dojo.declare, you can return even functions. &lt;br /&gt;
Your module can load other modules. Just put them in the array at the beginning and pass them as parameters to your function.&lt;br /&gt;
The advantage of passing the values as parameter is that you do not need to put these values in the global scope, so they can&#039;t be collisions with values defined in other scripts or the BGA Framework.&lt;br /&gt;
&lt;br /&gt;
The dojo toolkit provides good documentation to all of its components, the complete documentation for the AMD-Loader is here:&lt;br /&gt;
https://dojotoolkit.org/documentation/tutorials/1.10/modules/index.html It should be still correct, even as it seems to be only for version 1.10&lt;br /&gt;
&lt;br /&gt;
=== Including your own PHP module ===&lt;br /&gt;
&#039;&#039;&#039;Ingredients:&#039;&#039;&#039; ggg.game.php, modules/ggg_other.php&lt;br /&gt;
&lt;br /&gt;
* Create ggg_other.php in modules/ folder and sync&lt;br /&gt;
* Modify ggg.game.php to include it&lt;br /&gt;
&lt;br /&gt;
 require_once (&#039;modules/ggg_other.php&#039;);&lt;br /&gt;
&lt;br /&gt;
=== Creating a test class to run PHP locally ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Ingredients:&#039;&#039;&#039; ggg.game.php, stubs&lt;br /&gt;
For this you need stubs of other method you can use this for example&lt;br /&gt;
https://github.com/elaskavaia/bga-sharedcode/raw/master/misc/module/table/table.game.php&lt;br /&gt;
&lt;br /&gt;
Create another php files, i.e ggg_test.php&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;?php&lt;br /&gt;
define(&amp;quot;APP_GAMEMODULE_PATH&amp;quot;, &amp;quot;misc/&amp;quot;); // include path to stubs, which defines &amp;quot;table.game.php&amp;quot; and other classes&lt;br /&gt;
require_once (&#039;eminentdomaine.game.php&#039;);&lt;br /&gt;
&lt;br /&gt;
class MyGameTest1 extends MyGame { // this is your game class defined in ggg.game.php&lt;br /&gt;
    function __construct() {&lt;br /&gt;
        parent::__construct();&lt;br /&gt;
        include &#039;../material.inc.php&#039;;// this is how this normally included, from constructor&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // override/stub methods here that access db and stuff&lt;br /&gt;
    function getGameStateValue($var) {&lt;br /&gt;
        if ($var == &#039;round&#039;)&lt;br /&gt;
            return 3;&lt;br /&gt;
        return 0;&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
$x = new MyGameTest1(); // instantiate your class&lt;br /&gt;
$p = $x-&amp;gt;getGameProgression(); // call one of the methods to test&lt;br /&gt;
if ($p != 50)&lt;br /&gt;
    echo &amp;quot;Test1: FAILED&amp;quot;;&lt;br /&gt;
else&lt;br /&gt;
    echo &amp;quot;Test1: PASSED&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Run from command line like&lt;br /&gt;
 php7 ggg_test.php&lt;br /&gt;
&lt;br /&gt;
If you do it this way - you can also use local php debugger (i.e. integrated with IDE or command line).&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Avoiding code in dojo declare style ===&lt;br /&gt;
Dojo class declarations are rather bizzare and do not work with most IDEs.&lt;br /&gt;
If you want to write in plain JS with classes, you can stub all the dojo define/declare stuff&lt;br /&gt;
and hook your class into that, so the classes are outside of this mess.&lt;br /&gt;
&lt;br /&gt;
NOTE: this technique is for experienced developers, do not try it if you do not understand&lt;br /&gt;
the consequences.&lt;br /&gt;
&lt;br /&gt;
This is complete example of game .js class&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  // Testla is game name is has to be changed&lt;br /&gt;
class Testla {&lt;br /&gt;
	constructor(game) {&lt;br /&gt;
		console.log(&#039;game constructor&#039;);&lt;br /&gt;
		this.game = game;&lt;br /&gt;
		this.varfoo = new MyFoo(); // this example of class from custom module&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	setup(gamedatas) {&lt;br /&gt;
		console.log(&amp;quot;Starting game setup&amp;quot;, this.varfoo);&lt;br /&gt;
		this.gamedatas = gamedatas;&lt;br /&gt;
		this.dojo.create(&amp;quot;div&amp;quot;, { class: &#039;whiteblock&#039;, innerHTML: _(&amp;quot;hello&amp;quot;) }, &#039;thething&#039;);&lt;br /&gt;
		console.log(&amp;quot;Ending game setup&amp;quot;);&lt;br /&gt;
	};&lt;br /&gt;
	onEnteringState(stateName, args) {&lt;br /&gt;
		console.log(&#039;onEnteringState : &#039; + stateName, args);&lt;br /&gt;
		this.game.addActionButton(&#039;b1&#039;,_(&#039;Click Me&#039;), (e)=&amp;gt;this.onButtonClick(e));&lt;br /&gt;
	};&lt;br /&gt;
	onLeavingState(stateName) {&lt;br /&gt;
		console.log(&#039;onLeavingState : &#039; + stateName, args);&lt;br /&gt;
	};&lt;br /&gt;
	onUpdateActionButtons(stateName, args) {&lt;br /&gt;
		console.log(&#039;onUpdateActionButtons : &#039; + stateName, args);&lt;br /&gt;
	};&lt;br /&gt;
	onButtonClick(event) {&lt;br /&gt;
		console.log(&#039;onButtonClick&#039;,event);&lt;br /&gt;
	};&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
define([&lt;br /&gt;
	&amp;quot;dojo&amp;quot;, &amp;quot;dojo/_base/declare&amp;quot;,&lt;br /&gt;
	&amp;quot;ebg/core/gamegui&amp;quot;,&lt;br /&gt;
	&amp;quot;ebg/counter&amp;quot;,&lt;br /&gt;
	g_gamethemeurl + &#039;/modules/foo.js&#039; // custom module if needed&lt;br /&gt;
],&lt;br /&gt;
	function(dojo, declare) {&lt;br /&gt;
                // testla is game name is has to be changed&lt;br /&gt;
		return declare(&amp;quot;bgagame.testla&amp;quot;, ebg.core.gamegui, {&lt;br /&gt;
			constructor: function() {&lt;br /&gt;
				this.xapp = new Testla(this);&lt;br /&gt;
				this.xapp.dojo = dojo;&lt;br /&gt;
			},&lt;br /&gt;
			setup: function(gamedatas) {&lt;br /&gt;
				this.xapp.setup(gamedatas);&lt;br /&gt;
			},&lt;br /&gt;
			onEnteringState: function(stateName, args) {&lt;br /&gt;
				this.xapp.onEnteringState(stateName, args?.args);&lt;br /&gt;
			},&lt;br /&gt;
			onLeavingState: function(stateName) {&lt;br /&gt;
				this.xapp.onLeavingState(stateName, args);&lt;br /&gt;
			},&lt;br /&gt;
			onUpdateActionButtons: function(stateName, args) {&lt;br /&gt;
				this.xapp.onUpdateActionButtons(stateName, args);&lt;br /&gt;
			},&lt;br /&gt;
		});&lt;br /&gt;
	});&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== More readable JS: onEnteringState ===&lt;br /&gt;
&lt;br /&gt;
If you have a lot of states in onEnteringState or onUpdateActionButtons and friends - it becomes rather wild, you can do this trick to call some methods dynamically.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
     onEnteringState: function(stateName, args) {&lt;br /&gt;
       console.log(&#039;Entering state: &#039; + stateName, args);&lt;br /&gt;
&lt;br /&gt;
       // Call appropriate method&lt;br /&gt;
       var methodName = &amp;quot;onEnteringState_&amp;quot; + stateName;&lt;br /&gt;
       if (this[methodName] !== undefined) {             &lt;br /&gt;
          console.log(&#039;Calling &#039; + methodName, args.args);&lt;br /&gt;
          this[methodName](args.args);&lt;br /&gt;
       }&lt;br /&gt;
     },&lt;br /&gt;
&lt;br /&gt;
     onEnteringState_playerTurn: function(args) { // this is args directly, not args.args &lt;br /&gt;
         // process&lt;br /&gt;
     },&lt;br /&gt;
&lt;br /&gt;
     onEnteringState_playerSomethingElse: function(args) { &lt;br /&gt;
         // process&lt;br /&gt;
     },&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note: since its ignores the undefined functions you don&#039;t have define function for each state, but on the other hand you cannot make typos.&lt;br /&gt;
Same applies to onUpdateActionButtons except you pass &#039;args&#039; to method, not args.args, and for onLeavingState where you don&#039;t pass anything.&lt;br /&gt;
&lt;br /&gt;
=== Frameworks and Preprocessors ===&lt;br /&gt;
&lt;br /&gt;
* [[BGA Type Safe Template]] - Setting up a fully typed project using typescript and more!&lt;br /&gt;
* [[Using Vue]] - work-in-progress guide on using the modern framework Vue.js to create a game&lt;br /&gt;
* [[Using Typescript and Scss]] - How to auto-build Typescript and SCSS files to make your code cleaner&lt;br /&gt;
&lt;br /&gt;
== Backend ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Assigning Player Order ===&lt;br /&gt;
Normally when game starts there is &amp;quot;natural&amp;quot; player order assigned randomly.&lt;br /&gt;
&lt;br /&gt;
If you want to deliberatly assign player order at the start of the game (for example, in a game with teams options), you can do so by retrieving the initialization-only player attribute &#039;&#039;&#039;player_table_order&#039;&#039;&#039; and using it to assign values to &#039;&#039;&#039;player_no&#039;&#039;&#039; (which is normally assigned at the start of a game in the order in which players come to the table). (See [https://en.doc.boardgamearena.com/Game_database_model:_dbmodel.sql#The_player_table Game database model] for more details.)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Example:&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
                // Retrieve inital player order ([0=&amp;gt;playerId1, 1=&amp;gt;playerId2, ...])&lt;br /&gt;
		$playerInitialOrder = [];&lt;br /&gt;
		foreach ($players as $playerId =&amp;gt; $player) {&lt;br /&gt;
			$playerInitialOrder[$player[&#039;player_table_order&#039;]] = $playerId;&lt;br /&gt;
		}&lt;br /&gt;
		ksort($playerInitialOrder);&lt;br /&gt;
		$playerInitialOrder = array_flip(array_values($playerInitialOrder));&lt;br /&gt;
&lt;br /&gt;
		// Player order based on &#039;playerTeams&#039; option&lt;br /&gt;
		$playerOrder = [0, 1, 2, 3];&lt;br /&gt;
		switch ($this-&amp;gt;getGameStateValue(&#039;playerTeams&#039;)) {&lt;br /&gt;
			case $this-&amp;gt;TEAM_1_2:&lt;br /&gt;
				$playerOrder = [0, 2, 1, 3];&lt;br /&gt;
				break;&lt;br /&gt;
			case $this-&amp;gt;TEAM_1_4:&lt;br /&gt;
				$playerOrder = [0, 1, 3, 2];&lt;br /&gt;
				break;&lt;br /&gt;
			case $this-&amp;gt;TEAM_RANDOM:&lt;br /&gt;
				shuffle($playerOrder);&lt;br /&gt;
				break;&lt;br /&gt;
			default:&lt;br /&gt;
			case $this-&amp;gt;TEAM_1_3:&lt;br /&gt;
				// Default order&lt;br /&gt;
				break;&lt;br /&gt;
		}&lt;br /&gt;
&lt;br /&gt;
                // Create players&lt;br /&gt;
		// Note: if you added some extra field on &amp;quot;player&amp;quot; table in the database (dbmodel.sql), you can initialize it there.&lt;br /&gt;
		$sql =&lt;br /&gt;
			&#039;INSERT INTO player (player_id, player_color, player_canal, player_name, player_avatar, player_no) VALUES &#039;;&lt;br /&gt;
		$values = [];&lt;br /&gt;
&lt;br /&gt;
		foreach ($players as $playerId =&amp;gt; $player) {&lt;br /&gt;
			$color = array_shift($default_colors);&lt;br /&gt;
			$values[] =&lt;br /&gt;
				&amp;quot;(&#039;&amp;quot; .&lt;br /&gt;
				$playerId .&lt;br /&gt;
				&amp;quot;&#039;,&#039;$color&#039;,&#039;&amp;quot; .&lt;br /&gt;
				$player[&#039;player_canal&#039;] .&lt;br /&gt;
				&amp;quot;&#039;,&#039;&amp;quot; .&lt;br /&gt;
				addslashes($player[&#039;player_name&#039;]) .&lt;br /&gt;
				&amp;quot;&#039;,&#039;&amp;quot; .&lt;br /&gt;
				addslashes($player[&#039;player_avatar&#039;]) .&lt;br /&gt;
				&amp;quot;&#039;,&#039;&amp;quot; .&lt;br /&gt;
				$playerOrder[$playerInitialOrder[$playerId]] .&lt;br /&gt;
				&amp;quot;&#039;)&amp;quot;;&lt;br /&gt;
		}&lt;br /&gt;
		$sql .= implode(&#039;,&#039;, $values);&lt;br /&gt;
		$this-&amp;gt;DbQuery($sql);&lt;br /&gt;
		$this-&amp;gt;reattributeColorsBasedOnPreferences(&lt;br /&gt;
			$players,&lt;br /&gt;
			$gameinfos[&#039;player_colors&#039;]&lt;br /&gt;
		);&lt;br /&gt;
		$this-&amp;gt;reloadPlayersBasicInfos();&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Send different notifications to active player vs everybody else ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Ingredients:&#039;&#039;&#039; ggg.js&lt;br /&gt;
&lt;br /&gt;
Hack alert. This is a hack. We were hoping for proper solution by bga framework.&lt;br /&gt;
&lt;br /&gt;
This will allow you to send notification with two message one for specific player and one for everybody else including spectators.&lt;br /&gt;
Note that this does not split the data - all data must be shared.&lt;br /&gt;
&lt;br /&gt;
Add this to .js file (if you already overriding it merge obviously)&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
/** @Override */&lt;br /&gt;
format_string_recursive: function(log, args) {&lt;br /&gt;
   if (typeof args.log_others != &#039;undefined&#039; &amp;amp;&amp;amp; typeof args.player_id != &#039;undefined&#039; &amp;amp;&amp;amp; this.player_id != args.player_id)&lt;br /&gt;
	log = args.log_others;&lt;br /&gt;
   return this.inherited(arguments); // you must call this to call super &lt;br /&gt;
},&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Example of usage (from eminentdomain)&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    $this-&amp;gt;notifyAllPlayers(&#039;tokenMoved&#039;, &lt;br /&gt;
             clienttranslate(&#039;${player_name} adds +2 Colonies to ${place_name}&#039;), // notification with show for player with player_id&lt;br /&gt;
             [&#039;player_id&#039;=&amp;gt;$player_id, // this is mandatory&lt;br /&gt;
             &#039;log_others&#039;=&amp;gt;clienttranslate(&#039;${player_name} adds +2 Colonies to an unknown planet&#039;), // notification will show for others&lt;br /&gt;
              ...&lt;br /&gt;
             ]);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Send transient notifications without incrementing move ID ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Ingredients:&#039;&#039;&#039; ggg.php&lt;br /&gt;
&lt;br /&gt;
Hack alert. This is a hack.&lt;br /&gt;
&lt;br /&gt;
Use this if you need to send some transient notification that should not create a new move ID. The notification should be idempotent -- it should have no practical effect on the game state and would be &#039;&#039;&#039;safe to drop&#039;&#039;&#039; (e.g., it would not matter if a player never received this notification). For example, in a co-op game you want all players to see a real-time preview of some action, before the active player commits their turn.&lt;br /&gt;
&lt;br /&gt;
Doing this mainly affects the instant replay &amp;amp; archive modes. During replay, the BGA framework automatically inserts a 1.5-second pause between each &amp;quot;move&amp;quot;. With this hack, your transient notifications are not considered to be a &amp;quot;move&amp;quot;, so no pause gets added.&lt;br /&gt;
&lt;br /&gt;
; In ggg.php&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$this-&amp;gt;not_a_move_notification = true; // note: do not increase the move counter&lt;br /&gt;
$this-&amp;gt;notifyAllPlayers(&#039;cardsPreview&#039;, &#039;&#039;, $args);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note: you cannot have code that send notification or even changes state after this, and you cannot reset this variable back either because it only takes effect when you exit action handling function&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Assorted Stuff ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Out-of-turn actions: Un-pass ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Ingredients:&#039;&#039;&#039; ggg.js, ggg.game.php, ggg.action.php, states.inc.php&lt;br /&gt;
&lt;br /&gt;
In multiplayer game sometimes players passes but than they think more and want to un-Pass and redo their choice. &lt;br /&gt;
To re-active a player who passes some trickery required.&lt;br /&gt;
&lt;br /&gt;
Define a special action that does that and hook it up.&lt;br /&gt;
&lt;br /&gt;
In states.inc.php add an action to multipleactiveplayer state to &amp;quot;unpass&amp;quot;, lets call it &amp;quot;actionCancel&amp;quot;&lt;br /&gt;
&lt;br /&gt;
In ggg.action.php add action hook&lt;br /&gt;
    public function actionCancel() {&lt;br /&gt;
        $this-&amp;gt;setAjaxMode();&lt;br /&gt;
        $this-&amp;gt;game-&amp;gt;actionCancel();&lt;br /&gt;
        $this-&amp;gt;ajaxResponse();&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
In ggg.game.php add action handler&lt;br /&gt;
    function actionCancel() {&lt;br /&gt;
        $this-&amp;gt;gamestate-&amp;gt;checkPossibleAction(&#039;actionCancel&#039;);&lt;br /&gt;
        $this-&amp;gt;gamestate-&amp;gt;setPlayersMultiactive(array ($this-&amp;gt;getCurrentPlayerId() ), &#039;error&#039;, false);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
Finally to call this in client ggg.js you would do something like:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 onUpdateActionButtons:  function(stateName, args) {&lt;br /&gt;
   if (this.isCurrentPlayerActive()) { &lt;br /&gt;
     // ...&lt;br /&gt;
   } else if (!this.isSpectator) { // player is NOT active but not spectator&lt;br /&gt;
       switch (stateName) {&lt;br /&gt;
          case &#039;playerTurnMultiPlayerState&#039;:&lt;br /&gt;
		this.addActionButton(&#039;button_unpass&#039;, _(&#039;Oh no!&#039;), &#039;onUnpass&#039;);&lt;br /&gt;
		break;&lt;br /&gt;
	}&lt;br /&gt;
   }&lt;br /&gt;
 }&lt;br /&gt;
				&lt;br /&gt;
 onUnpass: function(e) {&lt;br /&gt;
    this.bgaPerformAction(&amp;quot;actionCancel&amp;quot;, null, { checkAction: false }); // no checkAction!&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Although be careful that if the turn comes back to the player while he is about to click cancel, the action buttons will be updated and the player will misclick which can be quite frustrating. To avoid this, move the cancel button to another position, like to the left of pagemaintitletext:&lt;br /&gt;
  dojo.place(&#039;button_unpass&#039;, &#039;pagemaintitletext&#039;, &#039;before&#039;);&lt;br /&gt;
Being out of the generalactions div, it won&#039;t be automatically destroyed like normal buttons, so you&#039;ll have to handle that yourself in onLeavingState. You might also want to change the button color to red (blue buttons for active player only, red buttons also for inactive players?)&lt;br /&gt;
&lt;br /&gt;
Note: same technique can be used to do other out-of-turn actions, such as re-arranging cards in hand, exchanging resources, etc (i.e. if permitted by rules, such as &amp;quot;at any time player can...&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
=== Multi Step Interactions: Select Worker/Place Worker - Using Selection ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Ingredients:&#039;&#039;&#039; ggg.js&lt;br /&gt;
&lt;br /&gt;
Simple way to implement something like that without extra states is to use &amp;quot;selection&amp;quot; mechanism. When user click on worker add some sort of class into that element i.e. &#039;selected&#039; (which also have to have some indication by css i.e. outline).&lt;br /&gt;
&lt;br /&gt;
Than user can click on placement zone, you can use dojo.query for &amp;quot;selected&amp;quot; element and use it along with zone id to send data to server. If proper worker is not selected yet can give a error message using this.showMessage(...) function.&lt;br /&gt;
&lt;br /&gt;
Extra code required to properly cleanup selection between states.&lt;br /&gt;
Also when you do that sometimes you want to change the state prompt, see below &#039;Change state prompt&#039;&lt;br /&gt;
&lt;br /&gt;
=== Multi Step Interactions: Select Worker/Place Worker - Using Client States ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Ingredients:&#039;&#039;&#039; ggg.js&lt;br /&gt;
&lt;br /&gt;
I don&#039;t think its documented feature but there is a way to do client-only states, which is absolutely wonderful for few reasons&lt;br /&gt;
* When player interaction is two step process, such as select worker, place worker, or place worker, pick one of two resources of your choice&lt;br /&gt;
* When multi-step process can result of impossible situation and has to be undone (by rules)&lt;br /&gt;
* When multi-step process is triggered from multiple states (such as you can do same thing as activated card action, pass action or main action)&lt;br /&gt;
&lt;br /&gt;
So lets do Select Worker/Place Worker&lt;br /&gt;
&lt;br /&gt;
Define your server state as usual, i.e. playerMainTurn -&amp;gt; &amp;quot;You must pick up a worker&amp;quot;.&lt;br /&gt;
Now define a client state, we only need &amp;quot;name&amp;quot; and &amp;quot;descriptionmyturn&amp;quot;, lets say &amp;quot;client_playerPicksLocation&amp;quot;. Always prefix names of client state with &amp;quot;client_&amp;quot; to avoid confusion. Now we have to do the following:&lt;br /&gt;
* Have a handler for onUpdateActionButtons for playerMainTurn to activate all possible workers he can pick&lt;br /&gt;
* When player clicks workers, remember the worker in one of the members of the main class, I usually use one called this.clientStateArgs.&lt;br /&gt;
* Transition to new client state&lt;br /&gt;
  onWorker: function(e) {&lt;br /&gt;
      var id = event.currentTarget.id;&lt;br /&gt;
      dojo.stopEvent(event);&lt;br /&gt;
      ... // do validity checks&lt;br /&gt;
      this.clientStateArgs.worker_id = id;&lt;br /&gt;
      this.setClientState(&amp;quot;client_playerPicksLocation&amp;quot;, {&lt;br /&gt;
                                descriptionmyturn : _(&amp;quot;${you} must select location&amp;quot;),&lt;br /&gt;
                            });&lt;br /&gt;
   }&lt;br /&gt;
* Have a handler for onUpdateActionButtons for client_playerPicksLocation to activate all possible locations this worker can go AND add Cancel button (see below)&lt;br /&gt;
* Have a location handler which will eventually send a server request, using stored this.clientStateArgs.worker_id as worker id&lt;br /&gt;
* The cancel button should call a method to restore server state, also if you doing it for more than one state you can add this universally using this.on_client_state check&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
        if (this.isCurrentPlayerActive()) {&lt;br /&gt;
          if (this.on_client_state &amp;amp;&amp;amp; !$(&#039;button_cancel&#039;)) {&lt;br /&gt;
               this.addActionButton(&#039;button_cancel&#039;, _(&#039;Cancel&#039;), dojo.hitch(this, function() {&lt;br /&gt;
                                             this.restoreServerGameState();&lt;br /&gt;
               }));&lt;br /&gt;
          }&lt;br /&gt;
        } &lt;br /&gt;
Note: usually I call my own function call this.cancelLocalStateEffects() which will do more stuff first then call restoreServerGameState(), same function is usually needs to be called when server request has failed (i.e. invalid move)&lt;br /&gt;
&lt;br /&gt;
Note: If you need more than 2 steps, you may have to do client side animation to reflect the new state, which gets trickier because you have to undo that also on cancellation.&lt;br /&gt;
&lt;br /&gt;
Code is available here [https://github.com/elaskavaia/bga-sharedcode/blob/master/sharedcode.js sharedcode.js] (its using playerTurnPlayCubes and client_selectCubeLocation).&lt;br /&gt;
&lt;br /&gt;
=== Action Stack - Using Client States ===&lt;br /&gt;
&lt;br /&gt;
Action stack required where game is very complex and use triggered effects that can &amp;quot;stack&amp;quot;. It not always actual stack, it can be queue or random access&lt;br /&gt;
Examples:&lt;br /&gt;
* Magic the Gathering - classic card game where effects go on Stack, that allows to counter spell and counter spell of counter spell (not on bga - it just example of mechanics)&lt;br /&gt;
* Ultimate Railroads - action taking game where effects can be executed in any order&lt;br /&gt;
* Lewis and Clark - card game where actions executed as queue&lt;br /&gt;
&lt;br /&gt;
There is two ways of implementing it - on the server or the client.&lt;br /&gt;
For the server see article below.&lt;br /&gt;
The requirement for client side stack implementation is - all action can be undone, which means&lt;br /&gt;
* No dice rolls&lt;br /&gt;
* No card drawn&lt;br /&gt;
* No other players interaction&lt;br /&gt;
&lt;br /&gt;
No snippets are here, as this will be too complex but basically flow is:&lt;br /&gt;
* You have a action/effect stack (queue/list) as js object attached to &amp;quot;this&amp;quot;, i.e. this.unprocessed_actions&lt;br /&gt;
* When player plays a card, worker, etc, you read the effect of that card from the material file (client copy), and place into stack&lt;br /&gt;
* Then we call dispatch method which pulls the next action from the stack and change client state accordinly, i.e. this.setClientState(&amp;quot;client_playerGainsCubes&amp;quot;)&lt;br /&gt;
* When players acts on it - the action is removed from the stack and added to &amp;quot;server action arguments&amp;quot; list, this is another object which be used to send ajax call, i.e. this.clientStateArgs&lt;br /&gt;
* If nothing left in stack we can submit the ajax call assembling parameters from collected arguments (that can include action name)&lt;br /&gt;
* This method allows cheap undo - by restoring server state you will wipe out all user actions (but if you need intermediate aninmation you have to handle it yourself)&lt;br /&gt;
&lt;br /&gt;
Code can be found in Ultimate Railroads game (but it is random access list - so it a bit complex) and Lewis and Clark (complexity - user can always deny part of any effect)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Action Stack - Using Server States ===&lt;br /&gt;
&lt;br /&gt;
See definition of Action Stack above.&lt;br /&gt;
&lt;br /&gt;
To implement you usually need another db table that has the following fields: index of effect - which is used for sorted access, type - which is essense of the effect (i.e. collect resource), some extra arguments (i.e. resource type and resource count), and usually owner of the effect (i.e. player id)&lt;br /&gt;
The flow is:&lt;br /&gt;
* There is some initial player state, where player can play card for example&lt;br /&gt;
* Player main action - pushes the card effect on stack, which also can cause triggered effects which also go on stack&lt;br /&gt;
* After action processing is finished switch to game state which is &amp;quot;dispatcher&amp;quot;&lt;br /&gt;
* Dispatcher pulls the top effect (whatever definition of the top is), changes the active player and changes the state to appropriate player state to collect response. The &amp;quot;top&amp;quot; can be choice of multiple actions, in this case player has to chose one before resolving the effect.&lt;br /&gt;
* Player state knows about the stack and pulls arguments (argX) from the effect arguments of the db&lt;br /&gt;
* Player action should clear up the top effect, and can possibly add more effects, then switch to &amp;quot;dispatcher&amp;quot; state again&lt;br /&gt;
* If stack is empty, dispatcher can either pick next player itself or use another game state which responsible for picking next player&lt;br /&gt;
&lt;br /&gt;
Code can be found in Tapestry and Terraforming Mars.&lt;br /&gt;
=== Custom error/exception handling in JavaScript ===&lt;br /&gt;
&lt;br /&gt;
; In ggg.php&lt;br /&gt;
Throw BgaUserException with some easy-to-identify prefix such as &amp;quot;!!!&amp;quot; and a custom error code. DO NOT TRANSLATE this message text. The exception will rollback database transaction and cancel all changes (including any notifications).&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    function foo(bool $didConfirm = false): void&lt;br /&gt;
    {&lt;br /&gt;
        // do processing for the user&#039;s move&lt;br /&gt;
        // afterwards, you determine this move will end the game&lt;br /&gt;
        // so you want to rollback the transaction and require the user to confirm the move first&lt;br /&gt;
&lt;br /&gt;
        if ($gameIsEnding &amp;amp;&amp;amp; !$didConfirm) {&lt;br /&gt;
            throw new BgaUserException(&#039;!!!endGameConfirm&#039;, 9001);&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
; In ggg.js&lt;br /&gt;
Override framework function showMessage to suppress the red banner message and gamelog message when you detect the &amp;quot;!!!&amp;quot; prefix&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    /* @Override */&lt;br /&gt;
    showMessage: function (msg, type) {&lt;br /&gt;
      if (type == &amp;quot;error&amp;quot; &amp;amp;&amp;amp; msg &amp;amp;&amp;amp; msg.startsWith(&amp;quot;!!!&amp;quot;)) {&lt;br /&gt;
        return; // suppress red banner and gamelog message&lt;br /&gt;
      }&lt;br /&gt;
      this.inherited(arguments);&lt;br /&gt;
    },&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Deal with the error in your callback:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    fooAction: function (didConfirm) {&lt;br /&gt;
      var data = {&lt;br /&gt;
        foo: &amp;quot;bar&amp;quot;,&lt;br /&gt;
        didConfirm: !!didConfirm,&lt;br /&gt;
      };&lt;br /&gt;
      this.bgaPerformAction(&amp;quot;fooAction&amp;quot;, data).catch((error, errorMsg) =&amp;gt; {&lt;br /&gt;
        if (error &amp;amp;&amp;amp; errorMsg == &amp;quot;!!!endGameConfirm&amp;quot;) {&lt;br /&gt;
          // your custom error handling goes here&lt;br /&gt;
          // for example, show a confirmation dialog and repeat the action with additional param&lt;br /&gt;
          this.confirmationDialog(&lt;br /&gt;
            _(&amp;quot;Doing the foo action now will end the game&amp;quot;),&lt;br /&gt;
            () =&amp;gt; this.fooAction(true)&lt;br /&gt;
          );&lt;br /&gt;
        }&lt;br /&gt;
      });&lt;br /&gt;
    },&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
For custom global error handling, you could modify ajaxcallwrapper:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  ajaxcallwrapper: function (action, args, handler) {&lt;br /&gt;
    if (!args) args = {};&lt;br /&gt;
    args.lock = true;&lt;br /&gt;
    args.version = this.gamedatas.version;&lt;br /&gt;
    if (this.checkAction(action)) {&lt;br /&gt;
      this.bgaPerformAction(&lt;br /&gt;
        action,&lt;br /&gt;
        args&lt;br /&gt;
      ).catch((error, errorMsg, errorCode) =&amp;gt; {&lt;br /&gt;
          if (error &amp;amp;&amp;amp; errorMsg == &amp;quot;!!!checkVersion&amp;quot;) {&lt;br /&gt;
            this.infoDialog(&lt;br /&gt;
              _(&amp;quot;A new version of this game is now available&amp;quot;),&lt;br /&gt;
              _(&amp;quot;Reload Required&amp;quot;),&lt;br /&gt;
              () =&amp;gt; {&lt;br /&gt;
                window.location.reload();&lt;br /&gt;
              },&lt;br /&gt;
              true&lt;br /&gt;
            );&lt;br /&gt;
          } else {&lt;br /&gt;
            if (handler) handler(error, errorMsg, errorCode);&lt;br /&gt;
          }&lt;br /&gt;
        }&lt;br /&gt;
      );&lt;br /&gt;
    }&lt;br /&gt;
  },&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Force players to refresh after new deploy ===&lt;br /&gt;
&lt;br /&gt;
When you deploy a new version of your game, the PHP backend code is immediately updated but the JavaScript/HTML/CSS frontend code *does not update* for active players until they manually refresh the page (F5) in their browser. Obviously this is not ideal. In the best case, real-time tables don&#039;t see your shiny new enhancements. In the worst case, your old JS code isn&#039;t compatible with your new PHP code and the game breaks in strange ways (any bug reports filed will be false positives and unable to reproduce). To avoid any problems, you should force all players to immediately reload the page following a new deploy.&lt;br /&gt;
&lt;br /&gt;
By throwing a &amp;quot;visible&amp;quot; exception (simplest solution), you&#039;ll get something like this which instructs the user to reload:&lt;br /&gt;
&lt;br /&gt;
[[File:Force-refresh.png|950x950px]]&lt;br /&gt;
&lt;br /&gt;
Or, if you combine this technique with the above custom error handling technique, you could do something a bit nicer. You could show a dialog box and automatically refresh the page when the user clicks &amp;quot;OK&amp;quot;:&lt;br /&gt;
&lt;br /&gt;
[[File:Reload-required.png|500x500px]]&lt;br /&gt;
; In ggg.php&lt;br /&gt;
Transmit the server version number in &amp;lt;code&amp;gt;getAllDatas()&amp;lt;/code&amp;gt;.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    protected function getAllDatas(): array&lt;br /&gt;
    {&lt;br /&gt;
        $players = $this-&amp;gt;getCollectionFromDb(&amp;quot;SELECT player_id id, player_score score FROM player&amp;quot;);&lt;br /&gt;
        return [&lt;br /&gt;
            &#039;players&#039; =&amp;gt; $players,&lt;br /&gt;
            &#039;version&#039; =&amp;gt; intval($this-&amp;gt;gamestate-&amp;gt;table_globals[300]), // &amp;lt;-- ADD HERE&lt;br /&gt;
            ...&lt;br /&gt;
        ];&lt;br /&gt;
    }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Create a helper function to fail if the client and server versions mismatch. Note the version check uses &amp;lt;code&amp;gt;!=&amp;lt;/code&amp;gt; instead of &amp;lt;code&amp;gt;&amp;amp;lt;&amp;lt;/code&amp;gt; so it can support rollback to a previous deploy as well. ;-)&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    public function checkVersion(int $clientVersion): void&lt;br /&gt;
    {&lt;br /&gt;
        if ($clientVersion != intval($this-&amp;gt;gamestate-&amp;gt;table_globals[300])) {&lt;br /&gt;
            // Simplest way is to throw a &amp;quot;visible&amp;quot; exception&lt;br /&gt;
            // It&#039;s ugly but comes with a &amp;quot;click here&amp;quot; link to refresh&lt;br /&gt;
            throw new BgaVisibleSystemException($this-&amp;gt;_(&amp;quot;A new version of this game is now available. Please reload the page (F5).&amp;quot;));&lt;br /&gt;
&lt;br /&gt;
            // For something prettier, throw a &amp;quot;user&amp;quot; exception and handle in JS&lt;br /&gt;
            // (see BGA cookbook section above on custom error handling)&lt;br /&gt;
            throw new BgaUserException(&#039;!!!checkVersion&#039;);&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
; In ggg.action.php&lt;br /&gt;
Create a helper function for actions:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  private function checkVersion()&lt;br /&gt;
  {&lt;br /&gt;
    $clientVersion = (int) $this-&amp;gt;getArg(&#039;version&#039;, AT_int, false);&lt;br /&gt;
    $this-&amp;gt;game-&amp;gt;checkVersion($clientVersion);&lt;br /&gt;
  }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Call &amp;lt;code&amp;gt;$this-&amp;gt;checkVersion()&amp;lt;/code&amp;gt; at the top of &amp;lt;b&amp;gt;every action function&amp;lt;/b&amp;gt;, immediately after &amp;lt;code&amp;gt;$this-&amp;gt;setAjaxMode()&amp;lt;/code&amp;gt;:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  public function move()&lt;br /&gt;
  {&lt;br /&gt;
    $this-&amp;gt;setAjaxMode();&lt;br /&gt;
    $this-&amp;gt;checkVersion(); // &amp;lt;-- ADD HERE&lt;br /&gt;
    ...&lt;br /&gt;
    $this-&amp;gt;ajaxResponse();&lt;br /&gt;
  }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
; In ggg.js&lt;br /&gt;
Transmit the version (from gamedatas) as a parameter with every ajax call. For example, if you&#039;re already using a wrapper function for every ajax call, add it like this:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  ajaxcallwrapper: function (action, args) {&lt;br /&gt;
    if (!args) args = {};&lt;br /&gt;
    args.version = this.gamedatas.version; // &amp;lt;-- ADD HERE&lt;br /&gt;
    this.bgaPerformAction(action, args);&lt;br /&gt;
  },&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Disable / lock table creation for new deploy ===&lt;br /&gt;
&lt;br /&gt;
If you are deploying a major new game version, especially if it involves upgrading production game databases, you may have a lot of angry players if you break their tables.  Depending on your changes, you may be able to restore the previous version and fix the tables easily.&lt;br /&gt;
&lt;br /&gt;
However, if a new deploy turns out bad and players created turn-based tables while it was live, it may be quite difficult to fix those tables, since they were created from a bad deploy.&lt;br /&gt;
&lt;br /&gt;
The solution?  You can announce in your game group that you are locking table creation, and then in your new version, add an impossible startcondition to an existing option.  &lt;br /&gt;
Note: This only makes sense if you have a few games running in real time mode in the time of deployment, otherwise it won&#039;t achieve much, unless you wait at least a day for other turn based games to break (or not)&lt;br /&gt;
&lt;br /&gt;
Here is an example of an option with only 2 values (if you don&#039;t have options at all you have to create a fake option to use this method, if you have more values - you have to list them all):&lt;br /&gt;
&lt;br /&gt;
; In gameoptions.json&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        &amp;quot;startcondition&amp;quot;: {&lt;br /&gt;
            &amp;quot;0&amp;quot;: [ { &amp;quot;type&amp;quot;: &amp;quot;minplayers&amp;quot;, &amp;quot;value&amp;quot;: 32, &amp;quot;message&amp;quot;: &amp;quot;Maintenance in progress.  Table creation is disabled.&amp;quot; } ],&lt;br /&gt;
            &amp;quot;1&amp;quot;: [ { &amp;quot;type&amp;quot;: &amp;quot;minplayers&amp;quot;, &amp;quot;value&amp;quot;: 32, &amp;quot;message&amp;quot;: &amp;quot;Maintenance in progress.  Table creation is disabled.&amp;quot; } ]&lt;br /&gt;
        },&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
; In gameoptions.inc.php (older method if you have it in php)&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
// TODO NEXT remove after testing deploy to upgrade, here 0 and 1 - replace with values of your option!&lt;br /&gt;
&#039;startcondition&#039; =&amp;gt; [&lt;br /&gt;
   0 =&amp;gt; [ [ &#039;type&#039; =&amp;gt; &#039;minplayers&#039;, &#039;value&#039; =&amp;gt; 32, &#039;message&#039; =&amp;gt; totranslate(&#039;Maintenance in progress.  Table creation is disabled.&#039;) ] ],&lt;br /&gt;
   1 =&amp;gt; [ [ &#039;type&#039; =&amp;gt; &#039;minplayers&#039;, &#039;value&#039; =&amp;gt; 32, &#039;message&#039; =&amp;gt; totranslate(&#039;Maintenance in progress.  Table creation is disabled.&#039;) ] ],&lt;br /&gt;
],&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Be sure to click &amp;quot;Reload game options configuration&amp;quot; after making this change, then test in studio (test that you cannot create any table)&lt;br /&gt;
* Deploy to production&lt;br /&gt;
* Now, when a player attempts to create a new table, they will see a red error bar with your &amp;quot;Maintenance in progress&amp;quot; message.  &lt;br /&gt;
* Wait for screaming (if you have real times games in progress waiting 15 min probably ok, if you have only turn based games, probably a day)&lt;br /&gt;
* Once you confirm the new deploy looks good, you can revert the change in gameoptions.inc.php and do another deploy.&lt;br /&gt;
&lt;br /&gt;
=== Local Storage ===&lt;br /&gt;
&lt;br /&gt;
There is not much you can store in localStorage (https://developer.mozilla.org/docs/Web/API/Window/localStorage), since most stuff should be stored either in game db or in user prefrences,&lt;br /&gt;
but some stuff makes sense to store there, for example &amp;quot;zoom&amp;quot; level (if you use custom zooming). This setting really affect this specific host and specific browser, setting it localStorage makes most sense.&lt;br /&gt;
&lt;br /&gt;
game.js&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
   setup: function (gamedatas) {&lt;br /&gt;
        let zoom = localStorage.getItem(`${this.game_name}_zoom`);&lt;br /&gt;
        this.setZoom(zoom);&lt;br /&gt;
...&lt;br /&gt;
   },&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
In this case setZoom is custom function to actually set it.&lt;br /&gt;
When zoom changed, for example when some buttons pressed, store current value (but sanitize it so it never so bad that game cannot be viewed&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    setZoom: function (zoom) {&lt;br /&gt;
      zoom = parseInt(zoom) || 0;&lt;br /&gt;
      if (zoom === 0 || zoom &amp;lt; 0.1 || zoom &amp;gt; 10) {&lt;br /&gt;
        zoom = 1;&lt;br /&gt;
      }&lt;br /&gt;
      this.zoom = zoom;&lt;br /&gt;
      localStorage.setItem(`${this.game_name}_zoom`, &amp;quot;&amp;quot; + this.zoom);&lt;br /&gt;
... do actual zooming stuff&lt;br /&gt;
    },&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Capture client JavaScript errors in the &amp;quot;unexpected error&amp;quot; log ===&lt;br /&gt;
&lt;br /&gt;
PHP (backend) errors are recorded in the &amp;quot;unexpected error&amp;quot; log, but JavaScript (frontend) errors are only available in the browser itself. This means you have no visibility about things that go wrong in the client... unless you make clients report their errors to the server.&lt;br /&gt;
&lt;br /&gt;
; In actions.php:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  public function jsError()&lt;br /&gt;
  {&lt;br /&gt;
    $this-&amp;gt;setAjaxMode(false);&lt;br /&gt;
    $this-&amp;gt;game-&amp;gt;jsError($_POST[&#039;userAgent&#039;], $_POST[&#039;msg&#039;]);&lt;br /&gt;
    $this-&amp;gt;ajaxResponse();&lt;br /&gt;
  }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
; In game.php:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    public function jsError($userAgent, $msg): void&lt;br /&gt;
    {&lt;br /&gt;
        $this-&amp;gt;error(&amp;quot;JavaScript error from User-Agent: $userAgent\n$msg // &amp;quot;);&lt;br /&gt;
    }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
; In game.js:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
define([&amp;quot;dojo&amp;quot;, &amp;quot;dojo/_base/declare&amp;quot;, &amp;quot;ebg/core/gamegui&amp;quot;, &amp;quot;ebg/counter&amp;quot;], function (dojo, declare) {&lt;br /&gt;
  const uniqJsError = {};&lt;br /&gt;
  ...&lt;br /&gt;
&lt;br /&gt;
  return declare(&amp;quot;bgagame.nowboarding&amp;quot;, ebg.core.gamegui, {&lt;br /&gt;
    ...&lt;br /&gt;
    /* @Override */&lt;br /&gt;
    onScriptError(msg) {&lt;br /&gt;
      if (!uniqJsError[msg]) {&lt;br /&gt;
        uniqJsError[msg] = true;&lt;br /&gt;
        console.error(&amp;quot;⛔ Reporting JavaScript error&amp;quot;, msg);&lt;br /&gt;
        this.ajaxcall(&lt;br /&gt;
          &amp;quot;/&amp;quot; + this.game_name + &amp;quot;/&amp;quot; + this.game_name + &amp;quot;/jsError.html&amp;quot;,&lt;br /&gt;
          {&lt;br /&gt;
            msg,&lt;br /&gt;
            userAgent: navigator.userAgent,&lt;br /&gt;
          },&lt;br /&gt;
          this,&lt;br /&gt;
          () =&amp;gt; {},&lt;br /&gt;
          () =&amp;gt; {},&lt;br /&gt;
          &amp;quot;post&amp;quot;&lt;br /&gt;
        );&lt;br /&gt;
      }&lt;br /&gt;
      this.inherited(arguments);&lt;br /&gt;
    },&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Algorithms ==&lt;br /&gt;
&lt;br /&gt;
=== Generate permutations in lexicographic order ===&lt;br /&gt;
&lt;br /&gt;
Use this when you have an array like [1, 2, 3, 4] and need to loop over some/all 24 permutations of possible ordering. This type of [https://www.php.net/manual/en/language.generators.syntax.php generator function] computes each possibility one at a time, making it vastly more efficient than either a normal iteration or recursive function that produce all possibilities up front.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
function generatePermutations(array $array): Generator&lt;br /&gt;
{&lt;br /&gt;
    // https://en.wikipedia.org/wiki/Permutation#Generation_in_lexicographic_order&lt;br /&gt;
    // Sort the array and this is the first permutation&lt;br /&gt;
    sort($array);&lt;br /&gt;
    yield $array;&lt;br /&gt;
&lt;br /&gt;
    $count = count($array);&lt;br /&gt;
    do {&lt;br /&gt;
        // Find the largest index k where a[k] &amp;lt; a[k + 1]&lt;br /&gt;
        // End when no such index exists&lt;br /&gt;
        $found = false;&lt;br /&gt;
        for ($k = $count - 2; $k &amp;gt;= 0; $k--) {&lt;br /&gt;
            $kvalue = $array[$k];&lt;br /&gt;
            $knext = $array[$k + 1];&lt;br /&gt;
            if ($kvalue &amp;lt; $knext) {&lt;br /&gt;
                // Find the largest index l greater than k where a[k] &amp;lt; a[l]&lt;br /&gt;
                for ($l = $count - 1; $l &amp;gt; $k; $l--) {&lt;br /&gt;
                    $lvalue = $array[$l];&lt;br /&gt;
                    if ($kvalue &amp;lt; $lvalue) {&lt;br /&gt;
                        // Swap a[k] and a[l]&lt;br /&gt;
                        [$array[$k], $array[$l]] = [$array[$l], $array[$k]];&lt;br /&gt;
&lt;br /&gt;
                        // Reverse the sequence from a[k + 1] up to and including the final element&lt;br /&gt;
                        $reverse = array_reverse(array_slice($array, $k + 1));&lt;br /&gt;
                        array_splice($array, $k + 1, $count, $reverse);&lt;br /&gt;
                        yield $array;&lt;br /&gt;
&lt;br /&gt;
                        // Restart with the new array to find the next permutation&lt;br /&gt;
                        $found = true;&lt;br /&gt;
                        break 2;&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    } while ($found);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Usage:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$cash = [4, 1, 2, 3, 4];&lt;br /&gt;
foreach ($this-&amp;gt;generatePermutations($cash) as $p) {&lt;br /&gt;
    // your code here to evaluate permutation $p&lt;br /&gt;
    // first iteration: $p = [1, 2, 3, 4, 4]&lt;br /&gt;
    // last (60th) iteration: $p = [4, 4, 3, 2, 1]&lt;br /&gt;
    // break from loop once you achieve your goal&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Category:Studio]]&lt;/div&gt;</summary>
		<author><name>Sguzzer Gunayer</name></author>
	</entry>
	<entry>
		<id>https://en.doc.boardgamearena.com/index.php?title=BGA_Studio_Cookbook&amp;diff=22705</id>
		<title>BGA Studio Cookbook</title>
		<link rel="alternate" type="text/html" href="https://en.doc.boardgamearena.com/index.php?title=BGA_Studio_Cookbook&amp;diff=22705"/>
		<updated>2024-09-24T14:30:28Z</updated>

		<summary type="html">&lt;p&gt;Sguzzer Gunayer: /* Using CSS to create different colors of game pieces if you have only white piece */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;br /&gt;
&lt;br /&gt;
This page is a cookbook of design and implementation recipes for BGA Studio framework.&lt;br /&gt;
For tooling and usage recipes see [[Tools and tips of BGA Studio]].&lt;br /&gt;
If you have your own recipes feel free to edit this page.&lt;br /&gt;
&lt;br /&gt;
__TOC__&lt;br /&gt;
&lt;br /&gt;
== Visual Effects, Layout and Animation ==&lt;br /&gt;
&lt;br /&gt;
=== DOM manipulatons ===&lt;br /&gt;
&lt;br /&gt;
==== Create pieces dynamically (using template) ====&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Ingredients:&#039;&#039;&#039; ggg_ggg.tpl, ggg.js&lt;br /&gt;
&lt;br /&gt;
Note: this method is recommended by BGA guildlines&lt;br /&gt;
&lt;br /&gt;
Declared js template with variables in .tpl file, like this&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;script type=&amp;quot;text/javascript&amp;quot;&amp;gt;&lt;br /&gt;
    // Javascript HTML templates&lt;br /&gt;
    var jstpl_ipiece = &#039;&amp;lt;div class=&amp;quot;${type} ${type}_${color} inlineblock&amp;quot; aria-label=&amp;quot;${name}&amp;quot; title=&amp;quot;${name}&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&#039;;&lt;br /&gt;
&amp;lt;/script&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Use it like this in .js file&lt;br /&gt;
  div = this.format_block(&#039;jstpl_ipiece&#039;, {&lt;br /&gt;
                                type : &#039;meeple&#039;,&lt;br /&gt;
                                color : &#039;ff0000&#039;,&lt;br /&gt;
                                name : &#039;Bob&#039;,&lt;br /&gt;
                            });&lt;br /&gt;
  &lt;br /&gt;
Then you do whatever you need to do with that div, this one specifically design to go to log entries, because it has embedded title (otherwise its a picture only) and no id.&lt;br /&gt;
&lt;br /&gt;
Note: you could have place this variable in js itself, but keeping it in .tpl allows you to have your js code be free of HTML. Normally it never happens but&lt;br /&gt;
it is good to strive for it.&lt;br /&gt;
Note: you can also use string concatenation, its less readable. You can also use dojo dom object creation api&#039;s but its brutally verbose and its more unreadable.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Create pieces dynamically (using string concatenation) ====&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Ingredients:&#039;&#039;&#039; ggg.js&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  div = &amp;quot;&amp;lt;div class=&#039;meeple_&amp;quot;+color+&amp;quot;&#039;&amp;gt;&amp;lt;/div&amp;gt;&amp;quot;;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
or modern way&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  div = `&amp;lt;div class=&#039;meeple_${color}&#039;&amp;gt;&amp;lt;/div&amp;gt;`;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Create all pieces statically ====&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Ingredients:&#039;&#039;&#039; ggg_ggg.tpl, ggg.css, ggg.view.php (optional) &lt;br /&gt;
&lt;br /&gt;
* Create ALL game pieces in html template (.tpl)&lt;br /&gt;
* ALL pieces should have unique id, and it should be meaningful, i.e. meeple_red_1&lt;br /&gt;
* Do not use inline styling&lt;br /&gt;
* Id of player&#039;s specific pieces should use some sort of &#039;color&#039; identification, since player id cannot be used in static layout, you can use english color name, hex 6 char value, or color &amp;quot;number&amp;quot; (1,2,3...)&lt;br /&gt;
* Pieces should have separated class for its color, type, etc, so it can be easily styled in groups. In example below you now can style all meeples, all red meeples or all red tokens, or all &amp;quot;first&amp;quot; meeples&lt;br /&gt;
&lt;br /&gt;
ggg.tpl:&lt;br /&gt;
&amp;lt;pre&amp;gt; &lt;br /&gt;
  &amp;lt;div id=&amp;quot;home_red&amp;quot; class=&amp;quot;home_red home&amp;quot;&amp;gt;&lt;br /&gt;
     &amp;lt;div id=&amp;quot;meeple_red_1&amp;quot; class=&amp;quot;meeple red n1&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
     &amp;lt;div id=&amp;quot;meeple_red_2&amp;quot; class=&amp;quot;meeple red n2&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
  &amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
ggg.css:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
.meeple {&lt;br /&gt;
	width: 32px;&lt;br /&gt;
	height: 39px;&lt;br /&gt;
	background-image: url(img/78_64_stand_meeples.png);&lt;br /&gt;
	background-size: 352px;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.meeple.red {&lt;br /&gt;
	background-position: 30% 0%;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* There should be straight forward mapping between server id and js id (or 1:1)&lt;br /&gt;
* You place objects in different zones of the layout, and setup css to take care of layout&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
.home .meeple{&lt;br /&gt;
   display: inline-block;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
* If you need to have a temporary object that look like original you can use dojo.clone (and change id to some temp id)&lt;br /&gt;
* If there is lots of repetition or zone grid you can use template generator, but inject style declaration in css instead of inline style for flexibility&lt;br /&gt;
&lt;br /&gt;
Note:&lt;br /&gt;
* If you use this model you cannot use premade js components such as Stock and Zone&lt;br /&gt;
* You have to use alternative methods of animation (slightly altered) since default method will leave object with inline style attributes which you don&#039;t need&lt;br /&gt;
&lt;br /&gt;
==== Use player color in template ====&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Ingredients:&#039;&#039;&#039; ggg_ggg.tpl, ggg.view.php&lt;br /&gt;
&lt;br /&gt;
.view.php:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    function build_page($viewArgs) {&lt;br /&gt;
        // Get players &amp;amp; players number&lt;br /&gt;
        $players = $this-&amp;gt;game-&amp;gt;loadPlayersBasicInfos();&lt;br /&gt;
        $players_nbr = count($players);&lt;br /&gt;
        /**&lt;br /&gt;
         * ********* Place your code below: ***********&lt;br /&gt;
         */&lt;br /&gt;
        &lt;br /&gt;
        // Set PCOLOR to the current player color hex&lt;br /&gt;
        global $g_user;&lt;br /&gt;
        $cplayer = $g_user-&amp;gt;get_id();&lt;br /&gt;
        if (array_key_exists($cplayer, $players)) { // may be not set if spectator&lt;br /&gt;
            $player_color = $players [$cplayer] [&#039;player_color&#039;];&lt;br /&gt;
        } else {&lt;br /&gt;
            $player_color = &#039;ffffff&#039;; // spectator&lt;br /&gt;
        }&lt;br /&gt;
        $this-&amp;gt;tpl [&#039;PCOLOR&#039;] = $player_color;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Status bar ===&lt;br /&gt;
&lt;br /&gt;
==== Changing state prompt ====&lt;br /&gt;
&lt;br /&gt;
State prompt is message displayed for player which usually comes from state description.&lt;br /&gt;
Sometimes you want to change it without changing state (one way is change state but locally, see client states above).&lt;br /&gt;
&lt;br /&gt;
Simple way just change the html&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        setMainTitle: function(text) {&lt;br /&gt;
            $(&#039;pagemaintitletext&#039;).innerHTML = text;&lt;br /&gt;
        },&lt;br /&gt;
         // usage&lt;br /&gt;
        onMeeple: function(event) {&lt;br /&gt;
              //... &lt;br /&gt;
              this.setMainTitle(_(&#039;You must select where meeple is going&#039;));&lt;br /&gt;
        },&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This however will not work with parameters and will not draw You in color, if you want this its more sophisticated:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        setDescriptionOnMyTurn : function(text) {&lt;br /&gt;
            this.gamedatas.gamestate.descriptionmyturn = text;&lt;br /&gt;
            var tpl = dojo.clone(this.gamedatas.gamestate.args);&lt;br /&gt;
            if (tpl === null) {&lt;br /&gt;
                tpl = {};&lt;br /&gt;
            }&lt;br /&gt;
            var title = &amp;quot;&amp;quot;;&lt;br /&gt;
            if (this.isCurrentPlayerActive() &amp;amp;&amp;amp; text !== null) {&lt;br /&gt;
                tpl.you = this.divYou(); &lt;br /&gt;
            }&lt;br /&gt;
            title = this.format_string_recursive(text, tpl);&lt;br /&gt;
&lt;br /&gt;
            if (!title) {&lt;br /&gt;
                this.setMainTitle(&amp;quot;&amp;amp;nbsp;&amp;quot;);&lt;br /&gt;
            } else {&lt;br /&gt;
                this.setMainTitle(title);&lt;br /&gt;
            }&lt;br /&gt;
        },&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note: this method uses &#039;&#039;&#039;setMainTitle&#039;&#039;&#039; defined above and &#039;&#039;&#039;divYou&#039;&#039;&#039; defined in another section of this wiki.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Animation ===&lt;br /&gt;
&lt;br /&gt;
==== Attach to new parent without destroying the object ====&lt;br /&gt;
&lt;br /&gt;
BGA function attachToNewParent for some reason destroys the original, if you want similar function that does not you can use this&lt;br /&gt;
ggg.js&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        /**&lt;br /&gt;
         * This method will attach mobile to a new_parent without destroying, unlike original attachToNewParent which destroys mobile and&lt;br /&gt;
         * all its connectors (onClick, etc)&lt;br /&gt;
         */&lt;br /&gt;
        attachToNewParentNoDestroy: function (mobile_in, new_parent_in, relation, place_position) {&lt;br /&gt;
&lt;br /&gt;
            const mobile = $(mobile_in);&lt;br /&gt;
            const new_parent = $(new_parent_in);&lt;br /&gt;
&lt;br /&gt;
            var src = dojo.position(mobile);&lt;br /&gt;
            if (place_position)&lt;br /&gt;
                mobile.style.position = place_position;&lt;br /&gt;
            dojo.place(mobile, new_parent, relation);&lt;br /&gt;
            mobile.offsetTop;//force re-flow&lt;br /&gt;
            var tgt = dojo.position(mobile);&lt;br /&gt;
            var box = dojo.marginBox(mobile);&lt;br /&gt;
            var cbox = dojo.contentBox(mobile);&lt;br /&gt;
            var left = box.l + src.x - tgt.x;&lt;br /&gt;
            var top = box.t + src.y - tgt.y;&lt;br /&gt;
&lt;br /&gt;
            mobile.style.position = &amp;quot;absolute&amp;quot;;&lt;br /&gt;
            mobile.style.left = left + &amp;quot;px&amp;quot;;&lt;br /&gt;
            mobile.style.top = top + &amp;quot;px&amp;quot;;&lt;br /&gt;
            box.l += box.w - cbox.w;&lt;br /&gt;
            box.t += box.h - cbox.h;&lt;br /&gt;
            mobile.offsetTop;//force re-flow&lt;br /&gt;
            return box;&lt;br /&gt;
        },&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Animation on oversurface ====&lt;br /&gt;
If you use non-absolute position for your game elements (i.e you use layouts) - you cannot really use BGA animation functions. After years of fidding with different options I use&lt;br /&gt;
techique which I call animation on oversurface that works when parents use different zoom, rotation, etc&lt;br /&gt;
&lt;br /&gt;
* You need another layer on top of everything - oversurface&lt;br /&gt;
* We create copy of the object on oversurface - to move&lt;br /&gt;
* We move the real object on final position - but make it invisible for now&lt;br /&gt;
* We move the phantom to final position applying required zoom and rotation (using css animation), then destroy it&lt;br /&gt;
* When animation is done we make original object visible in new position&lt;br /&gt;
&lt;br /&gt;
The code is bit complex it can be found here&lt;br /&gt;
&lt;br /&gt;
https://codepen.io/VictoriaLa/pen/gORvdJo&lt;br /&gt;
&lt;br /&gt;
Game using it: century, ultimaterailroads&lt;br /&gt;
&lt;br /&gt;
==== Scroll element into view ====&lt;br /&gt;
Ingredients: game.js&lt;br /&gt;
&lt;br /&gt;
This function will scroll given node (div) into view and respect replays and archive mode&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    scrollIntoViewAfter: function (node, delay) {&lt;br /&gt;
      if (this.instantaneousMode || this.inSetup) {&lt;br /&gt;
        return;&lt;br /&gt;
      }&lt;br /&gt;
      if (typeof g_replayFrom != &amp;quot;undefined&amp;quot;) {&lt;br /&gt;
        $(node).scrollIntoView();&lt;br /&gt;
        return;&lt;br /&gt;
      }&lt;br /&gt;
      if (!delay) delay = 0;&lt;br /&gt;
      setTimeout(() =&amp;gt; {&lt;br /&gt;
        $(node).scrollIntoView({ behavior: &amp;quot;smooth&amp;quot;, block: &amp;quot;center&amp;quot; });&lt;br /&gt;
      }, delay);&lt;br /&gt;
    },&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Logs ===&lt;br /&gt;
&lt;br /&gt;
==== Inject icon images in the log ====&lt;br /&gt;
&lt;br /&gt;
Here is an example of what was done for Terra Mystica which is simple and straightforward:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
//Define the proper message&lt;br /&gt;
		$message = clienttranslate(&#039;${player_name} gets ${power_income} via Structures&#039;);&lt;br /&gt;
		if ($price &amp;gt; 0) {&lt;br /&gt;
			$this-&amp;gt;DbQuery(&amp;quot;UPDATE player SET player_score = player_score - $price WHERE player_id = $player_id&amp;quot;);&lt;br /&gt;
			$message = clienttranslate(&#039;${player_name} pays ${vp_price} and gets ${power_income} via Structures&#039;);&lt;br /&gt;
		}&lt;br /&gt;
&lt;br /&gt;
// Notify&lt;br /&gt;
		$this-&amp;gt;notifyAllPlayers( &amp;quot;powerViaStructures&amp;quot;, $message, array(&lt;br /&gt;
			&#039;i18n&#039; =&amp;gt; array( ),&lt;br /&gt;
			&#039;player_id&#039; =&amp;gt; $player_id,&lt;br /&gt;
			&#039;player_name&#039; =&amp;gt; $this-&amp;gt;getUniqueValueFromDb( &amp;quot;SELECT player_name FROM player WHERE player_id = $player_id&amp;quot; ),&lt;br /&gt;
			&#039;power_tokens&#039; =&amp;gt; $power_tokens,&lt;br /&gt;
			&#039;vp_price&#039; =&amp;gt; $this-&amp;gt;getLogsVPAmount($price),&lt;br /&gt;
			&#039;power_income&#039; =&amp;gt; $this-&amp;gt;getLogsPowerAmount($power_income),&lt;br /&gt;
			&#039;newScore&#039; =&amp;gt; $this-&amp;gt;getUniqueValueFromDb( &amp;quot;SELECT player_score FROM player WHERE player_id = $player_id&amp;quot; ),&lt;br /&gt;
			&#039;counters&#039; =&amp;gt; $this-&amp;gt;getGameCounters(null),&lt;br /&gt;
		) );&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
With some functions to have the needed html added inside the substitution variable, such as:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
function getLogsPowerAmount( $amount ) {&lt;br /&gt;
		return &amp;quot;&amp;lt;div class=&#039;tmlogs_icon&#039; title=&#039;Power&#039;&amp;gt;&amp;lt;div class=&#039;power_amount&#039;&amp;gt;$amount&amp;lt;/div&amp;gt;&amp;lt;/div&amp;gt;&amp;quot;;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Note: injecting html from php is not ideal but easy, if you want more clean solution, use method below but it is a lot more sophisticated.&lt;br /&gt;
&lt;br /&gt;
==== Inject images and styled html in the log ====&lt;br /&gt;
&lt;br /&gt;
{{InfoBox|title=Warning — Translation|maxWidth=500|color=#c00|body=&#039;&#039;&#039;In order to prevent interference with the translation process, keep in mind that you must only apply modifications to the args object, and not try to substitute the keys (the &amp;lt;code&amp;gt;${player_name}&amp;lt;/code&amp;gt; parts of your string) in the log string.&#039;&#039;&#039;}}&lt;br /&gt;
&lt;br /&gt;
So you want nice pictures in the game log. What do you do? The first idea that comes to mind is to send html from php in notifications (see method above). &lt;br /&gt;
&lt;br /&gt;
This is a bad idea for many reasons:&lt;br /&gt;
&lt;br /&gt;
* It&#039;s bad architecture. ui elements leak into the server, and now you have to manage the ui in multiple places.&lt;br /&gt;
* If you decided to change something in the ui in future version, replay logs for old games and tutorials may not work, since they use stored notifications.&lt;br /&gt;
* Log previews for old games become unreadable. (This is the log state before you enter the game replay, which is useful for troubleshooting and game analysis.)&lt;br /&gt;
* It&#039;s more data to transfer and store in the db.&lt;br /&gt;
* It&#039;s a nightmare for translators.&lt;br /&gt;
&lt;br /&gt;
So what else can you do? You can use client side log injection to intercept log arguments (which come from the server) and replace them with html on the client side. Here are three different method you can use to achieve this.&lt;br /&gt;
&lt;br /&gt;
===== Override &amp;lt;code&amp;gt;this.format_string_recursive()&amp;lt;/code&amp;gt; method =====&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Ingredients:&#039;&#039;&#039; ggg.js, ggg.game.php&lt;br /&gt;
&lt;br /&gt;
I use this recipe for &#039;&#039;&#039;client side log injection&#039;&#039;&#039; to intercept log arguments (which come from the server) and replace them with html on the client side.&lt;br /&gt;
&lt;br /&gt;
[[File:clientloginjection.png|left]] &lt;br /&gt;
&lt;br /&gt;
ggg.js&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt; &lt;br /&gt;
&lt;br /&gt;
        /** Override this function to inject html into log items. This is a built-in BGA method.  */&lt;br /&gt;
&lt;br /&gt;
        /* @Override */&lt;br /&gt;
        format_string_recursive : function format_string_recursive(log, args) {&lt;br /&gt;
            try {&lt;br /&gt;
                if (log &amp;amp;&amp;amp; args &amp;amp;&amp;amp; !args.processed) {&lt;br /&gt;
                    args.processed = true;&lt;br /&gt;
                    &lt;br /&gt;
&lt;br /&gt;
                    // list of special keys we want to replace with images&lt;br /&gt;
                    var keys = [&#039;place_name&#039;,&#039;token_name&#039;];&lt;br /&gt;
                    &lt;br /&gt;
                  &lt;br /&gt;
                    for ( var i in keys) {&lt;br /&gt;
                        var key = keys[i];&lt;br /&gt;
                        key in args &amp;amp;&amp;amp; args[key] = this.getTokenDiv(key, args);                            &lt;br /&gt;
&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            } catch (e) {&lt;br /&gt;
                console.error(log,args,&amp;quot;Exception thrown&amp;quot;, e.stack);&lt;br /&gt;
            }&lt;br /&gt;
            return this.inherited({callee: format_string_recursive}, arguments);&lt;br /&gt;
        },&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Important:&#039;&#039;&#039; In the &#039;&#039;format_string_recursive&#039;&#039; method, the &#039;args&#039; parameter will only contain arguments passed to it from the notify method in ggg.game.php (see below).&lt;br /&gt;
&lt;br /&gt;
The &#039;log&#039; parameter is the actual string that is inserted into the logs. You can perform additional js string manipulation on it.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        getTokenDiv : function(key, args) {&lt;br /&gt;
            // ... implement whatever html you want here, example from sharedcode.js&lt;br /&gt;
            var token_id = args[key];&lt;br /&gt;
            var item_type = getPart(token_id,0);&lt;br /&gt;
            var logid = &amp;quot;log&amp;quot; + (this.globalid++) + &amp;quot;_&amp;quot; + token_id;&lt;br /&gt;
            switch (item_type) {&lt;br /&gt;
                case &#039;wcube&#039;:&lt;br /&gt;
                    var tokenDiv = this.format_block(&#039;jstpl_resource_log&#039;, {&lt;br /&gt;
                        &amp;quot;id&amp;quot; : logid,&lt;br /&gt;
                        &amp;quot;type&amp;quot; : &amp;quot;wcube&amp;quot;,&lt;br /&gt;
                        &amp;quot;color&amp;quot; : getPart(token_id,1),&lt;br /&gt;
                    });&lt;br /&gt;
                    return tokenDiv;&lt;br /&gt;
             &lt;br /&gt;
                case &#039;meeple&#039;:&lt;br /&gt;
                    if ($(token_id)) {&lt;br /&gt;
                        var clone = dojo.clone($(token_id));&lt;br /&gt;
    &lt;br /&gt;
                        dojo.attr(clone, &amp;quot;id&amp;quot;, logid);&lt;br /&gt;
                        this.stripPosition(clone);&lt;br /&gt;
                        dojo.addClass(clone, &amp;quot;logitem&amp;quot;);&lt;br /&gt;
                        return clone.outerHTML;&lt;br /&gt;
                    }&lt;br /&gt;
                    break;&lt;br /&gt;
     &lt;br /&gt;
                default:&lt;br /&gt;
                    break;&lt;br /&gt;
            }&lt;br /&gt;
&lt;br /&gt;
            return &amp;quot;&#039;&amp;quot; + this.clienttranslate_string(this.getTokenName(token_id)) + &amp;quot;&#039;&amp;quot;;&lt;br /&gt;
       },&lt;br /&gt;
       getTokenName : function(key) {&lt;br /&gt;
           return this.gamedatas.token_types[key].name; // get name for the key, from static table for example&lt;br /&gt;
       },&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note that in this case the server simply injects token_id as a name, and the client substitutes it for the translated name or the picture.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
ggg.game.php:&lt;br /&gt;
&lt;br /&gt;
           $this-&amp;gt;notifyAllPlayers(&#039;playerLog&#039;,clienttranslate(&#039;Game moves ${token_name}&#039;),[&#039;token_name&#039;=&amp;gt;$token_id]);&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Important:&#039;&#039;&#039; As noted above, only arguments actually passed by this method are available to the args parameter received in the client-side &#039;&#039;format_string_recursive&#039;&#039; method.&lt;br /&gt;
&lt;br /&gt;
Sometimes it is the case that you want to pass arguments that are not actually included in the output message. For example, suppose we have a method like this:&lt;br /&gt;
&lt;br /&gt;
           $this-&amp;gt;notifyAllPlayers(&#039;tokenPlaced&#039;,clienttranslate(&#039;Player placed ${token_name}&#039;),array(&lt;br /&gt;
              &#039;token_name&#039; =&amp;gt; $token_id,&lt;br /&gt;
              &#039;zone_played&#039; =&amp;gt; $zone);&lt;br /&gt;
&lt;br /&gt;
This will output &amp;quot;Player placed ${token_name}&amp;quot; in the log, and if we subscribe to a notification method activated by the &amp;quot;tokenPlaced&amp;quot; event in the client-side code, that method can make use of the &#039;zone_played&#039; argument. &lt;br /&gt;
&lt;br /&gt;
Now if you want to make some really cool things with game log, most probably you would need more arguments than are included in log message. The problem with that,&lt;br /&gt;
it will work at first, but if you reload game using F5 or when the game loads in turn based mode, you will loose your additional parameters, why? Because when game reloads it does not actually send same notifications, it sends special &amp;quot;hitstorical_log&amp;quot; notification where all  parameters not listed in the message are removed. In example above, field zone_played would be removed from historical log as it is not included in message of the notification. You can till preserve specific arguments in historical log by adding special field preserve to notification arguments like this:&lt;br /&gt;
 &lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
           $this-&amp;gt;notifyAllPlayers(&#039;tokenPlaced&#039;,clienttranslate(&#039;Player placed ${token_name}&#039;),array(&lt;br /&gt;
              &#039;token_name&#039; =&amp;gt; $token_id,&lt;br /&gt;
              &#039;zone_played&#039; =&amp;gt; $zone,&lt;br /&gt;
              &#039;preserve&#039; =&amp;gt; [ &#039;zone_played&#039; ]&lt;br /&gt;
           );&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Now you can use zone_played in format_string_recursive even in historical logs.&lt;br /&gt;
&lt;br /&gt;
===== Use &amp;lt;code&amp;gt;:formatFunction&amp;lt;/code&amp;gt; option provided by &amp;lt;code&amp;gt;dojo.string.substitute&amp;lt;/code&amp;gt; =====&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Ingredients:&#039;&#039;&#039; ggg.js, ggg.game.php, ggg_ggg.tpl, ggg.css&lt;br /&gt;
&lt;br /&gt;
The above method will work in most of the cases, but if you use dotted keys such as &amp;lt;code&amp;gt;${card.name}&amp;lt;/code&amp;gt; (which is supported by the framework, for private state args), the key won&#039;t be substituted because the &amp;lt;code&amp;gt;key in arg&amp;lt;/code&amp;gt; test will fail. If so you need to rely either on this way, or the one after.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;WARNING:&#039;&#039;&#039; using this method on an already advanced project will require you to go through all your notifications to change keys !&lt;br /&gt;
&lt;br /&gt;
Under the hood, the &#039;&#039;&#039;this.format_string_recursive()&#039;&#039;&#039; function calls the &#039;&#039;&#039;dojo.string.substitute&#039;&#039;&#039; method which substitutes &amp;lt;code&amp;gt;${keys}&amp;lt;/code&amp;gt; with the value provided. If you take a look at the [https://dojotoolkit.org/reference-guide/1.7/dojo/string.html#substitute documentation] and [https://github.com/dojo/dojo/blob/c3ceb017cfa25b703f5662dc83d1c8aae9bc5d81/string.js#L163 source code] you can notice that the key can be suffixed with a colon (&amp;lt;code&amp;gt;:&amp;lt;/code&amp;gt;) followed by a function name. This will allow you to specify directly in the substitution string which keys need HTML injection.&lt;br /&gt;
&lt;br /&gt;
First of all, you need to define your formatting function in the ggg.js file:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
[[ggg.js]]&lt;br /&gt;
        getTokenDiv : function(value, key) {&lt;br /&gt;
            //This is only an example implementation, you need to write your own.&lt;br /&gt;
            //The method should return HTML code&lt;br /&gt;
            switch (key) {&lt;br /&gt;
                case &#039;html_injected_argument1&#039;:&lt;br /&gt;
                    return this.format_block(&#039;jstpl_HTMLLogElement1&#039;,{value: value});&lt;br /&gt;
                case &#039;html_injected_argument2&#039;:&lt;br /&gt;
                    return this.format_block(&#039;jstpl_HTMLLogElement2&#039;,{value: value});&lt;br /&gt;
                ...&lt;br /&gt;
            }&lt;br /&gt;
       }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Obviously you need to define the appropriate templates in the ggg_ggg.tpl file:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
[[ggg_ggg.tpl]]&lt;br /&gt;
let jstpl_HTMLLogElement1 = &#039;&amp;lt;div class=&amp;quot;log-element log-element-1-${value}&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&#039;;&lt;br /&gt;
let jstpl_HTMLLogElement2 = &#039;&amp;lt;div class=&amp;quot;log-element log-element-2-${value}&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&#039;;&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
And the appropriate classes in ggg.css.&lt;br /&gt;
&lt;br /&gt;
Then you need to add the &amp;lt;code&amp;gt;dojo/aspect&amp;lt;/code&amp;gt; module at the top of the ggg.js file:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;[[ggg.js]]&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
 define([&lt;br /&gt;
     &amp;quot;dojo&amp;quot;, &amp;quot;dojo/_base/declare&amp;quot;,&lt;br /&gt;
     &#039;&#039;&#039;&amp;lt;span style=&amp;quot;color:green;&amp;quot;&amp;gt;&amp;quot;dojo/aspect&amp;quot;,&amp;lt;/span&amp;gt;                 //MUST BE IN THIRD POSITION&#039;&#039;&#039; (see [[#Including your own JavaScript module (II)|below]])&lt;br /&gt;
     &amp;quot;ebg/core/gamegui&amp;quot;,&lt;br /&gt;
     &amp;quot;ebg/counter&amp;quot;,&lt;br /&gt;
 ], function (dojo, declare, &amp;lt;span style=&amp;quot;color:green;&amp;quot;&amp;gt;&#039;&#039;&#039;aspect&#039;&#039;&#039;&amp;lt;/span&amp;gt;) {&lt;br /&gt;
 ...&lt;br /&gt;
&lt;br /&gt;
And you also need to add the following code in your &amp;lt;code&amp;gt;contructor&amp;lt;/code&amp;gt; method in the ggg.js:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;[[ggg.js]]&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
         constructor: function(){&lt;br /&gt;
&lt;br /&gt;
             // ... skipped code ...&lt;br /&gt;
             let gameObject = this;            //Needed as the this object in aspect.before will not refer to the game object in which the formatting function resides&lt;br /&gt;
             aspect.before(dojo.string, &amp;quot;substitute&amp;quot;, function(template, map, transform) {      //This allows you to modify the arguments of the dojo.string.substitute method before they&#039;re actually passed to it&lt;br /&gt;
                 return [template, map, transform, gameObject];&lt;br /&gt;
             });&lt;br /&gt;
&lt;br /&gt;
Now you&#039;re all set to inject HTML in your logs. To actually achieve this, you must specify the function name with the key like so:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;[[ggg.game.php]]&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
 $this-&amp;gt;notifyAllPlayers(&amp;quot;notificationName&amp;quot;, clienttranslate(&amp;quot;This log message contains ${plainTextArgument} and the following will receive HTML injection: ${html_injected_argument1:getTokenDiv}&amp;quot;), [&lt;br /&gt;
     &amp;quot;plainTextArgument&amp;quot; =&amp;gt; &amp;quot;some plain text here&amp;quot;,&lt;br /&gt;
     &amp;quot;html_injected_argument1&amp;quot; =&amp;gt; &amp;quot;some value used by getTokenDiv&amp;quot;,&lt;br /&gt;
 ]);&lt;br /&gt;
&lt;br /&gt;
You&#039;re not limited writing only one function, you can write as many functions as you like, and have them each inject a specific type of HTML. You just need to specify the relevant function name after the column in the substitution key.&lt;br /&gt;
&lt;br /&gt;
===== Use &amp;lt;code&amp;gt;transform&amp;lt;/code&amp;gt; argument of &amp;lt;code&amp;gt;dojo.string.substitute&amp;lt;/code&amp;gt; =====&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Ingredients:&#039;&#039;&#039; ggg.js, ggg.game.php, ggg_ggg.tpl, ggg.css&lt;br /&gt;
&lt;br /&gt;
This method is also relying on the use of &amp;lt;code&amp;gt;dojo.string.substitute&amp;lt;/code&amp;gt; by the framework, and will use the &amp;lt;code&amp;gt;transform&amp;lt;/code&amp;gt; argument, which, accordting to [https://github.com/dojo/dojo/blob/c3ceb017cfa25b703f5662dc83d1c8aae9bc5d81/string.js#L163 source code] and [https://dojotoolkit.org/reference-guide/1.7/dojo/string.html#substitute documentation] will be run on all the messages going through dojo.string.substitute.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;WARNING:&#039;&#039;&#039; This method will be applied to all strings that go through dojo.string.substitute. As such you must take extra care not to substitute keys that may be used by the framework (i.e. ${id}). In order to do so, a good practise would be to prefix all keys that need substitution with a trigram of the game name.&lt;br /&gt;
&lt;br /&gt;
Since all the keys will be fed to the tranform function, by default, it must return the value, substituted or not per your needs. You can define the function like this in the ggg.js file:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;[[ggg.js]]&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
         getTokenDiv : function(value, key) {&lt;br /&gt;
             //This is only an example implementation, you need to write your own.&lt;br /&gt;
             //The method should return HTML code&lt;br /&gt;
             switch (key) {&lt;br /&gt;
                 case &#039;html_injected_argument1&#039;:&lt;br /&gt;
                     return this.format_block(&#039;jstpl_HTMLLogElement1&#039;,{value: value});&lt;br /&gt;
                 case &#039;html_injected_argument2&#039;:&lt;br /&gt;
                     return this.format_block(&#039;jstpl_HTMLLogElement2&#039;,{value: value});&lt;br /&gt;
                 ...&lt;br /&gt;
                 default:&lt;br /&gt;
                     return value; //Needed otherwise regular strings won&#039;t appear since since the value isn&#039;t returned by the function&lt;br /&gt;
             }&lt;br /&gt;
         }&lt;br /&gt;
&lt;br /&gt;
The templates must be defined in the ggg_ggg.tpl file and the corresponding CSS classes in the ggg.css file.&lt;br /&gt;
&lt;br /&gt;
You need to add the following code at the beginning of the ggg.js file:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;[[ggg.js]]&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
 define([&lt;br /&gt;
     &amp;quot;dojo&amp;quot;, &amp;quot;dojo/_base/declare&amp;quot;,&lt;br /&gt;
     &#039;&#039;&#039;&amp;lt;span style=&amp;quot;color:green;&amp;quot;&amp;gt;&amp;quot;dojo/aspect&amp;quot;,&amp;lt;/span&amp;gt;                 //MUST BE IN THIRD POSITION&#039;&#039;&#039; (see [[#Including your own JavaScript module (II)|below]])&lt;br /&gt;
     &amp;quot;ebg/core/gamegui&amp;quot;,&lt;br /&gt;
     &amp;quot;ebg/counter&amp;quot;,&lt;br /&gt;
 ], function (dojo, declare, &amp;lt;span style=&amp;quot;color:green;&amp;quot;&amp;gt;&#039;&#039;&#039;aspect&#039;&#039;&#039;&amp;lt;/span&amp;gt;) {&lt;br /&gt;
 ...&lt;br /&gt;
&lt;br /&gt;
And the following code to the &amp;lt;code&amp;gt;constructor&amp;lt;/code&amp;gt; method in ggg.js:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;[[ggg.js]]&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
         constructor: function(){&lt;br /&gt;
             // ... skipped code ...&lt;br /&gt;
             let transformFunction = dojo.hitch(this, &amp;quot;getTokenDiv&amp;quot;);          //Needed as the this object in aspect.before will not refer to the game object in which the formatting function resides&lt;br /&gt;
             aspect.before(dojo.string, &amp;quot;substitute&amp;quot;, function(template, map, transform) {&lt;br /&gt;
                 if (undefined === transform) {    //Check for a transform function presence, just in case&lt;br /&gt;
                     return [template, map, transformFunction];&lt;br /&gt;
                 }&lt;br /&gt;
             });&lt;br /&gt;
&lt;br /&gt;
Then you&#039;re all set for log injection, no need to change anything on the PHP side.&lt;br /&gt;
&lt;br /&gt;
==== Processing logs on re-loading ====&lt;br /&gt;
&lt;br /&gt;
You rarely need to process logs when reloading, but if you want to do something fancy you may have to do it after logs are loaded. &lt;br /&gt;
Logs are loaded asyncronously so you have to listen for logs to be fully loaded.&lt;br /&gt;
Unfortunately there is no direct way of doing it so this is the hack.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Hack alert&#039;&#039;&#039; - this extends undocumented function and may be broken when framework is updated&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Ingredients:&#039;&#039;&#039; ggg.js&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
			/*&lt;br /&gt;
  			* [Undocumented] Override BGA framework functions to call onLoadingLogsComplete when loading is done&lt;br /&gt;
                        @Override&lt;br /&gt;
   			*/&lt;br /&gt;
			setLoader: function(image_progress, logs_progress) {&lt;br /&gt;
				this.inherited(arguments); // required, this is &amp;quot;super()&amp;quot; call, do not remove&lt;br /&gt;
				//console.log(&amp;quot;loader&amp;quot;, image_progress, logs_progress)&lt;br /&gt;
				if (!this.isLoadingLogsComplete &amp;amp;&amp;amp; logs_progress &amp;gt;= 100) {&lt;br /&gt;
					this.isLoadingLogsComplete = true; // this is to prevent from calling this more then once&lt;br /&gt;
					this.onLoadingLogsComplete();&lt;br /&gt;
				}&lt;br /&gt;
			},&lt;br /&gt;
&lt;br /&gt;
			onLoadingLogsComplete: function() {&lt;br /&gt;
				console.log(&#039;Loading logs complete&#039;);&lt;br /&gt;
				// do something here&lt;br /&gt;
			},&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Player Panel ===&lt;br /&gt;
&lt;br /&gt;
==== Inserting non-player panel ====&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Ingredients:&#039;&#039;&#039; ggg.js, ggg_ggg.tpl&lt;br /&gt;
&lt;br /&gt;
If you want to insert non-player panel on the right side (for example to hold extra preferences, zooming controls, etc)&lt;br /&gt;
&lt;br /&gt;
this can go pretty much anywhere in template it will be moved later&lt;br /&gt;
&lt;br /&gt;
ggg_ggg.tpl:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
	&amp;lt;div class=&#039;player_board_config&#039; id=&amp;quot;player_board_config&amp;quot;&amp;gt;&lt;br /&gt;
        &amp;lt;!-- here is whatever you want, buttons just example --&amp;gt;&lt;br /&gt;
		&amp;lt;button id=&amp;quot;zoom-out&amp;quot; class=&amp;quot; fa fa-search-minus fa-2x config-control&amp;quot;&amp;gt;&amp;lt;/button&amp;gt;&lt;br /&gt;
		&amp;lt;button id=&amp;quot;zoom-in&amp;quot; class=&amp;quot; fa fa-search-plus fa-2x config-control&amp;quot;&amp;gt;&amp;lt;/button&amp;gt;&lt;br /&gt;
		&amp;lt;button id=&amp;quot;show-settings&amp;quot; class=&amp;quot;fa fa-cog fa-2x config-control &amp;quot;&amp;gt;&amp;lt;/button&amp;gt;&lt;br /&gt;
        &amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
some hackery required in js&lt;br /&gt;
&lt;br /&gt;
ggg.js:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
/* @Override */&lt;br /&gt;
	updatePlayerOrdering() {&lt;br /&gt;
		this.inherited(arguments);&lt;br /&gt;
		dojo.place(&#039;player_board_config&#039;, &#039;player_boards&#039;, &#039;first&#039;);&lt;br /&gt;
	},&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Images and Icons ===&lt;br /&gt;
&lt;br /&gt;
==== Accessing images from js ====&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Ingredients:&#039;&#039;&#039; ggg.js&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt; &lt;br /&gt;
     // your game resources&lt;br /&gt;
     &lt;br /&gt;
     var my_img = &#039;&amp;lt;img src=&amp;quot;&#039;+g_gamethemeurl+&#039;img/cards.jpg&amp;quot;/&amp;gt;&#039;;&lt;br /&gt;
     &lt;br /&gt;
     // shared resources&lt;br /&gt;
     var my_help_img = &amp;quot;&amp;lt;img class=&#039;imgtext&#039; src=&#039;&amp;quot; + g_themeurl + &amp;quot;img/layout/help_click.png&#039; alt=&#039;action&#039; /&amp;gt; &amp;lt;span class=&#039;tooltiptext&#039;&amp;gt;&amp;quot; +&lt;br /&gt;
                    text + &amp;quot;&amp;lt;/span&amp;gt;&amp;quot;;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== High-Definition Graphics ====&lt;br /&gt;
&lt;br /&gt;
Some users will have screens which can display text and images at a greater resolution than the usual 72 dpi, e.g. the &amp;quot;Retina&amp;quot; screens on the 5k iMac, all iPads, and high-DPI screens on laptops from many manufacturers. If you can get art assets at this size, they will make your game look extra beautiful. You &#039;&#039;could&#039;&#039; just use large graphics and scale them down, but that would increase the download time and bandwidth for users who can&#039;t display them. Instead, a good way is to prepare a separate graphics file at exactly twice the size you would use otherwise, and add &amp;quot;@2x&amp;quot; at the end of the filename, e.g. if pieces.png is 240x320, then pieces@2x.png is 480x640.&lt;br /&gt;
&lt;br /&gt;
There are two changes required in order to use the separate graphics files. First in your css, where you use a file, add a media query which overrides the original definition and uses the bigger version on devices which can display them. Ensuring that the &amp;quot;background-size&amp;quot; attribute is set means that the size of the displayed object doesn&#039;t change, but only is drawn at the improved dot pitch.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
.piece {&lt;br /&gt;
    position: absolute;&lt;br /&gt;
    background-image: url(&#039;img/pieces.png&#039;);&lt;br /&gt;
    background-size:240px 320px;&lt;br /&gt;
    z-index: 10;&lt;br /&gt;
}&lt;br /&gt;
@media (-webkit-min-device-pixel-ratio: 2), (min-device-pixel-ratio: 2), (min-resolution: 192dpi)&lt;br /&gt;
{&lt;br /&gt;
    .piece {&lt;br /&gt;
        background-image: url(&#039;img/pieces@2x.png&#039;);&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Secondly, in your setup function in javascript, you must ensure than only the appropriate one version of the file gets pre-loaded (otherwise you more than waste the bandwidth saved by maintaining the standard-resolution file). Note that the media query is the same in both cases:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
            var isRetina = &amp;quot;(-webkit-min-device-pixel-ratio: 2), (min-device-pixel-ratio: 2), (min-resolution: 192dpi)&amp;quot;;&lt;br /&gt;
            if (window.matchMedia(isRetina).matches)&lt;br /&gt;
            {&lt;br /&gt;
                this.dontPreloadImage( &#039;pieces.png&#039; );&lt;br /&gt;
                this.dontPreloadImage( &#039;board.jpg&#039; );&lt;br /&gt;
            }&lt;br /&gt;
            else&lt;br /&gt;
            {&lt;br /&gt;
                this.dontPreloadImage( &#039;pieces@2x.png&#039; );&lt;br /&gt;
                this.dontPreloadImage( &#039;board@2x.jpg&#039; );&lt;br /&gt;
            }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Using CSS to create different colors of game pieces if you have only white piece ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
background-color: #${color}; &lt;br /&gt;
background-blend-mode: multiply;&lt;br /&gt;
background-image: url( &#039;img/mypiece.png&#039;);&lt;br /&gt;
mask: url(&#039;img/mypiece.png&#039;);&lt;br /&gt;
-webkit-mask: url(&#039;img/mypiece.png&#039;);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
where ${color} - is color you want&lt;br /&gt;
&lt;br /&gt;
Note: piece has to be white (shades of gray). Sprite can be used too, just add add background-position as usual.&lt;br /&gt;
&lt;br /&gt;
==== Accessing player avatar URLs ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
      getPlayerAvatar(playerId) {&lt;br /&gt;
         let avatarURL = &#039;&#039;;&lt;br /&gt;
&lt;br /&gt;
         if (null != $(&#039;avatar_&#039; + playerId)) {&lt;br /&gt;
            let smallAvatarURL = dojo.attr(&#039;avatar_&#039; + playerId, &#039;src&#039;);&lt;br /&gt;
            avatarURL = smallAvatarURL.replace(&#039;_32.&#039;, &#039;_184.&#039;);&lt;br /&gt;
         }&lt;br /&gt;
         else {&lt;br /&gt;
            avatarURL = &#039;https://x.boardgamearena.net/data/data/avatar/default_184.jpg&#039;;&lt;br /&gt;
         }&lt;br /&gt;
&lt;br /&gt;
         return avatarURL;&lt;br /&gt;
      },&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note:  This gets avatar URLs at 184x184 resolution.  You can also use 92, 50, and 32 depending on which resolution you want.&lt;br /&gt;
&lt;br /&gt;
==== Adding Image buttons ====&lt;br /&gt;
&lt;br /&gt;
Its pretty trivial but just in case you need a working function:&lt;br /&gt;
&lt;br /&gt;
ggg.js:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
                addImageActionButton: function (id, div_html, handler) { // div_html is string not node&lt;br /&gt;
                    this.addActionButton(id, div_html, handler, &#039;&#039;, false, &#039;gray&#039;); &lt;br /&gt;
                    dojo.style(id, &amp;quot;border&amp;quot;, &amp;quot;none&amp;quot;); // remove ugly border&lt;br /&gt;
                    dojo.addClass(id, &amp;quot;bgaimagebutton&amp;quot;); // add css class to do more styling&lt;br /&gt;
                    return $(id); // return node for chaining&lt;br /&gt;
                },&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Example of usage:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    this.addImageActionButton(&#039;button_coin&#039;,&amp;quot;&amp;lt;div class=&#039;coin&#039;&amp;gt;&amp;lt;/div&amp;gt;&amp;quot;, ()=&amp;gt;{ alert(&#039;Ha!&#039;); });&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Other Fluff ===&lt;br /&gt;
&lt;br /&gt;
==== Use thematic fonts ====&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Ingredients:&#039;&#039;&#039; ggg.css&lt;br /&gt;
&lt;br /&gt;
Sometime game elements use specific fonts of text, if you want to match it up you can load some specific font (IMPORTANT: from some &#039;&#039;&#039;free font&#039;&#039;&#039; source. See notes below).&lt;br /&gt;
&lt;br /&gt;
[[File:Dragonline_font.png]]&lt;br /&gt;
&lt;br /&gt;
.css&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
/* latin-ext */&lt;br /&gt;
@font-face {&lt;br /&gt;
  font-family: &#039;Qwigley&#039;;&lt;br /&gt;
  font-style: normal;&lt;br /&gt;
  font-weight: 400;&lt;br /&gt;
  src: local(&#039;Qwigley&#039;), local(&#039;Qwigley-Regular&#039;), url(https://fonts.gstatic.com/s/qwigley/v6/2Dy1Unur1HJoklbsg4iPJ_Y6323mHUZFJMgTvxaG2iE.woff2) format(&#039;woff2&#039;);&lt;br /&gt;
  unicode-range: U+0100-024F, U+1E00-1EFF, U+20A0-20AB, U+20AD-20CF, U+2C60-2C7F, U+A720-A7FF;&lt;br /&gt;
}&lt;br /&gt;
/* latin */&lt;br /&gt;
@font-face {&lt;br /&gt;
  font-family: &#039;Qwigley&#039;;&lt;br /&gt;
  font-style: normal;&lt;br /&gt;
  font-weight: normal;&lt;br /&gt;
  src: local(&#039;Qwigley&#039;), local(&#039;Qwigley-Regular&#039;), url(https://fonts.gstatic.com/s/qwigley/v6/gThgNuQB0o5ITpgpLi4Zpw.woff2) format(&#039;woff2&#039;);&lt;br /&gt;
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2212, U+2215, U+E0FF, U+EFFD, U+F000;&lt;br /&gt;
}&lt;br /&gt;
@font-face {&lt;br /&gt;
  font-family: &#039;Qwigley&#039;;&lt;br /&gt;
  font-style: normal;&lt;br /&gt;
  font-weight: normal;&lt;br /&gt;
  src: local(&#039;Qwigley&#039;), local(&#039;Qwigley-Regular&#039;), url(http://ff.static.1001fonts.net/q/w/qwigley.regular.ttf) format(&#039;ttf&#039;);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.zone_title {&lt;br /&gt;
	display: inline-block;&lt;br /&gt;
	position: absolute;&lt;br /&gt;
	font: italic 32px/32px &amp;quot;Qwigley&amp;quot;, cursive;	   &lt;br /&gt;
	height: 32px;&lt;br /&gt;
	width: auto;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;NB:&#039;&#039;&#039; if you need to include a font that&#039;s not available online, an extra action will be needed from an admin. Please include the font file(s) in your img directory, and mention it to admins when requesting your game to be moved to alpha. &#039;&#039;&#039;Please remember that the font has to be free, and include a .txt with all appropriate license information about the font.&#039;&#039;&#039;&lt;br /&gt;
You can look for free fonts (for example) on https://fonts.google.com or https://www.fontsquirrel.com/)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Content Security Policy&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
BGA runs a Content Security Policy which will limit the origins from which you can load external fonts, in order to prevent license abuse.&lt;br /&gt;
&lt;br /&gt;
The CSP is a whitelist of allowed origins. To see the list, view the response headers of any page on Studio, and look for the &amp;quot;Content-Security-Policy&amp;quot; header.&lt;br /&gt;
&lt;br /&gt;
You will specifically want to check for the font-src token within these headers, and limit any external fonts to these sources.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;This list is subject to change&#039;&#039;&#039; but as of the time of writing, the only acceptabled external sites are use.typekit.net and fonts.gstatic.com.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Scale to fit for big boards ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Ingredients:&#039;&#039;&#039; ggg_ggg.tpl, ggg.js&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Lets say you have huge game board, and lets say you want it to be 1400px wide. Besides the board there will be side bar which is 240 and trim. &lt;br /&gt;
My display is 1920 wide so it fits, but there is big chance other people won&#039;t have that width. What do you do?&lt;br /&gt;
&lt;br /&gt;
You have to decide:&lt;br /&gt;
* If board does not fit you want scale whole thing down, the best way is probably use viewport (see https://en.doc.boardgamearena.com/Your_game_mobile_version)&lt;br /&gt;
* You can leave the board as is and make sure it is scrollable horizonatally&lt;br /&gt;
* You add custom scale just for the board (can add user controls  - and hook to transform: scale())&lt;br /&gt;
&lt;br /&gt;
I tried to auto-scale but this just does work, too many variables - browser zoom, 3d mode, viewport, custom bga scaling, devicePixelRatio - all create some impossible coctail of zooming...&lt;br /&gt;
Here is scaling functing for custom user scaling&lt;br /&gt;
&lt;br /&gt;
ggg_ggg.tpl:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
   &amp;lt;div id=&amp;quot;thething&amp;quot; class=&amp;quot;thething&amp;quot;&amp;gt;&lt;br /&gt;
            ... everything else you declare ...&lt;br /&gt;
   &amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
ggg.js:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    onZoomPlus: function() {&lt;br /&gt;
       this.setZoom(this.zoom + 0.1);&lt;br /&gt;
    },&lt;br /&gt;
    onZoomMinus: function() {&lt;br /&gt;
       this.setZoom(this.zoom - 0.1);&lt;br /&gt;
    },&lt;br /&gt;
&lt;br /&gt;
    setZoom: function (zoom) {&lt;br /&gt;
      zoom = parseInt(zoom) || 0;&lt;br /&gt;
      if (zoom === 0 || zoom &amp;lt; 0.1 || zoom &amp;gt; 10) {&lt;br /&gt;
        zoom = 1;&lt;br /&gt;
      }&lt;br /&gt;
      this.zoom = zoom;&lt;br /&gt;
      var inner = document.getElementById(&amp;quot;thething&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
      if (zoom == 1) {&lt;br /&gt;
        inner.style.removeProperty(&amp;quot;transform&amp;quot;);&lt;br /&gt;
        inner.style.removeProperty(&amp;quot;width&amp;quot;);&lt;br /&gt;
      } else {&lt;br /&gt;
        inner.style.transform = &amp;quot;scale(&amp;quot; + zoom + &amp;quot;)&amp;quot;;&lt;br /&gt;
        inner.style.transformOrigin = &amp;quot;0 0&amp;quot;;&lt;br /&gt;
        inner.style.width = 100 / zoom + &amp;quot;%&amp;quot;;&lt;br /&gt;
      }&lt;br /&gt;
      localStorage.setItem(`${this.game_name}_zoom`, &amp;quot;&amp;quot; + this.zoom);&lt;br /&gt;
      this.onScreenWidthChange();&lt;br /&gt;
    },&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Dynamic tooltips ===&lt;br /&gt;
&lt;br /&gt;
If you really need a dynamic tooltip you can use this technique. (Only use it if the static tooltips provided by the BGA framework are not sufficient.)&lt;br /&gt;
&lt;br /&gt;
            new dijit.Tooltip({&lt;br /&gt;
                connectId: [&amp;quot;divItemId&amp;quot;],&lt;br /&gt;
                getContent: function(matchedNode){&lt;br /&gt;
                    return &amp;quot;... calculated ...&amp;quot;; &lt;br /&gt;
                }&lt;br /&gt;
            });&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
This is an out-of-the-box djit.Tooltip. It has a &#039;&#039;getContent&#039;&#039; method which is called dynamically.&lt;br /&gt;
&lt;br /&gt;
The string returned by getContent() becomes the innerHTML of the tooltip, so it can be anything. In this example matchedNode is a dojo node representing dom object with id of &amp;quot;divItemId&amp;quot; but there are more parameters which I am not posting here which allows more sophisticated subnode queries (i.e. you can attach tooltip to all nodes with class or whatever).&lt;br /&gt;
&lt;br /&gt;
[https://dojotoolkit.org/reference-guide/1.10/dijit/Tooltip.html dijit.Tooltip]&lt;br /&gt;
&lt;br /&gt;
It&#039;s not part of the BGA API so use at your own risk.&lt;br /&gt;
&lt;br /&gt;
=== Rendering text with players color and proper background ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Ingredients:&#039;&#039;&#039; ggg.js&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        /* Implementation of proper colored You with background in case of white or light colors  */&lt;br /&gt;
 &lt;br /&gt;
        divYou: function() {&lt;br /&gt;
            var color = this.gamedatas.players[this.player_id].color;&lt;br /&gt;
            var color_bg = &amp;quot;&amp;quot;;&lt;br /&gt;
            if (this.gamedatas.players[this.player_id] &amp;amp;&amp;amp; this.gamedatas.players[this.player_id].color_back) {&lt;br /&gt;
                color_bg = &amp;quot;background-color:#&amp;quot; + this.gamedatas.players[this.player_id].color_back + &amp;quot;;&amp;quot;;&lt;br /&gt;
            }&lt;br /&gt;
            var you = &amp;quot;&amp;lt;span style=\&amp;quot;font-weight:bold;color:#&amp;quot; + color + &amp;quot;;&amp;quot; + color_bg + &amp;quot;\&amp;quot;&amp;gt;&amp;quot; + __(&amp;quot;lang_mainsite&amp;quot;, &amp;quot;You&amp;quot;) + &amp;quot;&amp;lt;/span&amp;gt;&amp;quot;;&lt;br /&gt;
            return you;&lt;br /&gt;
        },&lt;br /&gt;
&lt;br /&gt;
        /* Implementation of proper colored player name with background in case of white or light colors  */&lt;br /&gt;
&lt;br /&gt;
        divColoredPlayer: function(player_id) {&lt;br /&gt;
            var color = this.gamedatas.players[player_id].color;&lt;br /&gt;
            var color_bg = &amp;quot;&amp;quot;;&lt;br /&gt;
            if (this.gamedatas.players[player_id] &amp;amp;&amp;amp; this.gamedatas.players[player_id].color_back) {&lt;br /&gt;
                color_bg = &amp;quot;background-color:#&amp;quot; + this.gamedatas.players[player_id].color_back + &amp;quot;;&amp;quot;;&lt;br /&gt;
            }&lt;br /&gt;
            var div = &amp;quot;&amp;lt;span style=\&amp;quot;color:#&amp;quot; + color + &amp;quot;;&amp;quot; + color_bg + &amp;quot;\&amp;quot;&amp;gt;&amp;quot; + this.gamedatas.players[player_id].name + &amp;quot;&amp;lt;/span&amp;gt;&amp;quot;;&lt;br /&gt;
            return div;&lt;br /&gt;
        },&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Cool realistic shadow effect with CSS ===&lt;br /&gt;
&lt;br /&gt;
==== Rectangles and circles ====&lt;br /&gt;
&lt;br /&gt;
It is often nice to have a drop shadow around tiles and tokens, to separate them from the table visually. It is very easy to add a shadow to rectangular elements, just add this to your css:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
.xxx-tile {&lt;br /&gt;
    box-shadow: 3px 3px 3px #000000a0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
box-shadow obeys &#039;&#039;&#039;border-radius&#039;&#039;&#039; of the element, so it will look good for rounded rectangles, and hence also circles (if border-radius is set appropriately).&lt;br /&gt;
&lt;br /&gt;
box-shadow also supports various other parameters and can be used to achieve effects such as glowing, borders, inner shadows etc. If you need to animate a box-shadow, you may be able to get better performance (avoiding redraws) if you attach the shadow to another element (possibly an ::after pseudo-element) and change only the &#039;&#039;&#039;opacity&#039;&#039;&#039; of that element.&lt;br /&gt;
&lt;br /&gt;
==== Irregular Shapes ====&lt;br /&gt;
&lt;br /&gt;
If you wish to make a shadow effect for game pieces that are not a rectangle, but your game pieces are drawn from rectangles in a PNG image, you can apply the shadow to the piece using any art package and save it inside the image. This usually will yield the best performance. Remember to account for the size of the shadow when you lay out images in the sprite sheet.&lt;br /&gt;
&lt;br /&gt;
However that sometimes will not be an option, for example if the image needs to be rotated while the shadow remains offset in the same direction. In this case, one option is to not use box-shadow but use filter, which is supported by recent major browsers.  This way, you can use the alpha channel of your element to drop a shadow.  This even work for transparent backgrounds, so that if you are using the &amp;quot;CSS-sprite&amp;quot; method, it will work!&lt;br /&gt;
&lt;br /&gt;
For instance:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
.xxx-token {&lt;br /&gt;
    filter: drop-shadow(0px 0px 1px #000000);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Beware that some browsers still do not always draw drop-shadow correctly. In particular, Safari frequently leaves bits of shadow behind when objects move around the screen. In Chrome, shadows sometimes flicker badly if another element is animating close by. Some of these correctness issues can be solved by adding &#039;&#039;&#039;isolation: isolate; will-change: filter;&#039;&#039;&#039; to affected elements, but this significantly affects redraw performance.&lt;br /&gt;
&lt;br /&gt;
Beware of performance issues - particularly on Safari (MacOS, iPhone and iPad). Keep in mind that drop-shadow are very GPU intensive. This becomes noticeable once you have about 40 components with drop-shadow filter. If that is your case, you can quite easily implement a user preference to disable shadows for users on slower machines:&lt;br /&gt;
&lt;br /&gt;
gameoptions.inc.php&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
100 =&amp;gt; array(&lt;br /&gt;
			&#039;name&#039; =&amp;gt; totranslate(&#039;Shadows&#039;),&lt;br /&gt;
			&#039;needReload&#039; =&amp;gt; true, // after user changes this preference game interface would auto-reload&lt;br /&gt;
			&#039;values&#039; =&amp;gt; array(&lt;br /&gt;
					1 =&amp;gt; array( &#039;name&#039; =&amp;gt; totranslate( &#039;Enabled&#039; ), &#039;cssPref&#039; =&amp;gt; &#039;&#039; ),&lt;br /&gt;
					2 =&amp;gt; array( &#039;name&#039; =&amp;gt; totranslate( &#039;Disabled&#039; ), &#039;cssPref&#039; =&amp;gt; &#039;no-shadow&#039; )&lt;br /&gt;
			)&lt;br /&gt;
	),&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[game].css&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
.no-shadow * {&lt;br /&gt;
	filter: none !important; &lt;br /&gt;
} &lt;br /&gt;
&amp;lt;/pre&amp;gt;For Safari, it is usually better to simply disable drop-shadow completely: [[Game interface stylesheet: yourgamename.css#Warning: using drop-shadow]].&lt;br /&gt;
&lt;br /&gt;
==== Shadows with clip-path ====&lt;br /&gt;
&lt;br /&gt;
For some reason, a shadow will not work together with clip-path on one element. To use both clip-path (when for example using .svg to cut out cardboard components from your .jpg spritesheet) and drop-shadow, you need to wrap the element into another one, and apply drop-shadow to the outer one, and clip-path to the inner one.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;div class=&#039;my-token-wrap&#039;&amp;gt;&lt;br /&gt;
  &amp;lt;div class=&#039;my-token&#039;&amp;gt;&lt;br /&gt;
  &amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
.my-token-wrap {&lt;br /&gt;
    filter: drop-shadow(0px 0px 1px #000000);&lt;br /&gt;
}&lt;br /&gt;
.my-token-wrap .my-token {&lt;br /&gt;
    clip-path: url(#my-token-path);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Using the CSS classes from the state machine ===&lt;br /&gt;
&lt;br /&gt;
If you need to hide or show stuff depending on the state of your game, you can of course use javascript, but CSS is hand enough for that.  The #overall-content element does change class depending on the game state.  For instance, if you are in state &#039;&#039;playerTurn&#039;&#039;, it will have the class &#039;&#039;gamestate_playerTurn&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
So now, if you want to show the discard pile only during player turns, you may use:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#discard_pile { display: none }&lt;br /&gt;
.gamestate_playerTurn #discard_pile { display: block }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This can be used if you want to change sizing of elements, position, layout or visual appearance.&lt;br /&gt;
&lt;br /&gt;
== Game Model and Database design ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Database for The euro game ===&lt;br /&gt;
Lets say we have a game with workers, dice, tokens, board, resources, money and vp. Workers and dice can be placed in various zones on the board, and you can get resources, money, tokens and vp in your home zone. Also tokens can be flipped or not flipped.&lt;br /&gt;
&lt;br /&gt;
[[File:Madeira board.png]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Now lets try to map it, we have&lt;br /&gt;
* (meeple,zone)&lt;br /&gt;
* (die, zone, sideup)&lt;br /&gt;
* (resource cube/money token/vp token,player home zone)&lt;br /&gt;
* (token, player home zone, flip state)&lt;br /&gt;
We can notice that resource and money are uncountable, and don&#039;t need to be track individually so we can replace our mapping to&lt;br /&gt;
* (resource type/money,player home zone, count)&lt;br /&gt;
And vp stored already for us in player table, so we can remove it from that list.&lt;br /&gt;
&lt;br /&gt;
Now when we get to encode it we can see that everything can be encoded as (object,zone,state) form, where object and zone is string and state is integer. The resource mapping is slightly different semantically so you can go with two table, or counting using same table with state been used as count for resources.&lt;br /&gt;
&lt;br /&gt;
So the piece mapping for non-grid based games can be in most case represented by (string: token_key, string: token_location, int: token_state), example of such database schema can be found here: [https://github.com/elaskavaia/bga-sharedcode/blob/master/dbmodel.sql dbmodel.sql] and class implementing access to it here [https://github.com/elaskavaia/bga-sharedcode/blob/master/modules/tokens.php table.game.php].&lt;br /&gt;
&lt;br /&gt;
Variant 1: Minimalistic&lt;br /&gt;
&lt;br /&gt;
 CREATE TABLE IF NOT EXISTS `token` (&lt;br /&gt;
  `token_key` varchar(32) NOT NULL,&lt;br /&gt;
  `token_location` varchar(32) NOT NULL,&lt;br /&gt;
  `token_state` int(10),&lt;br /&gt;
  PRIMARY KEY (`token_key`)&lt;br /&gt;
 ) ENGINE=InnoDB DEFAULT CHARSET=utf8;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+token&lt;br /&gt;
! token_key&lt;br /&gt;
! token_location&lt;br /&gt;
! token_state&lt;br /&gt;
|-&lt;br /&gt;
|meeple_red_1&lt;br /&gt;
|home_red&lt;br /&gt;
|0&lt;br /&gt;
|-&lt;br /&gt;
|dice_black_2&lt;br /&gt;
|board_guard&lt;br /&gt;
|1&lt;br /&gt;
|-&lt;br /&gt;
|dice_green_1&lt;br /&gt;
|board_action_mayor&lt;br /&gt;
|3&lt;br /&gt;
|-&lt;br /&gt;
|bread&lt;br /&gt;
|home_red&lt;br /&gt;
|5&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Now how we represent resource counters such as bread?&lt;br /&gt;
Using same table from we simply add special counter token for bread and use state to indicate the count. Note to keep first column unique we have to add player identification for that counter, i.e. ff0000 is red player.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+token&lt;br /&gt;
! token_key&lt;br /&gt;
! token_location&lt;br /&gt;
! token_state&lt;br /&gt;
|-&lt;br /&gt;
|bread_ff0000&lt;br /&gt;
|tableau_ff0000&lt;br /&gt;
|5&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
See php module for this table here https://github.com/elaskavaia/bga-sharedcode/blob/master/modules/tokens.php&lt;br /&gt;
&lt;br /&gt;
Variant 2: Additional resource table, resource count for each player id&lt;br /&gt;
&lt;br /&gt;
 CREATE TABLE IF NOT EXISTS `resource` (&lt;br /&gt;
  `player_id` int(10) unsigned NOT NULL,&lt;br /&gt;
  `resource_key` varchar(32) NOT NULL,&lt;br /&gt;
  `resource_count` int(10) signed NOT NULL,&lt;br /&gt;
  PRIMARY KEY (`player_id`,`resource_key`)&lt;br /&gt;
 ) ENGINE=InnoDB DEFAULT CHARSET=utf8;&lt;br /&gt;
&lt;br /&gt;
 ALTER TABLE resource ADD CONSTRAINT fk_player_id FOREIGN KEY (player_id) REFERENCES player(player_id);&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+resource&lt;br /&gt;
! player_id&lt;br /&gt;
! resource_key&lt;br /&gt;
! resource_count&lt;br /&gt;
|-&lt;br /&gt;
|123456&lt;br /&gt;
|bread&lt;br /&gt;
|5&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Variant 3: More normalised&lt;br /&gt;
&lt;br /&gt;
This version is similar to &amp;quot;card&amp;quot; table from hearts tutorial, you can also use exact cards database schema and Deck implementation for most purposes (even you not dealing with cards). &lt;br /&gt;
&lt;br /&gt;
 CREATE TABLE IF NOT EXISTS `token` (&lt;br /&gt;
  `token_id` int(10) unsigned NOT NULL AUTO_INCREMENT,&lt;br /&gt;
  `token_type` varchar(16) NOT NULL,&lt;br /&gt;
  `token_arg` int(11) NOT NULL,&lt;br /&gt;
  `token_location` varchar(32) NOT NULL,&lt;br /&gt;
  `token_state` int(10),&lt;br /&gt;
  PRIMARY KEY (`token_id`)&lt;br /&gt;
 ) ENGINE=InnoDB DEFAULT CHARSET=utf8;&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+token&lt;br /&gt;
! token_id&lt;br /&gt;
! token_type&lt;br /&gt;
! token_arg&lt;br /&gt;
! token_location&lt;br /&gt;
! token_state&lt;br /&gt;
|-&lt;br /&gt;
|22&lt;br /&gt;
|meeple&lt;br /&gt;
|123456&lt;br /&gt;
|home_123456&lt;br /&gt;
|0&lt;br /&gt;
|-&lt;br /&gt;
|23&lt;br /&gt;
|dice&lt;br /&gt;
|2&lt;br /&gt;
|board_guard&lt;br /&gt;
|1&lt;br /&gt;
|-&lt;br /&gt;
|26&lt;br /&gt;
|dice&lt;br /&gt;
|1&lt;br /&gt;
|board_action_mayor&lt;br /&gt;
|3&lt;br /&gt;
|-&lt;br /&gt;
|49&lt;br /&gt;
|bread&lt;br /&gt;
|0&lt;br /&gt;
|home_123456&lt;br /&gt;
|5&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Advantages of this would be is a bit more straightforward to do some queries in db, disadvantage its hard to read (as you can compare with previous example, you&lt;br /&gt;
cannot just look at say, ah I know what it means). Another questionable advantage is it allows you to do id randomisation, so it hard to do crafted queries to &lt;br /&gt;
cheat, the down side of that you cannot understand it either, and handcraft db states for debugging or testing.&lt;br /&gt;
&lt;br /&gt;
=== Database for The card game ===&lt;br /&gt;
&lt;br /&gt;
Lets say you have a standard card game, player have hidden cards in hand, you can draw card from draw deck, play card on tableau and discard to discard pile.&lt;br /&gt;
We have to design database for such game.&lt;br /&gt;
&lt;br /&gt;
In real word to &amp;quot;save&amp;quot; the game we take a picture a play area, save cards from it, then put away draw deck, discard and hand of each player separately and mark it, also we will record current scoring (if any) and who&#039;s turn was it.&lt;br /&gt;
&lt;br /&gt;
* Framework handles state machine transition, so you don&#039;t have to worry about database design for that (i.e. who&#039;s turn it is, what phase of the game we are at, you still have to design it but part of state machine step)&lt;br /&gt;
* Also framework supports basic player information, color, order around the table, basic scoring, etc, so you don&#039;t have to worry about it either&lt;br /&gt;
* The only thing you need in our database is state of the &amp;quot;board&amp;quot;, which is &amp;quot;where each pieces is, and in what state&amp;quot;, or (position,rotation) pair.&lt;br /&gt;
&lt;br /&gt;
Lets see what we have for that:&lt;br /&gt;
* The card state is very simple, its usually &amp;quot;face up/face down&amp;quot;, &amp;quot;tapped/untapped&amp;quot;, &amp;quot;right side up/up side down&amp;quot;&lt;br /&gt;
* As position go we never need real coordinates x,y,z. We need to know what &amp;quot;zone&amp;quot; card was, and depending on the zone it may sometimes need an extra &amp;quot;z&amp;quot; or &amp;quot;x&amp;quot; as card order. The zone position usually static or irrelevant.&lt;br /&gt;
* So our model is: we have cards, which have some attributes, at any given point in time they belong to a &amp;quot;zone&amp;quot;, and can also have order and state&lt;br /&gt;
* Now for mapping we should consider what information changes and what information is static, later is always candidate for material file&lt;br /&gt;
* For dynamic information we should try to reduce amount of fields we need&lt;br /&gt;
**  we need at least a field for card, so its one&lt;br /&gt;
**  we need to know what zone cards belong to, its 2&lt;br /&gt;
**  and we have possibly few other fields, if you look closely at you game you may find out that most of the zone only need one attribute at a time, i.e. draw pile always have cards face down, hand always face up, also for hand and discard order does not matter at all (but for draw it does matter). So in majority of cases we can get away with one single extra integer field representing state or order&lt;br /&gt;
* In real database both card and zone will be integers as primary keys referring to additional tables, but in our case its total overkill, so they can be strings as easily&lt;br /&gt;
&lt;br /&gt;
Variant 1: Minimalistic&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
CREATE TABLE IF NOT EXISTS `card` (&lt;br /&gt;
  `card_key` varchar(32) unsigned NOT NULL,&lt;br /&gt;
  `card_location` varchar(32) NOT NULL,&lt;br /&gt;
  `card_state` int(11) NOT NULL,&lt;br /&gt;
  PRIMARY KEY (`card_id`)&lt;br /&gt;
) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=1 ;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Variant 2: More normalised&lt;br /&gt;
&lt;br /&gt;
This version supported by Deck php class, so unless you want to rewrite db access layer go with this one&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
CREATE TABLE IF NOT EXISTS `card` (&lt;br /&gt;
  `card_id` int(10) unsigned NOT NULL AUTO_INCREMENT,&lt;br /&gt;
  `card_type` varchar(16) NOT NULL,&lt;br /&gt;
  `card_type_arg` int(11) NOT NULL,&lt;br /&gt;
  `card_location` varchar(16) NOT NULL,&lt;br /&gt;
  `card_location_arg` int(11) NOT NULL,&lt;br /&gt;
  PRIMARY KEY (`card_id`)&lt;br /&gt;
) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=1 ;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note: if you using this schema, some zones/locations have special semantic. The &#039;hand&#039; location is actually multiple locations - one per player, but player id is encoded as card_location_arg. If &#039;hand&#039; in your game is ordered, visible or can have some other card states, you cannot use hand location (replacement is hand_&amp;lt;player_id&amp;gt; or hand_&amp;lt;color_id&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
== Code Organization ==&lt;br /&gt;
&lt;br /&gt;
=== Including your own JavaScript module ===&lt;br /&gt;
&#039;&#039;&#039;Ingredients:&#039;&#039;&#039; ggg.js, modules/ggg_other.js&lt;br /&gt;
&lt;br /&gt;
* Create ggg_other.js in modules/ folder and sync&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
define([&lt;br /&gt;
    &amp;quot;dojo&amp;quot;, &amp;quot;dojo/_base/declare&amp;quot;&lt;br /&gt;
], function( dojo, declare )&lt;br /&gt;
{&lt;br /&gt;
return declare(&amp;quot;bgagame.other&amp;quot;, null, { // null here if we don&#039;t want to inherit from anything&lt;br /&gt;
        constructor: function(){},&lt;br /&gt;
        mystuff: function(){},&lt;br /&gt;
    });&lt;br /&gt;
        &lt;br /&gt;
});&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
* Modify ggg.js to include it&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
  define([ &amp;quot;dojo&amp;quot;, &amp;quot;dojo/_base/declare&amp;quot;, &amp;quot;ebg/core/gamegui&amp;quot;, &amp;quot;ebg/counter&amp;quot;,&lt;br /&gt;
    g_gamethemeurl + &amp;quot;modules/ggg_other.js&amp;quot;     // load my own module!!!&lt;br /&gt;
  ], function(dojo,&lt;br /&gt;
        declare) {&lt;br /&gt;
     &lt;br /&gt;
&lt;br /&gt;
use it&lt;br /&gt;
&lt;br /&gt;
  foo = new bgagame.other();&lt;br /&gt;
&lt;br /&gt;
=== Including your own JavaScript module (II) ===&lt;br /&gt;
&lt;br /&gt;
* Create ggg_other.js in modules/ folder and sync&lt;br /&gt;
&lt;br /&gt;
  define([], function () {&lt;br /&gt;
    return &amp;quot;value&amp;quot;;&lt;br /&gt;
  });&lt;br /&gt;
&lt;br /&gt;
* Modify ggg.js to include it&lt;br /&gt;
&lt;br /&gt;
  define([ &lt;br /&gt;
    &amp;quot;dojo&amp;quot;, &lt;br /&gt;
    &amp;quot;dojo/_base/declare&amp;quot;, &lt;br /&gt;
    &amp;quot;bgagame/modules/ggg_other&amp;quot;, &lt;br /&gt;
    &amp;quot;ebg/core/gamegui&amp;quot;, &lt;br /&gt;
    &amp;quot;ebg/counter&amp;quot;&lt;br /&gt;
  ], function(dojo, declare, other) {&lt;br /&gt;
  &lt;br /&gt;
  });&lt;br /&gt;
&lt;br /&gt;
  &lt;br /&gt;
This is maybe a little bit more the idea of the AMD Loader than the first option, although the first option should work as well.&lt;br /&gt;
&lt;br /&gt;
A little explanation to this:&lt;br /&gt;
The define function loads all the modules listed in the array and calls the following function with these loaded modules as parameters.&lt;br /&gt;
By putting your module at the third position in the array it is passed as the third parameter to the function. Be aware that the modules are resolved by position only, not by name. So you can load the module &#039;&#039;&#039;ggg_other&#039;&#039;&#039; and pass it as a parameter with the name &#039;&#039;&#039;other&#039;&#039;&#039;. &#039;&#039;&#039;gamegui&#039;&#039;&#039; and &#039;&#039;&#039;counter&#039;&#039;&#039; are passed in as well, but when the parameters are not defined they are just skipped. Because these modules put their content into the global scope it does not matter and you can use them from there.&lt;br /&gt;
&lt;br /&gt;
In the example above the string &amp;quot;value&amp;quot; is passed for the parameter &#039;&#039;&#039;other&#039;&#039;&#039;, but the function in your module can return whatever you want. It can be an object, an array, something you declared with dojo.declare, you can return even functions. &lt;br /&gt;
Your module can load other modules. Just put them in the array at the beginning and pass them as parameters to your function.&lt;br /&gt;
The advantage of passing the values as parameter is that you do not need to put these values in the global scope, so they can&#039;t be collisions with values defined in other scripts or the BGA Framework.&lt;br /&gt;
&lt;br /&gt;
The dojo toolkit provides good documentation to all of its components, the complete documentation for the AMD-Loader is here:&lt;br /&gt;
https://dojotoolkit.org/documentation/tutorials/1.10/modules/index.html It should be still correct, even as it seems to be only for version 1.10&lt;br /&gt;
&lt;br /&gt;
=== Including your own PHP module ===&lt;br /&gt;
&#039;&#039;&#039;Ingredients:&#039;&#039;&#039; ggg.game.php, modules/ggg_other.php&lt;br /&gt;
&lt;br /&gt;
* Create ggg_other.php in modules/ folder and sync&lt;br /&gt;
* Modify ggg.game.php to include it&lt;br /&gt;
&lt;br /&gt;
 require_once (&#039;modules/ggg_other.php&#039;);&lt;br /&gt;
&lt;br /&gt;
=== Creating a test class to run PHP locally ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Ingredients:&#039;&#039;&#039; ggg.game.php, stubs&lt;br /&gt;
For this you need stubs of other method you can use this for example&lt;br /&gt;
https://github.com/elaskavaia/bga-sharedcode/raw/master/misc/module/table/table.game.php&lt;br /&gt;
&lt;br /&gt;
Create another php files, i.e ggg_test.php&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;?php&lt;br /&gt;
define(&amp;quot;APP_GAMEMODULE_PATH&amp;quot;, &amp;quot;misc/&amp;quot;); // include path to stubs, which defines &amp;quot;table.game.php&amp;quot; and other classes&lt;br /&gt;
require_once (&#039;eminentdomaine.game.php&#039;);&lt;br /&gt;
&lt;br /&gt;
class MyGameTest1 extends MyGame { // this is your game class defined in ggg.game.php&lt;br /&gt;
    function __construct() {&lt;br /&gt;
        parent::__construct();&lt;br /&gt;
        include &#039;../material.inc.php&#039;;// this is how this normally included, from constructor&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // override/stub methods here that access db and stuff&lt;br /&gt;
    function getGameStateValue($var) {&lt;br /&gt;
        if ($var == &#039;round&#039;)&lt;br /&gt;
            return 3;&lt;br /&gt;
        return 0;&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
$x = new MyGameTest1(); // instantiate your class&lt;br /&gt;
$p = $x-&amp;gt;getGameProgression(); // call one of the methods to test&lt;br /&gt;
if ($p != 50)&lt;br /&gt;
    echo &amp;quot;Test1: FAILED&amp;quot;;&lt;br /&gt;
else&lt;br /&gt;
    echo &amp;quot;Test1: PASSED&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Run from command line like&lt;br /&gt;
 php7 ggg_test.php&lt;br /&gt;
&lt;br /&gt;
If you do it this way - you can also use local php debugger (i.e. integrated with IDE or command line).&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Avoiding code in dojo declare style ===&lt;br /&gt;
Dojo class declarations are rather bizzare and do not work with most IDEs.&lt;br /&gt;
If you want to write in plain JS with classes, you can stub all the dojo define/declare stuff&lt;br /&gt;
and hook your class into that, so the classes are outside of this mess.&lt;br /&gt;
&lt;br /&gt;
NOTE: this technique is for experienced developers, do not try it if you do not understand&lt;br /&gt;
the consequences.&lt;br /&gt;
&lt;br /&gt;
This is complete example of game .js class&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  // Testla is game name is has to be changed&lt;br /&gt;
class Testla {&lt;br /&gt;
	constructor(game) {&lt;br /&gt;
		console.log(&#039;game constructor&#039;);&lt;br /&gt;
		this.game = game;&lt;br /&gt;
		this.varfoo = new MyFoo(); // this example of class from custom module&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	setup(gamedatas) {&lt;br /&gt;
		console.log(&amp;quot;Starting game setup&amp;quot;, this.varfoo);&lt;br /&gt;
		this.gamedatas = gamedatas;&lt;br /&gt;
		this.dojo.create(&amp;quot;div&amp;quot;, { class: &#039;whiteblock&#039;, innerHTML: _(&amp;quot;hello&amp;quot;) }, &#039;thething&#039;);&lt;br /&gt;
		console.log(&amp;quot;Ending game setup&amp;quot;);&lt;br /&gt;
	};&lt;br /&gt;
	onEnteringState(stateName, args) {&lt;br /&gt;
		console.log(&#039;onEnteringState : &#039; + stateName, args);&lt;br /&gt;
		this.game.addActionButton(&#039;b1&#039;,_(&#039;Click Me&#039;), (e)=&amp;gt;this.onButtonClick(e));&lt;br /&gt;
	};&lt;br /&gt;
	onLeavingState(stateName) {&lt;br /&gt;
		console.log(&#039;onLeavingState : &#039; + stateName, args);&lt;br /&gt;
	};&lt;br /&gt;
	onUpdateActionButtons(stateName, args) {&lt;br /&gt;
		console.log(&#039;onUpdateActionButtons : &#039; + stateName, args);&lt;br /&gt;
	};&lt;br /&gt;
	onButtonClick(event) {&lt;br /&gt;
		console.log(&#039;onButtonClick&#039;,event);&lt;br /&gt;
	};&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
define([&lt;br /&gt;
	&amp;quot;dojo&amp;quot;, &amp;quot;dojo/_base/declare&amp;quot;,&lt;br /&gt;
	&amp;quot;ebg/core/gamegui&amp;quot;,&lt;br /&gt;
	&amp;quot;ebg/counter&amp;quot;,&lt;br /&gt;
	g_gamethemeurl + &#039;/modules/foo.js&#039; // custom module if needed&lt;br /&gt;
],&lt;br /&gt;
	function(dojo, declare) {&lt;br /&gt;
                // testla is game name is has to be changed&lt;br /&gt;
		return declare(&amp;quot;bgagame.testla&amp;quot;, ebg.core.gamegui, {&lt;br /&gt;
			constructor: function() {&lt;br /&gt;
				this.xapp = new Testla(this);&lt;br /&gt;
				this.xapp.dojo = dojo;&lt;br /&gt;
			},&lt;br /&gt;
			setup: function(gamedatas) {&lt;br /&gt;
				this.xapp.setup(gamedatas);&lt;br /&gt;
			},&lt;br /&gt;
			onEnteringState: function(stateName, args) {&lt;br /&gt;
				this.xapp.onEnteringState(stateName, args?.args);&lt;br /&gt;
			},&lt;br /&gt;
			onLeavingState: function(stateName) {&lt;br /&gt;
				this.xapp.onLeavingState(stateName, args);&lt;br /&gt;
			},&lt;br /&gt;
			onUpdateActionButtons: function(stateName, args) {&lt;br /&gt;
				this.xapp.onUpdateActionButtons(stateName, args);&lt;br /&gt;
			},&lt;br /&gt;
		});&lt;br /&gt;
	});&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== More readable JS: onEnteringState ===&lt;br /&gt;
&lt;br /&gt;
If you have a lot of states in onEnteringState or onUpdateActionButtons and friends - it becomes rather wild, you can do this trick to call some methods dynamically.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
     onEnteringState: function(stateName, args) {&lt;br /&gt;
       console.log(&#039;Entering state: &#039; + stateName, args);&lt;br /&gt;
&lt;br /&gt;
       // Call appropriate method&lt;br /&gt;
       var methodName = &amp;quot;onEnteringState_&amp;quot; + stateName;&lt;br /&gt;
       if (this[methodName] !== undefined) {             &lt;br /&gt;
          console.log(&#039;Calling &#039; + methodName, args.args);&lt;br /&gt;
          this[methodName](args.args);&lt;br /&gt;
       }&lt;br /&gt;
     },&lt;br /&gt;
&lt;br /&gt;
     onEnteringState_playerTurn: function(args) { // this is args directly, not args.args &lt;br /&gt;
         // process&lt;br /&gt;
     },&lt;br /&gt;
&lt;br /&gt;
     onEnteringState_playerSomethingElse: function(args) { &lt;br /&gt;
         // process&lt;br /&gt;
     },&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note: since its ignores the undefined functions you don&#039;t have define function for each state, but on the other hand you cannot make typos.&lt;br /&gt;
Same applies to onUpdateActionButtons except you pass &#039;args&#039; to method, not args.args, and for onLeavingState where you don&#039;t pass anything.&lt;br /&gt;
&lt;br /&gt;
=== Frameworks and Preprocessors ===&lt;br /&gt;
&lt;br /&gt;
* [[BGA Type Safe Template]] - Setting up a fully typed project using typescript and more!&lt;br /&gt;
* [[Using Vue]] - work-in-progress guide on using the modern framework Vue.js to create a game&lt;br /&gt;
* [[Using Typescript and Scss]] - How to auto-build Typescript and SCSS files to make your code cleaner&lt;br /&gt;
&lt;br /&gt;
== Backend ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Assigning Player Order ===&lt;br /&gt;
Normally when game starts there is &amp;quot;natural&amp;quot; player order assigned randomly.&lt;br /&gt;
&lt;br /&gt;
If you want to deliberatly assign player order at the start of the game (for example, in a game with teams options), you can do so by retrieving the initialization-only player attribute &#039;&#039;&#039;player_table_order&#039;&#039;&#039; and using it to assign values to &#039;&#039;&#039;player_no&#039;&#039;&#039; (which is normally assigned at the start of a game in the order in which players come to the table). (See [https://en.doc.boardgamearena.com/Game_database_model:_dbmodel.sql#The_player_table Game database model] for more details.)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Example:&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
                // Retrieve inital player order ([0=&amp;gt;playerId1, 1=&amp;gt;playerId2, ...])&lt;br /&gt;
		$playerInitialOrder = [];&lt;br /&gt;
		foreach ($players as $playerId =&amp;gt; $player) {&lt;br /&gt;
			$playerInitialOrder[$player[&#039;player_table_order&#039;]] = $playerId;&lt;br /&gt;
		}&lt;br /&gt;
		ksort($playerInitialOrder);&lt;br /&gt;
		$playerInitialOrder = array_flip(array_values($playerInitialOrder));&lt;br /&gt;
&lt;br /&gt;
		// Player order based on &#039;playerTeams&#039; option&lt;br /&gt;
		$playerOrder = [0, 1, 2, 3];&lt;br /&gt;
		switch ($this-&amp;gt;getGameStateValue(&#039;playerTeams&#039;)) {&lt;br /&gt;
			case $this-&amp;gt;TEAM_1_2:&lt;br /&gt;
				$playerOrder = [0, 2, 1, 3];&lt;br /&gt;
				break;&lt;br /&gt;
			case $this-&amp;gt;TEAM_1_4:&lt;br /&gt;
				$playerOrder = [0, 1, 3, 2];&lt;br /&gt;
				break;&lt;br /&gt;
			case $this-&amp;gt;TEAM_RANDOM:&lt;br /&gt;
				shuffle($playerOrder);&lt;br /&gt;
				break;&lt;br /&gt;
			default:&lt;br /&gt;
			case $this-&amp;gt;TEAM_1_3:&lt;br /&gt;
				// Default order&lt;br /&gt;
				break;&lt;br /&gt;
		}&lt;br /&gt;
&lt;br /&gt;
                // Create players&lt;br /&gt;
		// Note: if you added some extra field on &amp;quot;player&amp;quot; table in the database (dbmodel.sql), you can initialize it there.&lt;br /&gt;
		$sql =&lt;br /&gt;
			&#039;INSERT INTO player (player_id, player_color, player_canal, player_name, player_avatar, player_no) VALUES &#039;;&lt;br /&gt;
		$values = [];&lt;br /&gt;
&lt;br /&gt;
		foreach ($players as $playerId =&amp;gt; $player) {&lt;br /&gt;
			$color = array_shift($default_colors);&lt;br /&gt;
			$values[] =&lt;br /&gt;
				&amp;quot;(&#039;&amp;quot; .&lt;br /&gt;
				$playerId .&lt;br /&gt;
				&amp;quot;&#039;,&#039;$color&#039;,&#039;&amp;quot; .&lt;br /&gt;
				$player[&#039;player_canal&#039;] .&lt;br /&gt;
				&amp;quot;&#039;,&#039;&amp;quot; .&lt;br /&gt;
				addslashes($player[&#039;player_name&#039;]) .&lt;br /&gt;
				&amp;quot;&#039;,&#039;&amp;quot; .&lt;br /&gt;
				addslashes($player[&#039;player_avatar&#039;]) .&lt;br /&gt;
				&amp;quot;&#039;,&#039;&amp;quot; .&lt;br /&gt;
				$playerOrder[$playerInitialOrder[$playerId]] .&lt;br /&gt;
				&amp;quot;&#039;)&amp;quot;;&lt;br /&gt;
		}&lt;br /&gt;
		$sql .= implode(&#039;,&#039;, $values);&lt;br /&gt;
		$this-&amp;gt;DbQuery($sql);&lt;br /&gt;
		$this-&amp;gt;reattributeColorsBasedOnPreferences(&lt;br /&gt;
			$players,&lt;br /&gt;
			$gameinfos[&#039;player_colors&#039;]&lt;br /&gt;
		);&lt;br /&gt;
		$this-&amp;gt;reloadPlayersBasicInfos();&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Send different notifications to active player vs everybody else ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Ingredients:&#039;&#039;&#039; ggg.js&lt;br /&gt;
&lt;br /&gt;
Hack alert. This is a hack. We were hoping for proper solution by bga framework.&lt;br /&gt;
&lt;br /&gt;
This will allow you to send notification with two message one for specific player and one for everybody else including spectators.&lt;br /&gt;
Note that this does not split the data - all data must be shared.&lt;br /&gt;
&lt;br /&gt;
Add this to .js file (if you already overriding it merge obviously)&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
/** @Override */&lt;br /&gt;
format_string_recursive: function(log, args) {&lt;br /&gt;
   if (typeof args.log_others != &#039;undefined&#039; &amp;amp;&amp;amp; typeof args.player_id != &#039;undefined&#039; &amp;amp;&amp;amp; this.player_id != args.player_id)&lt;br /&gt;
	log = args.log_others;&lt;br /&gt;
   return this.inherited(arguments); // you must call this to call super &lt;br /&gt;
},&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Example of usage (from eminentdomain)&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    $this-&amp;gt;notifyAllPlayers(&#039;tokenMoved&#039;, &lt;br /&gt;
             clienttranslate(&#039;${player_name} adds +2 Colonies to ${place_name}&#039;), // notification with show for player with player_id&lt;br /&gt;
             [&#039;player_id&#039;=&amp;gt;$player_id, // this is mandatory&lt;br /&gt;
             &#039;log_others&#039;=&amp;gt;clienttranslate(&#039;${player_name} adds +2 Colonies to an unknown planet&#039;), // notification will show for others&lt;br /&gt;
              ...&lt;br /&gt;
             ]);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Send transient notifications without incrementing move ID ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Ingredients:&#039;&#039;&#039; ggg.php&lt;br /&gt;
&lt;br /&gt;
Hack alert. This is a hack.&lt;br /&gt;
&lt;br /&gt;
Use this if you need to send some transient notification that should not create a new move ID. The notification should be idempotent -- it should have no practical effect on the game state and would be &#039;&#039;&#039;safe to drop&#039;&#039;&#039; (e.g., it would not matter if a player never received this notification). For example, in a co-op game you want all players to see a real-time preview of some action, before the active player commits their turn.&lt;br /&gt;
&lt;br /&gt;
Doing this mainly affects the instant replay &amp;amp; archive modes. During replay, the BGA framework automatically inserts a 1.5-second pause between each &amp;quot;move&amp;quot;. With this hack, your transient notifications are not considered to be a &amp;quot;move&amp;quot;, so no pause gets added.&lt;br /&gt;
&lt;br /&gt;
; In ggg.php&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$this-&amp;gt;not_a_move_notification = true; // note: do not increase the move counter&lt;br /&gt;
$this-&amp;gt;notifyAllPlayers(&#039;cardsPreview&#039;, &#039;&#039;, $args);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note: you cannot have code that send notification or even changes state after this, and you cannot reset this variable back either because it only takes effect when you exit action handling function&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Assorted Stuff ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Out-of-turn actions: Un-pass ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Ingredients:&#039;&#039;&#039; ggg.js, ggg.game.php, ggg.action.php, states.inc.php&lt;br /&gt;
&lt;br /&gt;
In multiplayer game sometimes players passes but than they think more and want to un-Pass and redo their choice. &lt;br /&gt;
To re-active a player who passes some trickery required.&lt;br /&gt;
&lt;br /&gt;
Define a special action that does that and hook it up.&lt;br /&gt;
&lt;br /&gt;
In states.inc.php add an action to mmultipleactiveplayer state to &amp;quot;unpass&amp;quot;, lets call it &amp;quot;actionCancel&amp;quot;&lt;br /&gt;
&lt;br /&gt;
In ggg.action.php add action hook&lt;br /&gt;
    public function actionCancel() {&lt;br /&gt;
        $this-&amp;gt;setAjaxMode();&lt;br /&gt;
        $this-&amp;gt;game-&amp;gt;actionCancel();&lt;br /&gt;
        $this-&amp;gt;ajaxResponse();&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
In ggg.game.php add action handler&lt;br /&gt;
    function actionCancel() {&lt;br /&gt;
        $this-&amp;gt;gamestate-&amp;gt;checkPossibleAction(&#039;actionCancel&#039;);&lt;br /&gt;
        $this-&amp;gt;gamestate-&amp;gt;setPlayersMultiactive(array ($this-&amp;gt;getCurrentPlayerId() ), &#039;error&#039;, false);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
Finally to call this in client ggg.js you would do something like:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 onUpdateActionButtons:  function(stateName, args) {&lt;br /&gt;
   if (this.isCurrentPlayerActive()) { &lt;br /&gt;
     // ...&lt;br /&gt;
   } else if (!this.isSpectator) { // player is NOT active but not spectator&lt;br /&gt;
       switch (stateName) {&lt;br /&gt;
          case &#039;playerTurnMultiPlayerState&#039;:&lt;br /&gt;
		this.addActionButton(&#039;button_unpass&#039;, _(&#039;Oh no!&#039;), &#039;onUnpass&#039;);&lt;br /&gt;
		break;&lt;br /&gt;
	}&lt;br /&gt;
   }&lt;br /&gt;
 }&lt;br /&gt;
				&lt;br /&gt;
 onUnpass: function(e) {&lt;br /&gt;
    this.bgaPerformAction(&amp;quot;actionCancel&amp;quot;, null, { checkAction: false }); // no checkAction!&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Although be careful that if the turn comes back to the player while he is about to click cancel, the action buttons will be updated and the player will misclick which can be quite frustrating. To avoid this, move the cancel button to another position, like to the left of pagemaintitletext:&lt;br /&gt;
  dojo.place(&#039;button_unpass&#039;, &#039;pagemaintitletext&#039;, &#039;before&#039;);&lt;br /&gt;
Being out of the generalactions div, it won&#039;t be automatically destroyed like normal buttons, so you&#039;ll have to handle that yourself in onLeavingState. You might also want to change the button color to red (blue buttons for active player only, red buttons also for inactive players?)&lt;br /&gt;
&lt;br /&gt;
Note: same technique can be used to do other out-of-turn actions, such as re-arranging cards in hand, exchanging resources, etc (i.e. if permitted by rules, such as &amp;quot;at any time player can...&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
=== Multi Step Interactions: Select Worker/Place Worker - Using Selection ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Ingredients:&#039;&#039;&#039; ggg.js&lt;br /&gt;
&lt;br /&gt;
Simple way to implement something like that without extra states is to use &amp;quot;selection&amp;quot; mechanism. When user click on worker add some sort of class into that element i.e. &#039;selected&#039; (which also have to have some indication by css i.e. outline).&lt;br /&gt;
&lt;br /&gt;
Than user can click on placement zone, you can use dojo.query for &amp;quot;selected&amp;quot; element and use it along with zone id to send data to server. If proper worker is not selected yet can give a error message using this.showMessage(...) function.&lt;br /&gt;
&lt;br /&gt;
Extra code required to properly cleanup selection between states.&lt;br /&gt;
Also when you do that sometimes you want to change the state prompt, see below &#039;Change state prompt&#039;&lt;br /&gt;
&lt;br /&gt;
=== Multi Step Interactions: Select Worker/Place Worker - Using Client States ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Ingredients:&#039;&#039;&#039; ggg.js&lt;br /&gt;
&lt;br /&gt;
I don&#039;t think its documented feature but there is a way to do client-only states, which is absolutely wonderful for few reasons&lt;br /&gt;
* When player interaction is two step process, such as select worker, place worker, or place worker, pick one of two resources of your choice&lt;br /&gt;
* When multi-step process can result of impossible situation and has to be undone (by rules)&lt;br /&gt;
* When multi-step process is triggered from multiple states (such as you can do same thing as activated card action, pass action or main action)&lt;br /&gt;
&lt;br /&gt;
So lets do Select Worker/Place Worker&lt;br /&gt;
&lt;br /&gt;
Define your server state as usual, i.e. playerMainTurn -&amp;gt; &amp;quot;You must pick up a worker&amp;quot;.&lt;br /&gt;
Now define a client state, we only need &amp;quot;name&amp;quot; and &amp;quot;descriptionmyturn&amp;quot;, lets say &amp;quot;client_playerPicksLocation&amp;quot;. Always prefix names of client state with &amp;quot;client_&amp;quot; to avoid confusion. Now we have to do the following:&lt;br /&gt;
* Have a handler for onUpdateActionButtons for playerMainTurn to activate all possible workers he can pick&lt;br /&gt;
* When player clicks workers, remember the worker in one of the members of the main class, I usually use one called this.clientStateArgs.&lt;br /&gt;
* Transition to new client state&lt;br /&gt;
  onWorker: function(e) {&lt;br /&gt;
      var id = event.currentTarget.id;&lt;br /&gt;
      dojo.stopEvent(event);&lt;br /&gt;
      ... // do validity checks&lt;br /&gt;
      this.clientStateArgs.worker_id = id;&lt;br /&gt;
      this.setClientState(&amp;quot;client_playerPicksLocation&amp;quot;, {&lt;br /&gt;
                                descriptionmyturn : _(&amp;quot;${you} must select location&amp;quot;),&lt;br /&gt;
                            });&lt;br /&gt;
   }&lt;br /&gt;
* Have a handler for onUpdateActionButtons for client_playerPicksLocation to activate all possible locations this worker can go AND add Cancel button (see below)&lt;br /&gt;
* Have a location handler which will eventually send a server request, using stored this.clientStateArgs.worker_id as worker id&lt;br /&gt;
* The cancel button should call a method to restore server state, also if you doing it for more than one state you can add this universally using this.on_client_state check&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
        if (this.isCurrentPlayerActive()) {&lt;br /&gt;
          if (this.on_client_state &amp;amp;&amp;amp; !$(&#039;button_cancel&#039;)) {&lt;br /&gt;
               this.addActionButton(&#039;button_cancel&#039;, _(&#039;Cancel&#039;), dojo.hitch(this, function() {&lt;br /&gt;
                                             this.restoreServerGameState();&lt;br /&gt;
               }));&lt;br /&gt;
          }&lt;br /&gt;
        } &lt;br /&gt;
Note: usually I call my own function call this.cancelLocalStateEffects() which will do more stuff first then call restoreServerGameState(), same function is usually needs to be called when server request has failed (i.e. invalid move)&lt;br /&gt;
&lt;br /&gt;
Note: If you need more than 2 steps, you may have to do client side animation to reflect the new state, which gets trickier because you have to undo that also on cancellation.&lt;br /&gt;
&lt;br /&gt;
Code is available here [https://github.com/elaskavaia/bga-sharedcode/blob/master/sharedcode.js sharedcode.js] (its using playerTurnPlayCubes and client_selectCubeLocation).&lt;br /&gt;
&lt;br /&gt;
=== Action Stack - Using Client States ===&lt;br /&gt;
&lt;br /&gt;
Action stack required where game is very complex and use triggered effects that can &amp;quot;stack&amp;quot;. It not always actual stack, it can be queue or random access&lt;br /&gt;
Examples:&lt;br /&gt;
* Magic the Gathering - classic card game where effects go on Stack, that allows to counter spell and counter spell of counter spell (not on bga - it just example of mechanics)&lt;br /&gt;
* Ultimate Railroads - action taking game where effects can be executed in any order&lt;br /&gt;
* Lewis and Clark - card game where actions executed as queue&lt;br /&gt;
&lt;br /&gt;
There is two ways of implementing it - on the server or the client.&lt;br /&gt;
For the server see article below.&lt;br /&gt;
The requirement for client side stack implementation is - all action can be undone, which means&lt;br /&gt;
* No dice rolls&lt;br /&gt;
* No card drawn&lt;br /&gt;
* No other players interaction&lt;br /&gt;
&lt;br /&gt;
No snippets are here, as this will be too complex but basically flow is:&lt;br /&gt;
* You have a action/effect stack (queue/list) as js object attached to &amp;quot;this&amp;quot;, i.e. this.unprocessed_actions&lt;br /&gt;
* When player plays a card, worker, etc, you read the effect of that card from the material file (client copy), and place into stack&lt;br /&gt;
* Then we call dispatch method which pulls the next action from the stack and change client state accordinly, i.e. this.setClientState(&amp;quot;client_playerGainsCubes&amp;quot;)&lt;br /&gt;
* When players acts on it - the action is removed from the stack and added to &amp;quot;server action arguments&amp;quot; list, this is another object which be used to send ajax call, i.e. this.clientStateArgs&lt;br /&gt;
* If nothing left in stack we can submit the ajax call assembling parameters from collected arguments (that can include action name)&lt;br /&gt;
* This method allows cheap undo - by restoring server state you will wipe out all user actions (but if you need intermediate aninmation you have to handle it yourself)&lt;br /&gt;
&lt;br /&gt;
Code can be found in Ultimate Railroads game (but it is random access list - so it a bit complex) and Lewis and Clark (complexity - user can always deny part of any effect)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Action Stack - Using Server States ===&lt;br /&gt;
&lt;br /&gt;
See definition of Action Stack above.&lt;br /&gt;
&lt;br /&gt;
To implement you usually need another db table that has the following fields: index of effect - which is used for sorted access, type - which is essense of the effect (i.e. collect resource), some extra arguments (i.e. resource type and resource count), and usually owner of the effect (i.e. player id)&lt;br /&gt;
The flow is:&lt;br /&gt;
* There is some initial player state, where player can play card for example&lt;br /&gt;
* Player main action - pushes the card effect on stack, which also can cause triggered effects which also go on stack&lt;br /&gt;
* After action processing is finished switch to game state which is &amp;quot;dispatcher&amp;quot;&lt;br /&gt;
* Dispatcher pulls the top effect (whatever definition of the top is), changes the active player and changes the state to appropriate player state to collect response. The &amp;quot;top&amp;quot; can be choice of multiple actions, in this case player has to chose one before resolving the effect.&lt;br /&gt;
* Player state knows about the stack and pulls arguments (argX) from the effect arguments of the db&lt;br /&gt;
* Player action should clear up the top effect, and can possibly add more effects, then switch to &amp;quot;dispatcher&amp;quot; state again&lt;br /&gt;
* If stack is empty, dispatcher can either pick next player itself or use another game state which responsible for picking next player&lt;br /&gt;
&lt;br /&gt;
Code can be found in Tapestry and Terraforming Mars.&lt;br /&gt;
=== Custom error/exception handling in JavaScript ===&lt;br /&gt;
&lt;br /&gt;
; In ggg.php&lt;br /&gt;
Throw BgaUserException with some easy-to-identify prefix such as &amp;quot;!!!&amp;quot; and a custom error code. DO NOT TRANSLATE this message text. The exception will rollback database transaction and cancel all changes (including any notifications).&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    function foo(bool $didConfirm = false): void&lt;br /&gt;
    {&lt;br /&gt;
        // do processing for the user&#039;s move&lt;br /&gt;
        // afterwards, you determine this move will end the game&lt;br /&gt;
        // so you want to rollback the transaction and require the user to confirm the move first&lt;br /&gt;
&lt;br /&gt;
        if ($gameIsEnding &amp;amp;&amp;amp; !$didConfirm) {&lt;br /&gt;
            throw new BgaUserException(&#039;!!!endGameConfirm&#039;, 9001);&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
; In ggg.js&lt;br /&gt;
Override framework function showMessage to suppress the red banner message and gamelog message when you detect the &amp;quot;!!!&amp;quot; prefix&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    /* @Override */&lt;br /&gt;
    showMessage: function (msg, type) {&lt;br /&gt;
      if (type == &amp;quot;error&amp;quot; &amp;amp;&amp;amp; msg &amp;amp;&amp;amp; msg.startsWith(&amp;quot;!!!&amp;quot;)) {&lt;br /&gt;
        return; // suppress red banner and gamelog message&lt;br /&gt;
      }&lt;br /&gt;
      this.inherited(arguments);&lt;br /&gt;
    },&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Deal with the error in your callback:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    fooAction: function (didConfirm) {&lt;br /&gt;
      var data = {&lt;br /&gt;
        foo: &amp;quot;bar&amp;quot;,&lt;br /&gt;
        didConfirm: !!didConfirm,&lt;br /&gt;
      };&lt;br /&gt;
      this.bgaPerformAction(&amp;quot;fooAction&amp;quot;, data).catch((error, errorMsg) =&amp;gt; {&lt;br /&gt;
        if (error &amp;amp;&amp;amp; errorMsg == &amp;quot;!!!endGameConfirm&amp;quot;) {&lt;br /&gt;
          // your custom error handling goes here&lt;br /&gt;
          // for example, show a confirmation dialog and repeat the action with additional param&lt;br /&gt;
          this.confirmationDialog(&lt;br /&gt;
            _(&amp;quot;Doing the foo action now will end the game&amp;quot;),&lt;br /&gt;
            () =&amp;gt; this.fooAction(true)&lt;br /&gt;
          );&lt;br /&gt;
        }&lt;br /&gt;
      });&lt;br /&gt;
    },&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
For custom global error handling, you could modify ajaxcallwrapper:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  ajaxcallwrapper: function (action, args, handler) {&lt;br /&gt;
    if (!args) args = {};&lt;br /&gt;
    args.lock = true;&lt;br /&gt;
    args.version = this.gamedatas.version;&lt;br /&gt;
    if (this.checkAction(action)) {&lt;br /&gt;
      this.bgaPerformAction(&lt;br /&gt;
        action,&lt;br /&gt;
        args&lt;br /&gt;
      ).catch((error, errorMsg, errorCode) =&amp;gt; {&lt;br /&gt;
          if (error &amp;amp;&amp;amp; errorMsg == &amp;quot;!!!checkVersion&amp;quot;) {&lt;br /&gt;
            this.infoDialog(&lt;br /&gt;
              _(&amp;quot;A new version of this game is now available&amp;quot;),&lt;br /&gt;
              _(&amp;quot;Reload Required&amp;quot;),&lt;br /&gt;
              () =&amp;gt; {&lt;br /&gt;
                window.location.reload();&lt;br /&gt;
              },&lt;br /&gt;
              true&lt;br /&gt;
            );&lt;br /&gt;
          } else {&lt;br /&gt;
            if (handler) handler(error, errorMsg, errorCode);&lt;br /&gt;
          }&lt;br /&gt;
        }&lt;br /&gt;
      );&lt;br /&gt;
    }&lt;br /&gt;
  },&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Force players to refresh after new deploy ===&lt;br /&gt;
&lt;br /&gt;
When you deploy a new version of your game, the PHP backend code is immediately updated but the JavaScript/HTML/CSS frontend code *does not update* for active players until they manually refresh the page (F5) in their browser. Obviously this is not ideal. In the best case, real-time tables don&#039;t see your shiny new enhancements. In the worst case, your old JS code isn&#039;t compatible with your new PHP code and the game breaks in strange ways (any bug reports filed will be false positives and unable to reproduce). To avoid any problems, you should force all players to immediately reload the page following a new deploy.&lt;br /&gt;
&lt;br /&gt;
By throwing a &amp;quot;visible&amp;quot; exception (simplest solution), you&#039;ll get something like this which instructs the user to reload:&lt;br /&gt;
&lt;br /&gt;
[[File:Force-refresh.png|950x950px]]&lt;br /&gt;
&lt;br /&gt;
Or, if you combine this technique with the above custom error handling technique, you could do something a bit nicer. You could show a dialog box and automatically refresh the page when the user clicks &amp;quot;OK&amp;quot;:&lt;br /&gt;
&lt;br /&gt;
[[File:Reload-required.png|500x500px]]&lt;br /&gt;
; In ggg.php&lt;br /&gt;
Transmit the server version number in &amp;lt;code&amp;gt;getAllDatas()&amp;lt;/code&amp;gt;.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    protected function getAllDatas(): array&lt;br /&gt;
    {&lt;br /&gt;
        $players = $this-&amp;gt;getCollectionFromDb(&amp;quot;SELECT player_id id, player_score score FROM player&amp;quot;);&lt;br /&gt;
        return [&lt;br /&gt;
            &#039;players&#039; =&amp;gt; $players,&lt;br /&gt;
            &#039;version&#039; =&amp;gt; intval($this-&amp;gt;gamestate-&amp;gt;table_globals[300]), // &amp;lt;-- ADD HERE&lt;br /&gt;
            ...&lt;br /&gt;
        ];&lt;br /&gt;
    }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Create a helper function to fail if the client and server versions mismatch. Note the version check uses &amp;lt;code&amp;gt;!=&amp;lt;/code&amp;gt; instead of &amp;lt;code&amp;gt;&amp;amp;lt;&amp;lt;/code&amp;gt; so it can support rollback to a previous deploy as well. ;-)&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    public function checkVersion(int $clientVersion): void&lt;br /&gt;
    {&lt;br /&gt;
        if ($clientVersion != intval($this-&amp;gt;gamestate-&amp;gt;table_globals[300])) {&lt;br /&gt;
            // Simplest way is to throw a &amp;quot;visible&amp;quot; exception&lt;br /&gt;
            // It&#039;s ugly but comes with a &amp;quot;click here&amp;quot; link to refresh&lt;br /&gt;
            throw new BgaVisibleSystemException($this-&amp;gt;_(&amp;quot;A new version of this game is now available. Please reload the page (F5).&amp;quot;));&lt;br /&gt;
&lt;br /&gt;
            // For something prettier, throw a &amp;quot;user&amp;quot; exception and handle in JS&lt;br /&gt;
            // (see BGA cookbook section above on custom error handling)&lt;br /&gt;
            throw new BgaUserException(&#039;!!!checkVersion&#039;);&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
; In ggg.action.php&lt;br /&gt;
Create a helper function for actions:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  private function checkVersion()&lt;br /&gt;
  {&lt;br /&gt;
    $clientVersion = (int) $this-&amp;gt;getArg(&#039;version&#039;, AT_int, false);&lt;br /&gt;
    $this-&amp;gt;game-&amp;gt;checkVersion($clientVersion);&lt;br /&gt;
  }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Call &amp;lt;code&amp;gt;$this-&amp;gt;checkVersion()&amp;lt;/code&amp;gt; at the top of &amp;lt;b&amp;gt;every action function&amp;lt;/b&amp;gt;, immediately after &amp;lt;code&amp;gt;$this-&amp;gt;setAjaxMode()&amp;lt;/code&amp;gt;:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  public function move()&lt;br /&gt;
  {&lt;br /&gt;
    $this-&amp;gt;setAjaxMode();&lt;br /&gt;
    $this-&amp;gt;checkVersion(); // &amp;lt;-- ADD HERE&lt;br /&gt;
    ...&lt;br /&gt;
    $this-&amp;gt;ajaxResponse();&lt;br /&gt;
  }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
; In ggg.js&lt;br /&gt;
Transmit the version (from gamedatas) as a parameter with every ajax call. For example, if you&#039;re already using a wrapper function for every ajax call, add it like this:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  ajaxcallwrapper: function (action, args) {&lt;br /&gt;
    if (!args) args = {};&lt;br /&gt;
    args.version = this.gamedatas.version; // &amp;lt;-- ADD HERE&lt;br /&gt;
    this.bgaPerformAction(action, args);&lt;br /&gt;
  },&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Disable / lock table creation for new deploy ===&lt;br /&gt;
&lt;br /&gt;
If you are deploying a major new game version, especially if it involves upgrading production game databases, you may have a lot of angry players if you break their tables.  Depending on your changes, you may be able to restore the previous version and fix the tables easily.&lt;br /&gt;
&lt;br /&gt;
However, if a new deploy turns out bad and players created turn-based tables while it was live, it may be quite difficult to fix those tables, since they were created from a bad deploy.&lt;br /&gt;
&lt;br /&gt;
The solution?  You can announce in your game group that you are locking table creation, and then in your new version, add an impossible startcondition to an existing option.  &lt;br /&gt;
Note: This only makes sense if you have a few games running in real time mode in the time of deployment, otherwise it won&#039;t achieve much, unless you wait at least a day for other turn based games to break (or not)&lt;br /&gt;
&lt;br /&gt;
Here is an example of an option with only 2 values (if you don&#039;t have options at all you have to create a fake option to use this method, if you have more values - you have to list them all):&lt;br /&gt;
&lt;br /&gt;
; In gameoptions.json&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        &amp;quot;startcondition&amp;quot;: {&lt;br /&gt;
            &amp;quot;0&amp;quot;: [ { &amp;quot;type&amp;quot;: &amp;quot;minplayers&amp;quot;, &amp;quot;value&amp;quot;: 32, &amp;quot;message&amp;quot;: &amp;quot;Maintenance in progress.  Table creation is disabled.&amp;quot; } ],&lt;br /&gt;
            &amp;quot;1&amp;quot;: [ { &amp;quot;type&amp;quot;: &amp;quot;minplayers&amp;quot;, &amp;quot;value&amp;quot;: 32, &amp;quot;message&amp;quot;: &amp;quot;Maintenance in progress.  Table creation is disabled.&amp;quot; } ]&lt;br /&gt;
        },&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
; In gameoptions.inc.php (older method if you have it in php)&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
// TODO NEXT remove after testing deploy to upgrade, here 0 and 1 - replace with values of your option!&lt;br /&gt;
&#039;startcondition&#039; =&amp;gt; [&lt;br /&gt;
   0 =&amp;gt; [ [ &#039;type&#039; =&amp;gt; &#039;minplayers&#039;, &#039;value&#039; =&amp;gt; 32, &#039;message&#039; =&amp;gt; totranslate(&#039;Maintenance in progress.  Table creation is disabled.&#039;) ] ],&lt;br /&gt;
   1 =&amp;gt; [ [ &#039;type&#039; =&amp;gt; &#039;minplayers&#039;, &#039;value&#039; =&amp;gt; 32, &#039;message&#039; =&amp;gt; totranslate(&#039;Maintenance in progress.  Table creation is disabled.&#039;) ] ],&lt;br /&gt;
],&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Be sure to click &amp;quot;Reload game options configuration&amp;quot; after making this change, then test in studio (test that you cannot create any table)&lt;br /&gt;
* Deploy to production&lt;br /&gt;
* Now, when a player attempts to create a new table, they will see a red error bar with your &amp;quot;Maintenance in progress&amp;quot; message.  &lt;br /&gt;
* Wait for screaming (if you have real times games in progress waiting 15 min probably ok, if you have only turn based games, probably a day)&lt;br /&gt;
* Once you confirm the new deploy looks good, you can revert the change in gameoptions.inc.php and do another deploy.&lt;br /&gt;
&lt;br /&gt;
=== Local Storage ===&lt;br /&gt;
&lt;br /&gt;
There is not much you can store in localStorage (https://developer.mozilla.org/docs/Web/API/Window/localStorage), since most stuff should be stored either in game db or in user prefrences,&lt;br /&gt;
but some stuff makes sense to store there, for example &amp;quot;zoom&amp;quot; level (if you use custom zooming). This setting really affect this specific host and specific browser, setting it localStorage makes most sense.&lt;br /&gt;
&lt;br /&gt;
game.js&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
   setup: function (gamedatas) {&lt;br /&gt;
        let zoom = localStorage.getItem(`${this.game_name}_zoom`);&lt;br /&gt;
        this.setZoom(zoom);&lt;br /&gt;
...&lt;br /&gt;
   },&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
In this case setZoom is custom function to actually set it.&lt;br /&gt;
When zoom changed, for example when some buttons pressed, store current value (but sanitize it so it never so bad that game cannot be viewed&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    setZoom: function (zoom) {&lt;br /&gt;
      zoom = parseInt(zoom) || 0;&lt;br /&gt;
      if (zoom === 0 || zoom &amp;lt; 0.1 || zoom &amp;gt; 10) {&lt;br /&gt;
        zoom = 1;&lt;br /&gt;
      }&lt;br /&gt;
      this.zoom = zoom;&lt;br /&gt;
      localStorage.setItem(`${this.game_name}_zoom`, &amp;quot;&amp;quot; + this.zoom);&lt;br /&gt;
... do actual zooming stuff&lt;br /&gt;
    },&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Capture client JavaScript errors in the &amp;quot;unexpected error&amp;quot; log ===&lt;br /&gt;
&lt;br /&gt;
PHP (backend) errors are recorded in the &amp;quot;unexpected error&amp;quot; log, but JavaScript (frontend) errors are only available in the browser itself. This means you have no visibility about things that go wrong in the client... unless you make clients report their errors to the server.&lt;br /&gt;
&lt;br /&gt;
; In actions.php:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  public function jsError()&lt;br /&gt;
  {&lt;br /&gt;
    $this-&amp;gt;setAjaxMode(false);&lt;br /&gt;
    $this-&amp;gt;game-&amp;gt;jsError($_POST[&#039;userAgent&#039;], $_POST[&#039;msg&#039;]);&lt;br /&gt;
    $this-&amp;gt;ajaxResponse();&lt;br /&gt;
  }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
; In game.php:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    public function jsError($userAgent, $msg): void&lt;br /&gt;
    {&lt;br /&gt;
        $this-&amp;gt;error(&amp;quot;JavaScript error from User-Agent: $userAgent\n$msg // &amp;quot;);&lt;br /&gt;
    }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
; In game.js:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
define([&amp;quot;dojo&amp;quot;, &amp;quot;dojo/_base/declare&amp;quot;, &amp;quot;ebg/core/gamegui&amp;quot;, &amp;quot;ebg/counter&amp;quot;], function (dojo, declare) {&lt;br /&gt;
  const uniqJsError = {};&lt;br /&gt;
  ...&lt;br /&gt;
&lt;br /&gt;
  return declare(&amp;quot;bgagame.nowboarding&amp;quot;, ebg.core.gamegui, {&lt;br /&gt;
    ...&lt;br /&gt;
    /* @Override */&lt;br /&gt;
    onScriptError(msg) {&lt;br /&gt;
      if (!uniqJsError[msg]) {&lt;br /&gt;
        uniqJsError[msg] = true;&lt;br /&gt;
        console.error(&amp;quot;⛔ Reporting JavaScript error&amp;quot;, msg);&lt;br /&gt;
        this.ajaxcall(&lt;br /&gt;
          &amp;quot;/&amp;quot; + this.game_name + &amp;quot;/&amp;quot; + this.game_name + &amp;quot;/jsError.html&amp;quot;,&lt;br /&gt;
          {&lt;br /&gt;
            msg,&lt;br /&gt;
            userAgent: navigator.userAgent,&lt;br /&gt;
          },&lt;br /&gt;
          this,&lt;br /&gt;
          () =&amp;gt; {},&lt;br /&gt;
          () =&amp;gt; {},&lt;br /&gt;
          &amp;quot;post&amp;quot;&lt;br /&gt;
        );&lt;br /&gt;
      }&lt;br /&gt;
      this.inherited(arguments);&lt;br /&gt;
    },&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Algorithms ==&lt;br /&gt;
&lt;br /&gt;
=== Generate permutations in lexicographic order ===&lt;br /&gt;
&lt;br /&gt;
Use this when you have an array like [1, 2, 3, 4] and need to loop over some/all 24 permutations of possible ordering. This type of [https://www.php.net/manual/en/language.generators.syntax.php generator function] computes each possibility one at a time, making it vastly more efficient than either a normal iteration or recursive function that produce all possibilities up front.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
function generatePermutations(array $array): Generator&lt;br /&gt;
{&lt;br /&gt;
    // https://en.wikipedia.org/wiki/Permutation#Generation_in_lexicographic_order&lt;br /&gt;
    // Sort the array and this is the first permutation&lt;br /&gt;
    sort($array);&lt;br /&gt;
    yield $array;&lt;br /&gt;
&lt;br /&gt;
    $count = count($array);&lt;br /&gt;
    do {&lt;br /&gt;
        // Find the largest index k where a[k] &amp;lt; a[k + 1]&lt;br /&gt;
        // End when no such index exists&lt;br /&gt;
        $found = false;&lt;br /&gt;
        for ($k = $count - 2; $k &amp;gt;= 0; $k--) {&lt;br /&gt;
            $kvalue = $array[$k];&lt;br /&gt;
            $knext = $array[$k + 1];&lt;br /&gt;
            if ($kvalue &amp;lt; $knext) {&lt;br /&gt;
                // Find the largest index l greater than k where a[k] &amp;lt; a[l]&lt;br /&gt;
                for ($l = $count - 1; $l &amp;gt; $k; $l--) {&lt;br /&gt;
                    $lvalue = $array[$l];&lt;br /&gt;
                    if ($kvalue &amp;lt; $lvalue) {&lt;br /&gt;
                        // Swap a[k] and a[l]&lt;br /&gt;
                        [$array[$k], $array[$l]] = [$array[$l], $array[$k]];&lt;br /&gt;
&lt;br /&gt;
                        // Reverse the sequence from a[k + 1] up to and including the final element&lt;br /&gt;
                        $reverse = array_reverse(array_slice($array, $k + 1));&lt;br /&gt;
                        array_splice($array, $k + 1, $count, $reverse);&lt;br /&gt;
                        yield $array;&lt;br /&gt;
&lt;br /&gt;
                        // Restart with the new array to find the next permutation&lt;br /&gt;
                        $found = true;&lt;br /&gt;
                        break 2;&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    } while ($found);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Usage:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$cash = [4, 1, 2, 3, 4];&lt;br /&gt;
foreach ($this-&amp;gt;generatePermutations($cash) as $p) {&lt;br /&gt;
    // your code here to evaluate permutation $p&lt;br /&gt;
    // first iteration: $p = [1, 2, 3, 4, 4]&lt;br /&gt;
    // last (60th) iteration: $p = [4, 4, 3, 2, 1]&lt;br /&gt;
    // break from loop once you achieve your goal&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Category:Studio]]&lt;/div&gt;</summary>
		<author><name>Sguzzer Gunayer</name></author>
	</entry>
	<entry>
		<id>https://en.doc.boardgamearena.com/index.php?title=Game_interface_logic:_Game.js&amp;diff=22701</id>
		<title>Game interface logic: Game.js</title>
		<link rel="alternate" type="text/html" href="https://en.doc.boardgamearena.com/index.php?title=Game_interface_logic:_Game.js&amp;diff=22701"/>
		<updated>2024-09-23T10:01:59Z</updated>

		<summary type="html">&lt;p&gt;Sguzzer Gunayer: /* Classes */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Studio_Framework_Navigation}}&lt;br /&gt;
&lt;br /&gt;
__TOC__&lt;br /&gt;
&lt;br /&gt;
This is the main file for your game interface. Here you will define:&lt;br /&gt;
&lt;br /&gt;
* Which actions on the page will generate calls to the server.&lt;br /&gt;
* What happens when you get a notification for a change from the server and how it will show in the browser. &lt;br /&gt;
* Setup user interface&lt;br /&gt;
&lt;br /&gt;
== File structure ==&lt;br /&gt;
&lt;br /&gt;
The details of how the file is structured are described below with comments in the code skeleton provided to you.&lt;br /&gt;
&lt;br /&gt;
Here is the basic structure:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;constructor&#039;&#039;&#039;: here you can define global variables for your whole interface.&lt;br /&gt;
* &#039;&#039;&#039;setup&#039;&#039;&#039;: this method is called when the page is refreshed, and sets up the game interface.&lt;br /&gt;
* &#039;&#039;&#039;onEnteringState&#039;&#039;&#039;: this method is called when entering a new game state. You can use it to customize the view for each game state.&lt;br /&gt;
* &#039;&#039;&#039;onLeavingState&#039;&#039;&#039;: this method is called when leaving a game state.&lt;br /&gt;
* &#039;&#039;&#039;onUpdateActionButtons&#039;&#039;&#039;: called on state changes, in order to add action buttons to the status bar. Note: in a multipleactiveplayer state, it will be called when another player has become inactive.&lt;br /&gt;
* &#039;&#039;(utility methods)&#039;&#039;: this is where you can define your utility methods.&lt;br /&gt;
* &#039;&#039;(player&#039;s actions)&#039;&#039;: this is where you can write your handlers for player actions on the interface (example: click on an item).&lt;br /&gt;
* &#039;&#039;&#039;setupNotifications&#039;&#039;&#039;: this method associates notifications with notification handlers. For each game notification, you can trigger a javascript method to handle it and update the game interface.&lt;br /&gt;
* &#039;&#039;(notification handlers)&#039;&#039;: this is where you define the notifications handlers associated with notifications in &#039;&#039;&#039;setupNotifications&#039;&#039;&#039;, above.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
More details:&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;setup(gamedatas: object)            &#039;&#039;&#039;&lt;br /&gt;
This method must set up the game user interface according to current game situation specified in parameters.&lt;br /&gt;
The method is called each time the game interface is displayed to a player, ie:&lt;br /&gt;
&lt;br /&gt;
* when the game starts&lt;br /&gt;
* when a player opens a game in the browser later &lt;br /&gt;
* when a player refreshes the game page (F5)&lt;br /&gt;
* when player does a server side Undo&lt;br /&gt;
&lt;br /&gt;
&amp;quot;gamedatas&amp;quot; argument contains all data retrieved by your &amp;quot;getAllDatas&amp;quot; PHP method and some more.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;onEnteringState(stateName: string, args: { args: any } | null): void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
This method is called each time we enter a new game state.&lt;br /&gt;
You can use this method to perform some user interface changes at this moment.&lt;br /&gt;
To access state arguments passed via calling php arg* method use args?.args.&lt;br /&gt;
Typically you would do something only for active player, using this.isCurrentPlayerActive() check.&lt;br /&gt;
It is also called (for the current game state only) when doing a browser refresh (after the setup method is called).&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Warning&#039;&#039;&#039;: for multipleactiveplayer states:&lt;br /&gt;
the active players are NOT active yet so you must use onUpdateActionButtons to perform the client side operation which depends on a player active/inactive status.&lt;br /&gt;
If you are doing initialization of some structures which do not depend on the active player, you can just replace (this.isCurrentPlayerActive()) with (!this.isSpectator) &lt;br /&gt;
for the main switch in that method.&lt;br /&gt;
&lt;br /&gt;
See more details in [[Your_game_state_machine:_states.inc.php#Difference_between_Single_active_and_Multi_active_states]]&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;onLeavingState(stateName: string): void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
This method is called each time we leave a game state.&lt;br /&gt;
You can use this method to perform some user interface changes at this point (i.e. cleanup).&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;onUpdateActionButtons(stateName: string, args: object | null): void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
In this method you can manage &amp;quot;action buttons&amp;quot; that are displayed in the action status bar and highlight active UI elements.&lt;br /&gt;
To access state arguments passed via calling php arg* method use &#039;&#039;&#039;args&#039;&#039;&#039; parameter. Note: args can be null! For &#039;&#039;&#039;game&#039;&#039;&#039; states and when you don&#039;t supply state args function - it is null.&lt;br /&gt;
This method is called when the active or multiactive player changes. In a classic &amp;quot;activePlayer&amp;quot; state this method is called before the onEnteringState state.&lt;br /&gt;
In multipleactiveplayer state it is a mess. The sequencing of calls depends on whether you get into that state from transitions OR from reloading the whole game (i.e. F5).&lt;br /&gt;
&lt;br /&gt;
See more details in [[Your_game_state_machine:_states.inc.php#Difference_between_Single_active_and_Multi_active_states]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Dojo framework ==&lt;br /&gt;
&lt;br /&gt;
BGA uses the [http://dojotoolkit.org/ Dojo Javascript framework].&lt;br /&gt;
&lt;br /&gt;
The Dojo framework allows us to do complex things more easily. The BGA framework uses Dojo extensively.&lt;br /&gt;
&lt;br /&gt;
To implement a game, you only need to use a few parts of the Dojo framework. All the Dojo methods you need are described on this page.&lt;br /&gt;
&lt;br /&gt;
== Javascript minimization (after July 2020) ==&lt;br /&gt;
&lt;br /&gt;
For performance reasons, when deploying a game the javascript code is minimized using &#039;&#039;&#039;terser&#039;&#039;&#039; (https://github.com/terser/terser). This minifier works with modern javascript syntax. From your project &amp;quot;Manage game&amp;quot; page, you can now test a minified version of your javascript on the studio (and revert to the original).&lt;br /&gt;
&lt;br /&gt;
NB: it has been reported that there is an issue with this minifier and percentage values for opacity.&lt;br /&gt;
&lt;br /&gt;
== Accessing Players Information ==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.player_id: number&#039;&#039;&#039;&lt;br /&gt;
id of the player who is looking at the game. The player may not be part of the game (i.e. spectator)&lt;br /&gt;
  if (notif.args.player_id == this.player_id) {&lt;br /&gt;
    ...&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.isSpectator: boolean&#039;&#039;&#039;&lt;br /&gt;
Flag set to true if the user at the table is a spectator (not a player).&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    if (this.isSpectator) {&lt;br /&gt;
        this.player_color = &#039;ffffff&#039;;&lt;br /&gt;
    } else {&lt;br /&gt;
        this.player_color = gamedatas.players[this.player_id].color;&lt;br /&gt;
    }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note: If you want to hide an element from spectators, you should use [[Game_interface_stylesheet:_yourgamename.css#spectatorMode|CSS &#039;spectatorMode&#039; class]].&lt;br /&gt;
&lt;br /&gt;
You may consider making a function like this, to detect if the game is in a read-only state (i.e. non-interactive):&lt;br /&gt;
  // Returns true for spectators, instant replay (during game), archive mode (after game end)&lt;br /&gt;
  isReadOnly: function () {&lt;br /&gt;
    return this.isSpectator || typeof g_replayFrom != &#039;undefined&#039; || g_archive_mode;&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.gamedatas: object&#039;&#039;&#039;&lt;br /&gt;
Contains the initial set of data to init the game, created at game start or by game refresh (F5).&lt;br /&gt;
You can update it as needed to keep an up-to-date reference of the game on the client side if you need it, however most of the time this is unnecessary.&lt;br /&gt;
&lt;br /&gt;
Note: In hotseat mode, the framework does not keep this.gamedatas of hotseat players and shares the same set as the main player to store data.&lt;br /&gt;
&lt;br /&gt;
Note: be careful when you update this data structurally, many framework functions expect data to be certain way and they will break if they see something else.&lt;br /&gt;
&lt;br /&gt;
Typical example of accessing player&#039;s info&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
for (var player_id in this.gamedatas.players) { &lt;br /&gt;
    var playerInfo = this.gamedatas.players [player_id];&lt;br /&gt;
    var c = playerInfo.color;&lt;br /&gt;
    var name = playerInfo.name;&lt;br /&gt;
    // do something &lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.isCurrentPlayerActive(): boolean&#039;&#039;&#039;&lt;br /&gt;
Returns true if the player on whose browser the code is running is currently active (it&#039;s his turn to play). Note: see remarks above about usage of this function inside onEnteringState method.&lt;br /&gt;
  if (this.isCurrentPlayerActive()) {&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.getActivePlayerId(): number&#039;&#039;&#039;&lt;br /&gt;
Return the ID of the active player, or null if we are not in an &amp;quot;activeplayer&amp;quot; type state.&lt;br /&gt;
  if (this.player_id == this.getActivePlayerId()) ...&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.getActivePlayers(): number[]&#039;&#039;&#039;&lt;br /&gt;
Return an array with the IDs of players who are currently active (or an empty array if there are none).&lt;br /&gt;
&lt;br /&gt;
== Accessing and manipulating the DOM ==&lt;br /&gt;
&lt;br /&gt;
=== Element by Id ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;$(elementId: ElementOrId)&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
The $ function is used to get an HTML element using its &amp;quot;id&amp;quot; attribute.&lt;br /&gt;
&lt;br /&gt;
Example: modify the content of a &amp;quot;span&amp;quot; element:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
In your HTML code:&lt;br /&gt;
   &amp;lt;span id=&amp;quot;a_value_in_the_game_interface&amp;quot;&amp;gt;1234&amp;lt;/span&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In your Javascript code:&lt;br /&gt;
   $(&#039;a_value_in_the_game_interface&#039;).innerHTML = &amp;quot;9999&amp;quot;;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Note: It is safe to use if you don&#039;t know if variable is string (id of element) or element itself, i.e. &lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  foo: function(card) {&lt;br /&gt;
       card = $(card); // now its node, no need to write if (typeof card === &#039;string&#039;) ...&lt;br /&gt;
       // but its good idea to check for null here&lt;br /&gt;
       ...&lt;br /&gt;
  }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;getElementById(elementId: string)&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Note: $() is the standard method to access some HTML element with the BGA Framework. You can use &#039;&#039;&#039;getElementById&#039;&#039;&#039; but a longer to type and less handy as it does not do some checks.&lt;br /&gt;
&lt;br /&gt;
=== Style ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;dojo.style(node: ElementOrId, styleName: string, styleValue: any): void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
With dojo.style you can modify the CSS property of any HTML element in your interface.&lt;br /&gt;
&lt;br /&gt;
Examples:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
     // Make an element disappear&lt;br /&gt;
     dojo.style( &#039;my_element&#039;, &#039;display&#039;, &#039;none&#039; );&lt;br /&gt;
&lt;br /&gt;
     // Give an element a 2px border&lt;br /&gt;
     dojo.style( &#039;my_element&#039;, &#039;borderWidth&#039;, &#039;2px&#039; );&lt;br /&gt;
&lt;br /&gt;
     // Change the background position of an element&lt;br /&gt;
     // (very practical when you are using CSS sprites to transform an element to another)&lt;br /&gt;
     dojo.style( &#039;my_element&#039;, &#039;backgroundPosition&#039;, &#039;-20px -50px&#039; );&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note: if you have to modify several CSS properties of an element, or if you have a complex CSS transformation to do, you should consider using dojo.addClass/dojo.removeClass (see below).&lt;br /&gt;
&lt;br /&gt;
You can also use object to set multiple values&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
dojo.setStyle(&amp;quot;thinger&amp;quot;, {&lt;br /&gt;
  &amp;quot;opacity&amp;quot;: 0.5,&lt;br /&gt;
  &amp;quot;border&amp;quot;: &amp;quot;3px solid black&amp;quot;,&lt;br /&gt;
  &amp;quot;height&amp;quot;: &amp;quot;300px&amp;quot;&lt;br /&gt;
});&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.addStyleToClass(cssClassName: string, styleName: string, styleValue: any):&#039;&#039;&#039; &#039;&#039;&#039;void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Same as dojo.style(), but for all the nodes set with the specified cssClassName&lt;br /&gt;
Equivalent of &lt;br /&gt;
  &lt;br /&gt;
  dojo.query(`.${aclass}`).style(styleName, styleValue)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
dojo.query(&amp;quot;#baz &amp;gt; div&amp;quot;).style({&lt;br /&gt;
  opacity:0.75,&lt;br /&gt;
  fontSize:&amp;quot;13pt&amp;quot;&lt;br /&gt;
});&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Vanilla JS style&#039;&#039;&#039;&lt;br /&gt;
  $(&#039;my_element&#039;).style.display=&#039;none&#039;; // set&lt;br /&gt;
  var display = $(&#039;my_element&#039;).style.display; // get&lt;br /&gt;
  $(&#039;my_element&#039;).style.removeProperty(&#039;display&#039;); // remove&lt;br /&gt;
&lt;br /&gt;
=== Classes ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;dojo.addClass(node: ElementOrId, classes: string): void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;dojo.removeClass(node: ElementOrId, classes: string): void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;dojo.hasClass(node: ElementOrId, aclass: string): void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;dojo.toggleClass(node: ElementOrId, aclass: string): void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
In many situations, many small CSS property updates can be replaced by a CSS class change (i.e., you add a CSS class to your element instead of applying all modifications manually).&lt;br /&gt;
&lt;br /&gt;
Advantages are:&lt;br /&gt;
* All your CSS stuff remains in your CSS file.&lt;br /&gt;
* You can add/remove a list of CSS modifications with a simple function and without error.&lt;br /&gt;
* You can test whether you applied the CSS to an element with the &#039;&#039;&#039;dojo.hasClass&#039;&#039;&#039; method.&lt;br /&gt;
&lt;br /&gt;
Example from &#039;&#039;Reversi&#039;&#039;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    // We add &amp;quot;possibleMove&amp;quot; to an element&lt;br /&gt;
    dojo.addClass( &#039;square_&#039;+x+&#039;_&#039;+y, &#039;possibleMove&#039; );&lt;br /&gt;
&lt;br /&gt;
    // In our CSS file, the class is defined as:&lt;br /&gt;
    .possibleMove {&lt;br /&gt;
      background-color: white;&lt;br /&gt;
      opacity: 0.2;&lt;br /&gt;
      filter:alpha(opacity=20); /* For IE8 and earlier */  &lt;br /&gt;
      cursor: pointer;  &lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
     // So we&#039;ve applied 4 CSS property changes in one line of code.&lt;br /&gt;
&lt;br /&gt;
     // ... and when we need to check if a square is a possible move on the client side:&lt;br /&gt;
     if( dojo.hasClass( &#039;square_&#039;+x+&#039;_&#039;+y, &#039;possibleMove&#039; ) )&lt;br /&gt;
     { ... }&lt;br /&gt;
&lt;br /&gt;
     // ... and if we want to remove all possible moves in one line of code (see &amp;quot;dojo.query&amp;quot; method):&lt;br /&gt;
     dojo.query( &#039;.possibleMove&#039; ).removeClass( &#039;possibleMove&#039; );&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Vanilla JS classList&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
This is the only exception where dojo versions are better&lt;br /&gt;
  // add class&lt;br /&gt;
  $(token_id).classList.addClass(&#039;possibleMove&#039;);&lt;br /&gt;
  // remove class&lt;br /&gt;
  $(token_id).classList.removeClass(&#039;possibleMove&#039;);&lt;br /&gt;
  // add 2 classes&lt;br /&gt;
  const myclasses = [&#039;a&#039;,&#039;b&#039;];&lt;br /&gt;
  $(token_id).classList.addClass(...myclasses);&lt;br /&gt;
  // add classes to query result&lt;br /&gt;
  document.querySelectorAll(&amp;quot;.hand .card&amp;quot;).forEach((node)=&amp;gt;node.classList.addClass(&#039;possibleMove&#039;));&lt;br /&gt;
&lt;br /&gt;
=== Attributes ===&lt;br /&gt;
&lt;br /&gt;
;dojo.attr&lt;br /&gt;
&lt;br /&gt;
With dojo.attr you can access or change the value of an attribute or property of any HTML element in your interface.&lt;br /&gt;
&lt;br /&gt;
Exemple:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
     // Get the title of a node&lt;br /&gt;
     var title = dojo.attr( id, &#039;title&#039; );&lt;br /&gt;
     // Change the height of a node&lt;br /&gt;
     dojo.attr( &#039;img_growing_tree&#039;, &#039;height&#039;, 100 );&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Vanilla JS attr&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
   $(token).id=new_id; // set attr for &amp;quot;id&amp;quot;&lt;br /&gt;
   var id = $(token).id; // get&lt;br /&gt;
&lt;br /&gt;
=== Queries ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;dojo.query(cssSelector: string): Element[]&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
With dojo.query, you can query a bunch of HTML elements with a single function, with a &amp;quot;CSS selector&amp;quot; style.&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
     // All elements with class &amp;quot;possibleMove&amp;quot;:&lt;br /&gt;
     var elements = dojo.query( &#039;.possibleMove&#039; );&lt;br /&gt;
&lt;br /&gt;
     // Count number of tokens (i.e., elements of class &amp;quot;token&amp;quot;) on the board (i.e., the element with id &amp;quot;board&amp;quot;):&lt;br /&gt;
     dojo.query( &#039;#board .token&#039; ).length;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
But what is really cool with dojo.query is that you can combine it with almost all methods above.&lt;br /&gt;
&lt;br /&gt;
Examples:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
     // Trigger a method when the mouse enter in any element with class &amp;quot;meeple&amp;quot;:&lt;br /&gt;
     dojo.query( &#039;.meeple&#039; ).connect( &#039;onmouseenter&#039;, this, &#039;myMethodToTrigger&#039; );&lt;br /&gt;
&lt;br /&gt;
     // Hide all meeples who are on the board&lt;br /&gt;
     dojo.query( &#039;#board .meeple&#039; ).style( &#039;display&#039;, &#039;none&#039; );&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Vanilla JS query&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
  var cards=document.querySelectorAll(&amp;quot;.hand .card&amp;quot;);// all cards in all hands&lt;br /&gt;
  var cards=$(&#039;hand&#039;).querySelectorAll(&amp;quot;.card&amp;quot;);// all cards in specific hand&lt;br /&gt;
  var card=document.querySelector(&amp;quot;.hand .card&amp;quot;);// first card or null if none (super handy)&lt;br /&gt;
&lt;br /&gt;
=== Creating and Destroying elements ===&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;dojo.empty(node: ElementOrId)&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Remove all children of the node element&lt;br /&gt;
   dojo.empty(&#039;my_hand&#039;);&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;dojo.destroy(node: ElementOrId)&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Remove the element&lt;br /&gt;
   dojo.destroy(&#039;my_token&#039;);&lt;br /&gt;
&lt;br /&gt;
   dojo.query(&amp;quot;.green&amp;quot;, mynode).forEach(dojo.destroy); // this remove all subnode of class green from mynode&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;dojo.create(tag: string, attributes?: obj, parent?: ElementOrId): Element&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Create element&lt;br /&gt;
&lt;br /&gt;
    dojo.create(&amp;quot;div&amp;quot;, { class: &amp;quot;yellow_arrow&amp;quot; }, parent); // this creates div with class yellow_array and places it in &amp;quot;parent&amp;quot;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.format_block(name: string, args: object): string&#039;&#039;&#039;&lt;br /&gt;
This bga function that takes global var from template file and substitute variables, typical use would be&lt;br /&gt;
&lt;br /&gt;
                var player = gamedatas.players[player_id];&lt;br /&gt;
                var div = this.format_block(&#039;jstpl_player_board&#039;, player ); // var jstpl_player_board = ... is defined in .tpl file &lt;br /&gt;
Note: result is trimmed&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.format_string(name: string, args: object): string&#039;&#039;&#039;&lt;br /&gt;
This bga function just substitute variables in a string, i.e.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
     var div = this.format_string(&#039;&amp;lt;div color=&amp;quot;${player_color}&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&#039;, {player_color: &#039;#ff0000&#039;} );&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Note: result is trimmed&lt;br /&gt;
&lt;br /&gt;
Note: this can be replaced by using backquoted string now: &lt;br /&gt;
     const player_color =  &#039;#ff0000&#039;;&lt;br /&gt;
     const div = `&amp;lt;div color=&amp;quot;${player_color}&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;`;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.format_string_recursive&#039;&#039;&#039;&lt;br /&gt;
This bga function is similar to this.format_string but is capable of processing recursive argument structures and translations. It is used to format server notifications.&lt;br /&gt;
&lt;br /&gt;
TODO: find better place for these function docs&lt;br /&gt;
&lt;br /&gt;
=== Moving elements ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;dojo.place(node: string | Element, refNode: ElementOrId, pos?: string | number): Element&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
dojo.place is the best function to insert HTML code somewhere in your game interface without breaking something. It is much better to use than the &#039;&#039;&#039;innerHTML=&#039;&#039;&#039; method if you must insert HTML tags and not only values.&lt;br /&gt;
&lt;br /&gt;
node: &lt;br /&gt;
&lt;br /&gt;
Can be a String or a DOM node. If it is a string starting with “&amp;lt;”, it is assumed to be an HTML fragment, which will be created. Otherwise it is assumed to be an id of a DOM node.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
     // Insert your HTML code as a child of a container element&lt;br /&gt;
     dojo.place( &amp;quot;&amp;lt;div class=&#039;foo&#039;&amp;gt;&amp;lt;/div&amp;gt;&amp;quot;, &amp;quot;your_container_element_id&amp;quot; );&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
pos:&lt;br /&gt;
&lt;br /&gt;
Optional argument. Can be a number or one of the following strings: “before”, “after”, “replace”, “only”, “first”, or “last”. If omitted, “last” is assumed. &lt;br /&gt;
&lt;br /&gt;
&amp;quot;replace&amp;quot;: Replace the container element with my_node element&lt;br /&gt;
&lt;br /&gt;
&amp;quot;first&amp;quot;: Places the node as a child of the reference node. The node is placed as the first child.&lt;br /&gt;
&lt;br /&gt;
&amp;quot;last&amp;quot; (default): Places the node as a child of the reference node. The node is placed as the last child.&lt;br /&gt;
&lt;br /&gt;
&amp;quot;before&amp;quot;: places the node right before the reference node.&lt;br /&gt;
&lt;br /&gt;
&amp;quot;after&amp;quot;: places the node right after the reference node.&lt;br /&gt;
&lt;br /&gt;
&amp;quot;only&amp;quot;: replaces all children of the reference node with the node.&lt;br /&gt;
&lt;br /&gt;
positive integer: This parameter can be a positive integer. In this case, the node will be placed as a child of the reference node with this number (counting from 0). If the number is more than number of children, the node will be appended to the reference node making it the last child. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
     // Replace all children of container with my_node &lt;br /&gt;
     dojo.place( $(&#039;my_node&#039;), &amp;quot;your_container_element_id&amp;quot;, &amp;quot;only&amp;quot; );&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
See also full doc on dojo.place: [https://dojotoolkit.org/reference-guide/1.7/dojo/place.html]&lt;br /&gt;
&lt;br /&gt;
Usually, when you want to insert some piece of HTML in your game interface, you should use &amp;quot;[[Game_layout:_view_and_template:_yourgamename.view.php_and_yourgamename_yourgamename.tpl#Javascript_templates|Javascript templates]]&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
But you can also relocate elements like that. Note: it won&#039;t animate if you do that.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.placeOnObject(mobile_obj: ElementOrId, target_obj: ElementOrId): void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
places mobile_obj on target_obj, set the absolute positions and centers the mobile_obj on target_obj,&lt;br /&gt;
effect is immediate&lt;br /&gt;
&lt;br /&gt;
This is not really an animation, but placeOnObject is frequently used before starting an animation.&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  // (We just created an object &amp;quot;my_new_token&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
  // Place the new token on current player board&lt;br /&gt;
  this.placeOnObject( &amp;quot;my_new_token&amp;quot;, &amp;quot;overall_player_board_&amp;quot;+this.player_id );&lt;br /&gt;
  &lt;br /&gt;
  // Then slide it to its position on the board&lt;br /&gt;
  this.slideToObject( &amp;quot;my_new_token&amp;quot;, &amp;quot;a_place_on_board&amp;quot; ).play();&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.placeOnObjectPos(mobile_obj: ElementOrId, target_obj: ElementOrId, target_x: number, target_y: number): void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
This method works exactly like placeOnObject, except than you can specify some (x,y) coordinates (in px). This way, the center of &amp;quot;mobile_obj&amp;quot; will be placed to the specified x,y position relatively to the center of &amp;quot;target_obj&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Note: the placement works differently from this.slideToObjectPos&#039;&#039;, since coordinates are calculated based on the center of objects.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.attachToNewParent(mobile_obj: ElementOrId, target_obj: ElementOrId): void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
With this method, you change the HTML parent of &amp;quot;mobile_obj&amp;quot; element without moving it. &lt;br /&gt;
&amp;quot;target_obj&amp;quot; is the new parent of this element. The beauty of &lt;br /&gt;
attachToNewParent is that the mobile_obj element DOES NOT MOVE during this process.&lt;br /&gt;
&lt;br /&gt;
What happens is that the method calculate a relative position of mobile_obj to make sure it does not move after the HTML parent changes.&lt;br /&gt;
&lt;br /&gt;
Why using this method?&lt;br /&gt;
&lt;br /&gt;
Changing the HTML parent of an element can be useful for the following reasons:&lt;br /&gt;
* When the HTML parent moves, all its child are moving with them. If some game elements is no more linked with a parent HTML object, you may want to attach it to another place.&lt;br /&gt;
* The z_order (vertical order of display) depends on the position in the DOM, so you may need to change the parent of some game elements when they are moving in your game area.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;CAREFUL&#039;&#039;&#039;: this function destroys original object and places a clone onto a new parent, this will break all references to this HTML element (ex: dojo.connect).&lt;br /&gt;
If you need version that does not destroy the object but the same otherwise see [[BGA_Studio_Cookbook#Attach_to_new_parent_without_destroying_the_object]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Animations ==&lt;br /&gt;
&lt;br /&gt;
===Dojo Animations===&lt;br /&gt;
&lt;br /&gt;
BGA animations is based on Dojo Animation ([http://dojotoolkit.org/documentation/tutorials/1.8/animation/ see tutorial here]).&lt;br /&gt;
&lt;br /&gt;
However, most of the time, you can just use methods below, which are built on top of Dojo Animation.&lt;br /&gt;
&lt;br /&gt;
Note: one interesting method from Dojo that could be useful from time to time is &amp;quot;Dojo.Animation&amp;quot;. It allows you to make any CSS property &amp;quot;slide&amp;quot; from one value to another.&lt;br /&gt;
&lt;br /&gt;
Note 2: the slideTo methods are not compatible with CSS transform (scale, zoom, rotate...). If possible, avoid using CSS transform on nodes that are being slided. Eventually, the only possible solution to make these 2 compatible is to disable all CSS transform properties, use slideToObjectPos/placeOnObjectPos, and then apply them again.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Sliding===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.slideToObject(mobile_obj: ElementOrId, target_obj: ElementOrId, duration?: number, delay?: number): Animation&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
You can use slideToObject to &amp;quot;slide&amp;quot; an element to a target position.&lt;br /&gt;
&lt;br /&gt;
Sliding element on the game area is the recommended and the most used way to animate your game interface. Using slides allow players to figure out what is happening on the game, as if they were playing with the real boardgame.&lt;br /&gt;
&lt;br /&gt;
The parameters are:&lt;br /&gt;
* mobile_obj: the ID of the object to move. This object must be &amp;quot;relative&amp;quot; or &amp;quot;absolute&amp;quot; positioned.&lt;br /&gt;
* target_obj: the ID of the target object. This object must be &amp;quot;relative&amp;quot; or &amp;quot;absolute&amp;quot; positioned. Note that it is not mandatory that mobile_obj and target_obj have the same size. If their size are different, the system slides the center of mobile_obj to the center of target_obj.&lt;br /&gt;
* duration: (optional) defines the duration in millisecond of the slide. The default is 500 milliseconds.&lt;br /&gt;
* delay: (optional). If you defines a delay, the slide will start only after this delay. This is particularly useful when you want to slide several object from the same position to the same position: you can give a 0ms delay to the first object, a 100ms delay to the second one, a 200ms delay to the third one, ... this way they won&#039;t be superposed during the slide.&lt;br /&gt;
&lt;br /&gt;
BE CAREFUL: The method returns an dojo.fx animation, so you can combine it with other animation if you want to. It means that you have to call the &amp;quot;play()&amp;quot; method, otherwise the animation WON&#039;T START.&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
   this.slideToObject( &amp;quot;some_token&amp;quot;, &amp;quot;some_place_on_board&amp;quot; ).play();&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.slideToObjectPos(mobile_obj: ElementOrId, target_obj: ElementOrId, target_x: number, target_y: number, duration?: number, delay?: number): Animation&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
This method does exactly the same as &amp;quot;slideToObject&amp;quot;, except than you can specify some (x,y) coordinates. This way, &amp;quot;mobile_obj&amp;quot; will slide to the specified x,y position relatively to &amp;quot;target_obj&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
Example: slide a token to some place on the board, 10 pixels from the top:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
   this.slideToObjectPos( &amp;quot;some_token&amp;quot;, &amp;quot;some_place_on_board&amp;quot;, 0, 10 ).play();&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.slideTemporaryObject(mobile_obj_html: string, parent: ElementOrId, from: ElementOrId, to: ElementOrId, duration?: number, delay?: number): Animation&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
This method is useful when you want to slide a temporary HTML object from one place to another. As this object does not exists before the animation and won&#039;t remain after, it could be complex to create this object (with dojo.place), to place it at its origin (with placeOnObject) to slide it (with slideToObject) and to make it disappear at the end.&lt;br /&gt;
&lt;br /&gt;
slideTemporaryObject does all of this for you:&lt;br /&gt;
* mobile_obj_html is a piece of HTML code that represent the object to slide.&lt;br /&gt;
* parent is the ID of an HTML element of your interface that will be the parent of this temporary HTML object.&lt;br /&gt;
* from is the ID of the origin of the slide.&lt;br /&gt;
* to is the ID of the target of the slide.&lt;br /&gt;
* duration/delay works exactly like in &amp;quot;slideToObject&amp;quot;&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
this.slideTemporaryObject( &#039;&amp;lt;div class=&amp;quot;token_icon&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&#039;, &#039;tokens&#039;, &#039;my_origin_div&#039;, &#039;my_target_div&#039; ).play();&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Destroy===&lt;br /&gt;
&#039;&#039;&#039;this.slideToObjectAndDestroy(mobile_obj: ElementOrId, target_obj: ElementOrId, duration?: number, delay?: number): void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
This method is a handy shortcut to slide an existing HTML object to some place then destroy it upon arrival. It can be used for example to move a victory token or a card from the board to the player panel to show that the player earns it, then destroy it when we don&#039;t need to keep it visible on the player panel.&lt;br /&gt;
&lt;br /&gt;
It works the same as this.slideToObject and takes the same arguments, but it starts the animation. &lt;br /&gt;
&lt;br /&gt;
CAREFUL: Make sure nothing is creating the same object at the same time the animation is running, because this will cause some random disappearing effects&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
this.slideToObjectAndDestroy( &amp;quot;some_token&amp;quot;, &amp;quot;some_place_on_board&amp;quot;, 1000, 0 );&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.fadeOutAndDestroy( node: string | Element, duration?: number, delay?: number):&#039;&#039;&#039; &#039;&#039;&#039;void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
This function fade out the target node, then destroy it. Its starts the animation.&lt;br /&gt;
* duration/delay works exactly like in &amp;quot;slideToObject&amp;quot;&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
   this.fadeOutAndDestroy( &amp;quot;a_card_that_must_disappear&amp;quot; );&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
CAREFUL: the HTML node still exists until during few milliseconds, until the fadeOut has been completed.&lt;br /&gt;
Make sure nothing is creating same object at the same time as animation is running, because you will be some random dissapearing effects&lt;br /&gt;
&lt;br /&gt;
===Rotating elements===&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
This example combines &amp;quot;Dojo.Animation&amp;quot; method and a CSS property transform that allow you to rotate the element.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
// node is Element we rotating&lt;br /&gt;
		    var animation = new dojo.Animation({&lt;br /&gt;
			    curve: [fromDegree, toDegree],&lt;br /&gt;
			    onAnimate: (v) =&amp;gt; {&lt;br /&gt;
				    node.style.transform = &#039;rotate(&#039; + v + &#039;deg)&#039;;&lt;br /&gt;
			    } &lt;br /&gt;
		    });&lt;br /&gt;
		    &lt;br /&gt;
		    animation.play();  &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
BGA has its own interface to rotate&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.rotateTo(node: string | Element, degree: number): void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
It starts the animation, and stored the rotation degree in the class, so next time you rotate object - it is additive.&lt;br /&gt;
There is no animation hooks in this one, if you need to change any parameters use dojo animation above.&lt;br /&gt;
&lt;br /&gt;
There is also &#039;&#039;&#039;rotateInstantTo&#039;&#039;&#039; with same signature which does not animate&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Animation Callbacks===&lt;br /&gt;
&lt;br /&gt;
If you wish to run some code only after an animation has completed you can do this by linking a callback method to &#039;onEnd&#039;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
var animation_id = this.slideToObject( mobile_obj, target_obj, 500 );&lt;br /&gt;
dojo.connect(animation_id, &#039;onEnd&#039;, () =&amp;gt; {&lt;br /&gt;
   // do something here&lt;br /&gt;
});&lt;br /&gt;
animation_id.play();&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If you wish to call a second animation after the first (rather than general code) then you can use a dojo animation chain (see tutorial referenced above).&lt;br /&gt;
&lt;br /&gt;
== Players input ==&lt;br /&gt;
&lt;br /&gt;
=== Connecting ===&lt;br /&gt;
&#039;&#039;&#039;dojo.connect(element: Element, event: string, context: object, method: eventHandler): any&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;dojo.connect(element: Element, event: string, hander: eventHandler): any&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Used to associate a player event with one of your notification methods.&lt;br /&gt;
&lt;br /&gt;
Example: associate a click on an element (&amp;quot;my_element&amp;quot;) with one of our methods (&amp;quot;onClickOnMyElement&amp;quot;):&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
      dojo.connect( $(&#039;my_element&#039;), &#039;onclick&#039;, this, &#039;onClickOnMyElement&#039; );&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Same idea but base on query (i.e. all element of &#039;pet&#039; class)&lt;br /&gt;
      dojo.query(&amp;quot;.pet&amp;quot;).connect(&#039;onclick&#039;, this, &#039;onPet&#039;);&lt;br /&gt;
&lt;br /&gt;
Note: if you need to disconnect the handler you have to store handler returned from this method, i.e.&lt;br /&gt;
   &lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    var handler = dojo.connect(...);&lt;br /&gt;
    ...&lt;br /&gt;
    dojo.disconnect(handler);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If you don&#039;t store the handler - you have to destroy the object to disconnect it&lt;br /&gt;
&lt;br /&gt;
Typical function that implements the input handler will look like this&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
onPet: function(event) {&lt;br /&gt;
    var id = event.currentTarget.id;&lt;br /&gt;
    console.log(&#039;onPet &#039; + id);&lt;br /&gt;
    dojo.stopEvent(event);&lt;br /&gt;
    if (this.gamedatas.gamestate.name == &#039;playerTurnPet&#039;) {&lt;br /&gt;
          this.bgaPerformAction(&#039;actPlayPet&#039;, {card: id});&lt;br /&gt;
    } else {&lt;br /&gt;
          this.showMoveUnauthorized();&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.connect(element: ElementOrId, event: string, method: eventHandler): void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Used to associate a player event with one of your notification methods.&lt;br /&gt;
&lt;br /&gt;
      this.connect( $(&#039;my_element&#039;), &#039;onclick&#039;, &#039;onClickOnMyElement&#039; );&lt;br /&gt;
&lt;br /&gt;
Or you can use an in-place handler&lt;br /&gt;
&lt;br /&gt;
      this.connect( $(&#039;my_element&#039;), &#039;onclick&#039;, (e) =&amp;gt; { console.log(&#039;boo&#039;); } );&lt;br /&gt;
&lt;br /&gt;
Note that this function stores the connection handler. That is the only real difference between &#039;&#039;&#039;this.connect&#039;&#039;&#039; and &#039;&#039;&#039;dojo.connect&#039;&#039;&#039;. If you plan to destroy the element you connected, you &#039;&#039;&#039;must&#039;&#039;&#039; call this.disconnect() to prevent memory leaks.&lt;br /&gt;
This function is mainly for permanent objects - if you just want to connect the temp object you should probably not use this method but use dojo.connect which won&#039;t require any clean-up.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.connectClass(cssClassName: string, event: string, method: eventHandler): void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Same as connect(), but for all the nodes set with the specified cssClassName.&lt;br /&gt;
&lt;br /&gt;
	this.connectClass(&#039;pet&#039;, &#039;onclick&#039;, &#039;onPet&#039;);&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.disconnect(element: ElementOrId, event: string): void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Disconnect event handler (previously registered with this.connect or this.connectClass).&lt;br /&gt;
&lt;br /&gt;
   this.disconnect( $(&#039;my_element&#039;), &#039;onclick&#039;);&lt;br /&gt;
&lt;br /&gt;
Note: dynamic connect/disconnect is for advanced cases ONLY, you should always connect elements statically if possible, i.e. in setup() method.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.disconnectAll(): void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Disconnect all previously registed event handlers (registered via this.connect or this.connectClass)&lt;br /&gt;
&lt;br /&gt;
  this.disconnectAll();&lt;br /&gt;
&lt;br /&gt;
=== Actions ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.bgaPerformAction(action: string, args?: object, options: object = { lock: true, checkAction: true }): Promise&amp;lt;void&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Triggers an action on the backend. This is a combination of checkAction and ajaxcall, returning a Promise which resoves when ajaxcall ends.&lt;br /&gt;
&lt;br /&gt;
This method must be used to send a player input to the game server. &#039;&#039;&#039;It should not be triggered programmatically&#039;&#039;&#039;, especially not in loops, in callbacks, in notifications, or in onEnteringState/onUpdateActionButtons/onLeavingState, in order not to create race conditions or break replay game and tutorial features. It should be used only in reaction to a user action in the interface.&lt;br /&gt;
&lt;br /&gt;
* action: name of the action, as it is written in &amp;quot;possibleactions&amp;quot; of the current state.&lt;br /&gt;
* args: an object containing the call parameters to send to the action&lt;br /&gt;
* options: options to tweak the call with some defaults. Default is &amp;lt;code&amp;gt;{ lock: true, checkAction: true }&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Example of a standard call without args:&lt;br /&gt;
  this.bgaPerformAction(&#039;pass&#039;);&lt;br /&gt;
&lt;br /&gt;
Example of a standard call with action args:&lt;br /&gt;
  this.bgaPerformAction(&#039;actPlayCard&#039;, { id: this.selectedCardId });&lt;br /&gt;
&lt;br /&gt;
Example of a call without checking action (because player is inactive in a multiactive state):&lt;br /&gt;
&lt;br /&gt;
 this.bgaPerformAction(&#039;actChangeMind&#039;, {}, { checkAction: false });&lt;br /&gt;
&lt;br /&gt;
Example of a call without lock (because of a special action not directly related to the game flow):&lt;br /&gt;
&lt;br /&gt;
 this.bgaPerformAction(&#039;actSetAutoBid&#039;, { alwaysBidUntil: 500 }, { lock: false, checkAction: false });&lt;br /&gt;
&lt;br /&gt;
Example of call with reaction to exception:&lt;br /&gt;
  this.bgaPerformAction(&#039;actPlayCard&#039;, { id: this.selectedCardId }).catch(()=&amp;gt;{ this.selectedCardId = undefined; });&lt;br /&gt;
&lt;br /&gt;
Example of call with reaction to success:&lt;br /&gt;
  this.bgaPerformAction(&#039;actPlayCard&#039;, { id: this.selectedCardId }).then(()=&amp;gt;{ this.unselectAll(); });&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.ajaxcall(url, parameters, obj_callback, callback, callback_anycase?, ajax_method?: string)&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Note: bgaPerformAction is a simpler way to use ajax calls, ajaxcall stays in the doc for legacy reasons only and should not be used in new projects.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Same warning as &#039;&#039;&#039;this.bgaPerformAction&#039;&#039;&#039; about using on user action only.&lt;br /&gt;
&lt;br /&gt;
* url: the url of the action to perform. For a game, it must be: &amp;quot;/&amp;lt;mygame&amp;gt;/&amp;lt;mygame&amp;gt;/myAction.html&amp;quot;&lt;br /&gt;
* parameters: an array of parameter to send to the game server. &lt;br /&gt;
** Note that &amp;quot;lock: true&amp;quot; must always be specified in this list of parameters in order the interface can be locked during the server call. Cannot use lock: false - to not lock it has to be undefined.&lt;br /&gt;
** Note: Restricted parameter names (please don&#039;t use them):&lt;br /&gt;
*** &amp;quot;action&amp;quot;&lt;br /&gt;
*** &amp;quot;module&amp;quot;&lt;br /&gt;
*** &amp;quot;class&amp;quot;&lt;br /&gt;
* obj_callback: must be set to &amp;quot;this&amp;quot;.&lt;br /&gt;
* callback (non-optional but rarely used): a function to trigger when the server returns result and everything went fine (not used, as all data handling is done via notifications).&lt;br /&gt;
* callback_anycase: (optional) a function to trigger when the server returns ok OR error.  If no error this function is called with parameter value false. If an error occurred, the first parameter will be set to true, the second will contain the error message sent by the PHP back-end, and the third will contain an error code.&lt;br /&gt;
* ajax_method: (optional and rarely used) if you need to send large amounts of data (over 2048 bytes), you can set this parameter to &#039;post&#039; (all lower-case) to send a POST request as opposed to the default GET. This works, but was not officially documented, so only use if you really need to.&lt;br /&gt;
&lt;br /&gt;
Usage:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
this.ajaxcall( &#039;/mygame/mygame/actMyAction.html&#039;, { lock: true, &lt;br /&gt;
   arg1: myarg1, &lt;br /&gt;
   arg2: myarg2&lt;br /&gt;
}, this, (result)=&amp;gt;{} );&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.checkAction(action: string, nomessage?: boolean): boolean &#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Check if player can do the specified action by taking into account:&lt;br /&gt;
* if interface is locked it will return false and show message &amp;quot;An action is already in progress&amp;quot;,  unless nomessage set to true &lt;br /&gt;
* if player is not active it will return false and show message &amp;quot;This is not your turn&amp;quot;, unless nomessage set to true &lt;br /&gt;
* if action is not in list in possible actions (defined by &amp;quot;possibleaction&amp;quot; in current game state) it will return false and show &amp;quot;This move is not authorized now&amp;quot; error (unconditionally).&lt;br /&gt;
* otherwise returns true&lt;br /&gt;
Example:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  function onClickOnGameElement( evt )  {&lt;br /&gt;
     if( this.checkAction( &amp;quot;actMyAction&amp;quot; ) ) {&lt;br /&gt;
        // Do the action&lt;br /&gt;
     }&lt;br /&gt;
  }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.checkPossibleActions(action: string): boolean&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
* this is independent of the player being active, so can be used instead of this.checkAction(). This is particularly useful for multiplayer states when the player is not active in a &#039;player may like to change their mind&#039; scenario. Unlike this.checkAction, this function does NOT take interface locking into account &lt;br /&gt;
&lt;br /&gt;
* if action is not in list in possible actions (defined by &amp;quot;possibleaction&amp;quot; in current game state) it will return false and show &amp;quot;This move is not authorized now&amp;quot; error (unconditionally).&lt;br /&gt;
* otherwise returns true&lt;br /&gt;
&lt;br /&gt;
  function onChangeMyMind( evt )  {&lt;br /&gt;
     if( this.checkPossibleActions( &amp;quot;actMyAction&amp;quot; ) ) {&lt;br /&gt;
        // Do the action&lt;br /&gt;
     }&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.checkLock(nomessage?: boolean): boolean&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
When using &amp;quot;lock: true&amp;quot; in ajax call you can use this function to check if interface is in lock state (it will be locked during server call and notification processing).&lt;br /&gt;
This check can be used to block some other interactions which do not result in ajaxcall or if you want to suppress errors. Note: normally you only need to use this.checkAction(...), this is for advanced cases.&lt;br /&gt;
&lt;br /&gt;
It will also show error unless nomessage is set to true&lt;br /&gt;
&lt;br /&gt;
  function onChangeMyMind( evt )  {&lt;br /&gt;
     if( this.checkLock() ) {&lt;br /&gt;
        // Do the action&lt;br /&gt;
     }&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
== Notifications ==&lt;br /&gt;
&lt;br /&gt;
When something happens on the server side, your game interface Javascript logic received a notification.&lt;br /&gt;
If you have not done so yet check what notification are in [[Main_game_logic:_yourgamename.game.php#Notifications]]&lt;br /&gt;
&lt;br /&gt;
Here&#039;s how you can handle these notifications on the client side.&lt;br /&gt;
&lt;br /&gt;
=== Subscribe to notifications ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;dojo.subscribe(notif_type: string, callback_obj: Object, handler: string|handler)&#039;&#039;&#039;&lt;br /&gt;
* notif_type - notification type/name send by php server&lt;br /&gt;
* callback_obj - usually this&lt;br /&gt;
* handler - if string method of callback_obj with name name is called, when notification is called, with notification object as parameter (see below)&lt;br /&gt;
&lt;br /&gt;
Your Javascript &amp;quot;setupNotifications&amp;quot; method is the place where you can subscribe to notifications from your PHP code.&lt;br /&gt;
&lt;br /&gt;
Here&#039;s how you associate one of your Javascript method to a notification &amp;quot;playDisc&amp;quot; (from Reversi example):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
   setupNotifications: function() {&lt;br /&gt;
      ...&lt;br /&gt;
      dojo.subscribe(&#039;playDisc&#039;, this, &amp;quot;notif_playDisc&amp;quot;);&lt;br /&gt;
   },&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note: the &amp;quot;playDisc&amp;quot; corresponds to the name of the notification you define it in your PHP code, in your &amp;quot;notifyAllPlayers&amp;quot; or &amp;quot;notifyPlayer&amp;quot; method.&lt;br /&gt;
&lt;br /&gt;
Then, you have to define your &amp;quot;notif_playDisc&amp;quot; method:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
   notif_playDisc: function(notif) {&lt;br /&gt;
     // Remove current possible moves (makes the board more clear)&lt;br /&gt;
     dojo.query( &#039;.possibleMove&#039; ).removeClass( &#039;possibleMove&#039; );          &lt;br /&gt;
     this.addDiscOnBoard( notif.args.x, notif.args.y, notif.args.player_id );&lt;br /&gt;
   },&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In a notification handler like our &amp;quot;notif_playDisc&amp;quot; method, you can access all notifications arguments with &amp;quot;notif.args&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&lt;br /&gt;
PHP&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    $this-&amp;gt;notifyAllPlayers( &amp;quot;apples&amp;quot;, clienttranslate(&#039;player takes ${count} apples&#039;), [ &amp;quot;count&amp;quot; =&amp;gt; 3 ] );&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
JavaScript&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    setupNotifications: function() {&lt;br /&gt;
       dojo.subscribe( &#039;apples&#039;, this, &#039;notif_apples&#039; );&lt;br /&gt;
    },&lt;br /&gt;
&lt;br /&gt;
    notif_apples: function(notif) {&lt;br /&gt;
      //You can access the &amp;quot;count&amp;quot; like this:&lt;br /&gt;
       alert(&amp;quot;count = &amp;quot; + notif.args.count);&lt;br /&gt;
    }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== The notification Object received by client ===&lt;br /&gt;
&lt;br /&gt;
When sending a notification on your PHP, the client side will receive an Object with the following attributes:&lt;br /&gt;
&lt;br /&gt;
* type - type of the notification (as passed by php function)&lt;br /&gt;
* log - the log string passed from php notification&lt;br /&gt;
* args - This is the arguments that you passed on your notification method on php&lt;br /&gt;
* bIsTableMsg - is true when you use [[Main_game_logic:_yourgamename.game.php#NotifyAllPlayers|NotifyAllPlayers]] method (false otherwise)&lt;br /&gt;
* channelorig - information about table ID (formatted as : &amp;quot;/table/t[TABLE_NUMBER]&amp;quot;)&lt;br /&gt;
* gamenameorig - name of the game&lt;br /&gt;
* move_id - ID of the move associated with the notification&lt;br /&gt;
* table_id - ID of the table (comes as string)&lt;br /&gt;
* time - UNIX GMT timestamp&lt;br /&gt;
* uid - unique identifier of the notification&lt;br /&gt;
* h - unknown&lt;br /&gt;
&lt;br /&gt;
&#039;&#039; Note that those information were inferred from observation on console log. If an Admin can confirm/correct (and remove this line), you&#039;re welcome :)&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
=== Ignoring notifications ===&lt;br /&gt;
&lt;br /&gt;
Sometimes you need to ignore some notification on client side. You don&#039;t want them to be shown in game log and you don&#039;t want them to be handled.&lt;br /&gt;
&lt;br /&gt;
The most common use case is when a player gets private information. They will receive a specific notification (such as &amp;quot;You received Ace of Heart&amp;quot;), while other players would receive more generic notification (&amp;quot;Player received a card&amp;quot;).&lt;br /&gt;
&lt;br /&gt;
In X.game.php&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        $this-&amp;gt;notifyAllPlayers(&amp;quot;dealCard&amp;quot;, clienttranslate(&#039;${player_name} received a card&#039;), [&lt;br /&gt;
            &#039;player_id&#039; =&amp;gt; $playerId,&lt;br /&gt;
            &#039;player_name&#039; =&amp;gt; $this-&amp;gt;getActivePlayerName()&lt;br /&gt;
        ]);&lt;br /&gt;
&lt;br /&gt;
        $this-&amp;gt;notifyPlayer($playerId, &amp;quot;dealCardPrivate&amp;quot;, clienttranslate(&#039;You received ${cardName}&#039;), [&lt;br /&gt;
            &amp;quot;type&amp;quot; =&amp;gt; $card[&amp;quot;type&amp;quot;],&lt;br /&gt;
            &amp;quot;cardName&amp;quot; =&amp;gt; $this-&amp;gt;getCardName($card[&amp;quot;type&amp;quot;])&lt;br /&gt;
        ]);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The problem with this approach is that the active player will receive two notifications:&lt;br /&gt;
* Player1 received a card&lt;br /&gt;
* You received Ace of Hearts&lt;br /&gt;
&lt;br /&gt;
Hence, notification ignoring.&lt;br /&gt;
&lt;br /&gt;
NOTE: You can think that it would be possible to send such notification to all players except active just by using notifyPlayer and it seems to work. The problem however is that table spectators would miss such notification and their user interface (and game log) wouldn&#039;t be updated. Since there is no way to send notification just to spectators, ignoring the notification (or &amp;quot;filtering&amp;quot;) is the only reasonable solution.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;setIgnoreNotificationCheck(notif_type: string, predicate: ((notif: Notif)=&amp;gt;boolean))&#039;&#039;&#039;&lt;br /&gt;
This method will set a check whether any of notifications of specific type should be ignored.&lt;br /&gt;
&lt;br /&gt;
The parameters are:&lt;br /&gt;
* notif_type: type of the notification &lt;br /&gt;
* predicate (notif =&amp;gt; boolean): a function that will receive notif object and will return true if this specific notification should be ignored&lt;br /&gt;
&lt;br /&gt;
Before dispatching any notification of this type, the framework will call predicate to check whether notification should be ignored, if it return true - the notification will be dispatched, i.e. logged or handled.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    this.notifqueue.setIgnoreNotificationCheck( &#039;dealCard&#039;, (notif) =&amp;gt; (notif.args.player_id == this.player_id) );&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
IMPORTANT: Remember that this notification is ignored on the client side, but was still received by the client. Therefore it shouldn&#039;t contain any private information as cheaters can get it. In other words this is not a way to hide information.&lt;br /&gt;
&lt;br /&gt;
IMPORTANT: When a game is reloaded with F5 or when opening a turn based game, old notifications are replayed as history notification. They are used just to update the game log and are stripped of all arguments except player_id, i18n and any argument present in message. If you use and other argument in your predicate you should &#039;&#039;&#039;preserve&#039;&#039;&#039; it as explained [[Main_game_logic:_yourgamename.game.php#Notify_players|here]].&lt;br /&gt;
&lt;br /&gt;
=== Synchronous notifications ===&lt;br /&gt;
&lt;br /&gt;
When several notifications are received by your game interface, these notifications are processed immediately, one after the other, in the same exact order they have been generated in your PHP game logic.&lt;br /&gt;
&lt;br /&gt;
However, sometimes, you need to give some time to the players to figure out what happened on the game before jumping to the next notification. Indeed, in many games, there are a lot of automatic actions, and the computer is going to resolve all these actions very fast if you don&#039;t tell it not to do so.&lt;br /&gt;
&lt;br /&gt;
As an example, for Reversi, when someone is playing a disc, we want to wait 500 milliseconds before doing anything else in order the opponent player can figure out what move has been played.&lt;br /&gt;
&lt;br /&gt;
Here&#039;s how we do this, right after our subscription:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    dojo.subscribe( &#039;playDisc&#039;, this, &amp;quot;notif_playDisc&amp;quot; );&lt;br /&gt;
    this.notifqueue.setSynchronous( &#039;playDisc&#039;, 500 );   // Wait 500 milliseconds after executing the playDisc handler&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
-----&lt;br /&gt;
&lt;br /&gt;
It is also possible to control the delay timing dynamically (e.g., using notification args). As an example, maybe your notification &#039;cardPlayed&#039; should pause for a different amount of time depending on the number or type of cards played.&lt;br /&gt;
&lt;br /&gt;
For this case, use &#039;&#039;&#039;setSynchronous&#039;&#039;&#039; without specifying the duration and use &#039;&#039;&#039;setSynchronousDuration&#039;&#039;&#039; within the notification callback.&lt;br /&gt;
&lt;br /&gt;
* NOTE: If you forget to invoke &#039;&#039;&#039;setSynchronousDuration&#039;&#039;&#039;, the game will remain paused forever!&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
setupNotifications: function () {&lt;br /&gt;
    dojo.subscribe( &#039;cardPlayed&#039;, this, &#039;notif_cardPlayed&#039; );&lt;br /&gt;
    this.notifqueue.setSynchronous( &#039;cardPlayed&#039; ); // wait time is dynamic&lt;br /&gt;
    ...&lt;br /&gt;
},&lt;br /&gt;
&lt;br /&gt;
notif_cardPlayed: function (notif) {&lt;br /&gt;
    // MUST call setSynchronousDuration&lt;br /&gt;
&lt;br /&gt;
    // Example 1: From notification args (PHP)&lt;br /&gt;
    this.notifqueue.setSynchronousDuration(notif.args.duration);&lt;br /&gt;
    ...&lt;br /&gt;
&lt;br /&gt;
    // Or, example 2: Match the duration to a Dojo animation&lt;br /&gt;
    var anim = dojo.fx.combine([&lt;br /&gt;
        ...&lt;br /&gt;
    ]);&lt;br /&gt;
    anim.play();&lt;br /&gt;
    this.notifqueue.setSynchronousDuration(anim.duration);&lt;br /&gt;
},&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You can also manually call this.notifqueue.setSynchronousDuration(0) once client operations are finished, but be careful that even fast replay still has a path to call it.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;WARNING: combining synchronous and ignored notifications&#039;&#039;&#039;&lt;br /&gt;
You must be careful when combining dynamic synchronous durations (as described above) with ignored notifications. If you have a conditionally ignored notification like this (see below section):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;this.notifqueue.setIgnoreNotificationCheck( &#039;myNotif&#039;, (notif) =&amp;gt; (notif.args.player_id == this.player_id) /* or any other condition */ )&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
then you CANNOT do&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;this.notifqueue.setSynchronous(&#039;myNotif&#039;);&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
as, when the ignored check passes, the notification handler, in which `this.notifqueue.setSychronousDuration` is called, is never called and so the duration is never set and interface locking results.&lt;br /&gt;
&lt;br /&gt;
The workaround is to set a &amp;quot;dummy&amp;quot; time:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;this.notifqueue.setSynchronous(&#039;myNotif&#039;, 5000);&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
whose value is irrelevant but must be large enough to cover the time before the notification handler is called. The large value never actually comes into play because the notification is either ignored, or the synchronous duration is reset to a sensible value inside the handler.&lt;br /&gt;
&lt;br /&gt;
=== Pre-defined notification types ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;tableWindow&#039;&#039;&#039; - This defines notification to display [[Game_interface_logic:_yourgamename.js#Scoring_dialogs|Scoring Dialogs]], see below.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;message&#039;&#039;&#039; - This defines notification that shows on players log and have no other effect (technically any unhandled notification will do the same but its recommended to use this keyword for consistency)&lt;br /&gt;
&lt;br /&gt;
   // You can call this on php side without doing anything on client side&lt;br /&gt;
    self::notifyAllPlayers( &#039;message&#039;, clienttranslate(&#039;hello&#039;), [] );&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;simplePause&#039;&#039;&#039; - This notification will just delay other notifications, maybe useful if you know you need some extra time for animation or something. Requires a time parameter.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    self::notifyAllPlayers( &#039;simplePause&#039;, &#039;&#039;, [ &#039;time&#039; =&amp;gt; 500] ); // time is in milliseconds&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note: the following types are RESERVED by framework, do not use:&lt;br /&gt;
&lt;br /&gt;
gameStateChange gameStateChangePrivateArg gameStateMultipleActiveUpdate newActivePlayer playerstatus yourturnack clockalert tableInfosChanged playerEliminated tableDecision  archivewaitingdelay end_archivewaitingdelay replaywaitingdelay end_replaywaitingdelay replayinitialwaitingdelay end_replayinitialwaitingdelay aiPlayerWaitingDelay replay_has_ended updateSpectatorList  wouldlikethink updateReflexionTime undoRestorePoint resetInterfaceWithAllDatas zombieModeFail zombieModeFailWarning aiError skipTurnOfPlayer zombieBack allPlayersAreZombie gameResultNeutralized playerConcedeGame showTutorial showCursor showCursorClick skipTurnOfPlayerWarning  banFromTable resultsAvailable switchToTurnbased newPrivateState infomsg&lt;br /&gt;
&lt;br /&gt;
== Tooltips ==&lt;br /&gt;
&lt;br /&gt;
=== Adding static tooltips ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.addTooltip(nodeId: string, helpStringTranslated: string, actionStringTranslated: string, delay?: number): void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Add a simple text tooltip to the DOM node.&lt;br /&gt;
&lt;br /&gt;
Specify &#039;helpStringTranslated&#039; to display some information about &amp;quot;what is this game element?&amp;quot;.&lt;br /&gt;
Specify &#039;actionStringTranslated&#039; to display some information about &amp;quot;what happens when I click on this element?&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
You must specify both of the strings. You can only use one and specify an empty string (&#039;&#039;) for the other one.&lt;br /&gt;
&lt;br /&gt;
When you pass text directly function _() must be used for the text to be marked for translation! Except for empty string.&lt;br /&gt;
&lt;br /&gt;
Parameter &amp;quot;delay&amp;quot; is optional. It is primarily used to specify a zero delay for some game element when the tooltip gives really important information for the game - but remember: no essential information must be placed in tooltips as they won&#039;t be displayed in some browsers (see [[BGA_Studio_Guidelines|Guidelines]]).&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
   this.addTooltip( &#039;cardcount&#039;, _(&#039;Number of cards in hand&#039;), &#039;&#039; );&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note: this generates static tooltip and attaches to existing dom element, if you need to generate tooltip more dynamically you have to call that method every time information about object is updated or use completely different tehnique, see dynamic tooltips below.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.addTooltipHtml(nodeId: string, html: string, delay?: number): void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Add an HTML tooltip to the DOM node (for more elaborate content such as presenting a bigger version of a card).&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.addTooltipToClass(cssClass: string, helpStringTranslated: string, actionStringTranslated: string, delay?: number ): void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Add a simple text tooltip to all the DOM nodes set with this cssClass. See more details above for this.addTooltip.&lt;br /&gt;
     this.addTooltipToClass( &#039;meeple&#039;, _(&#039;This is A Meeple&#039;), _(&#039;Click to tickle&#039;) );&lt;br /&gt;
&lt;br /&gt;
IMPORTANT: all concerned nodes must exist and have IDs to get tooltips.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.addTooltipHtmlToClass(cssClass: string, html: string, delay?: number): void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Add an HTML tooltip to to all the DOM nodes set with this cssClass (for more elaborate content such as presenting a bigger version of a card).&lt;br /&gt;
&lt;br /&gt;
IMPORTANT: all concerned nodes must exist and have IDs to get tooltips.&lt;br /&gt;
&lt;br /&gt;
=== Removing static tooltips ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.removeTooltip(nodeId: string): void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Remove a tooltip from the DOM node with given id.&lt;br /&gt;
&lt;br /&gt;
=== Advanced tooltips ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;force tooltip to open&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
If you want to force tooltip to open in reaction to some other action, i.e. click you can do this&lt;br /&gt;
&lt;br /&gt;
   this.tooltips[id].open(id)&lt;br /&gt;
&lt;br /&gt;
where id is the id of the tooltip node where tooltip was installed.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;dynamic tooltips&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
See [[BGA_Studio_Cookbook#Dynamic_tooltips]]&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;tooltips on mobile&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Tooltips is very unreliable on mobile, it is recommended to implement some other method to obtaining same information,&lt;br /&gt;
such as simple click handler in dedicated &amp;quot;Help&amp;quot; mode or provide dedicated clickable areas such as corner of card.&lt;br /&gt;
&lt;br /&gt;
== Warning messages ==&lt;br /&gt;
&lt;br /&gt;
Sometimes, there is something important that is happening in the game and you have to make sure all players get the message. Most of the time, the evolution of the game situation or the game log is enough, but sometimes you need something more visible.&lt;br /&gt;
&lt;br /&gt;
Ex: someone fulfills one of the end of the game conditions, so this is the last turn.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.showMessage(msg: string, type: string): void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
showMessage shows a message in a big rectangular area on the top of the screen of the current player, and it dissapears after few seconds (also it will be in the log in some cases).&lt;br /&gt;
&lt;br /&gt;
* &amp;quot;msg&amp;quot; is the string to display. It should be translated.&lt;br /&gt;
* &amp;quot;type&amp;quot; can be set to &amp;quot;info&amp;quot;, &amp;quot;error&amp;quot;, &amp;quot;only_to_log&amp;quot; or custom string. If set to &amp;quot;info&amp;quot;, the message will be an informative message on a white background. If set to &amp;quot;error&amp;quot;, the message will be an error message on a red background and it will be added to log. If set to &amp;quot;only_to_log&amp;quot;, the message will be added to the game log but will not popup at the top of the screen.&lt;br /&gt;
If set to custom string, it will be transparent, to use custom type define &amp;quot;head_xxx&amp;quot; in css, where xxx is the type. For example if you want yellow warning, use &amp;quot;warning&amp;quot; as type and add this to css:&lt;br /&gt;
 .head_warning {&lt;br /&gt;
    background-color: #e6c66e;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
Important: the normal way to inform players about the progression of the game is the game log. The &amp;quot;showMessage&amp;quot; is intrusive and should not be used often.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    notif_messageinfo: function(notif) {&lt;br /&gt;
	if (!g_archive_mode) {&lt;br /&gt;
        	var message = this.format_string_recursive(notif.log, notif.args);&lt;br /&gt;
		this.showMessage(_(&#039;Announcement:&#039;) + &amp;quot; &amp;quot; + message, &#039;info&#039;);		&lt;br /&gt;
         }&lt;br /&gt;
    },&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Show message could be used on the client side to prevent user wrong moves before it is send to server.&lt;br /&gt;
Example from &#039;battleship&#039;:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
onGrid: function(event) {&lt;br /&gt;
     if (checkIfPlayerTriesToFireOnThemselves(event)) {&lt;br /&gt;
        this.showMessage(_(&#039;This is your own board silly!&#039;), &#039;error&#039;);&lt;br /&gt;
        return;&lt;br /&gt;
     }&lt;br /&gt;
     ...&lt;br /&gt;
},&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.showMoveUnauthorized(): void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Shows predefined user error that move is unauthorized now&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
onPet: function(event) {&lt;br /&gt;
     if (checkPet(event)==false) {&lt;br /&gt;
        this.showMoveUnauthorized();&lt;br /&gt;
        return;&lt;br /&gt;
     }&lt;br /&gt;
     ...&lt;br /&gt;
},&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Dialogs ==&lt;br /&gt;
&lt;br /&gt;
=== Confirmation dialog ===&lt;br /&gt;
&lt;br /&gt;
When an important action with a lot of consequences is triggered by the player, you may want to propose a confirmation dialog.&lt;br /&gt;
&lt;br /&gt;
CAREFUL: the general guideline of BGA is to AVOID the use of confirmation dialogs. Confirmation dialogs slow down the game and bother players. The players know that they have to pay attention to each move when they are playing online.&lt;br /&gt;
&lt;br /&gt;
The situations where you should use a confirmation dialog are the following:&lt;br /&gt;
* It must not happen very often during a game.&lt;br /&gt;
* It must be linked to an action that can really &amp;quot;kill a game&amp;quot; if the player does not pay attention.&lt;br /&gt;
* It must be something that can be done by mistake (ex: a link on the action status bar).&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.confirmationDialog(message: string, yesHandler: (param: any) =&amp;gt; void, noHandler?: (param: any) =&amp;gt; void, param?: any): void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
* message - message will be shown to user, use _() to translate&lt;br /&gt;
* yesHandler - non-optional handler to be called on yes&lt;br /&gt;
* noHandler - optional handler to called on no&lt;br /&gt;
* param - if specified, it will be passed to both handlers&lt;br /&gt;
NOTE: this is async function, it does not return anything and you should not do anything after, you must do everything in handlers&lt;br /&gt;
&lt;br /&gt;
How to display a confirmation dialog:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    this.confirmationDialog(_(&amp;quot;Are you sure you want to bake a pie?&amp;quot;), () =&amp;gt; {&lt;br /&gt;
      this.bakeThePie();&lt;br /&gt;
    });&lt;br /&gt;
    return; // nothing should be called or done after calling this, all action must be done in the handler&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
With param and both handlers&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    this.confirmationDialog(_(&amp;quot;Are you sure you want to bake a pie?&amp;quot;), &lt;br /&gt;
           (ingredient) =&amp;gt; this.bakeThePie(ingredient), &lt;br /&gt;
           (ingredient) =&amp;gt; console.log(`cancelled baking of ${ingredient}`), &lt;br /&gt;
           &#039;apple&#039;);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Multiple choice dialog ===&lt;br /&gt;
&lt;br /&gt;
You can use this dialog to give user a choice with small amount of options&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.multipleChoiceDialog(message: string, choices: string[], callback: (choice: number) =&amp;gt; void): void&#039;&#039;&#039;&lt;br /&gt;
* message - message will be shown to user, use _() to translate&lt;br /&gt;
* choices - array of choices&lt;br /&gt;
* callback - non-optional handler to be called on choice made, the choice parameter is the INDEX of the choice from the array of choices&lt;br /&gt;
&lt;br /&gt;
NOTE: this is async function, it does not return anything and you should not do anything after, you must do everything in handlers&lt;br /&gt;
NOTE: there is no cancel handler, so make sure you gave user a choice to get out of it&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    const keys = [&amp;quot;0&amp;quot;, &amp;quot;1&amp;quot;, &amp;quot;5&amp;quot;, &amp;quot;10&amp;quot;];&lt;br /&gt;
    this.multipleChoiceDialog(_(&amp;quot;How many bugs to fix?&amp;quot;), keys, (choice) =&amp;gt; {&lt;br /&gt;
      if (choice==0) return; // cancel operation, do not call server action&lt;br /&gt;
      var bugchoice = keys[choice]; // choice will be 0,1,2,3 here&lt;br /&gt;
      this.bgaPerformAction(&amp;quot;fixBugs&amp;quot;, { number: bugchoice });&lt;br /&gt;
    });&lt;br /&gt;
    return; // must return here&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Generic Dialogs ===&lt;br /&gt;
&lt;br /&gt;
As a general rule, you shouldn&#039;t use dialogs windows.&lt;br /&gt;
&lt;br /&gt;
BGA guidelines specify that all game elements should be displayed on the main screen. Players can eventually scroll down to see game elements they don&#039;t need to see anytime, and you may eventually create anchors to move between game area section. Of course dialogs windows are very practical, but the thing is: all players know how to scroll down, and not all players know how to show up your dialog window. In addition, when the dialog shows up, players can&#039;t access the other game components.&lt;br /&gt;
&lt;br /&gt;
Sometimes although, you need to display a dialog window. Here is how you do this:&lt;br /&gt;
&lt;br /&gt;
  // Create the new dialog over the play zone. You should store the handler in a member variable to access it later&lt;br /&gt;
  this.myDlg = new ebg.popindialog();&lt;br /&gt;
  this.myDlg.create( &#039;myDialogUniqueId&#039; );&lt;br /&gt;
  this.myDlg.setTitle( _(&amp;quot;my dialog title to translate&amp;quot;) );&lt;br /&gt;
  this.myDlg.setMaxWidth( 500 ); // Optional&lt;br /&gt;
  &lt;br /&gt;
  // Create the HTML of my dialog. &lt;br /&gt;
  // The best practice here is to use [[Game_layout:_view_and_template:_yourgamename.view.php_and_yourgamename_yourgamename.tpl#Javascript_templates|Javascript templates]]&lt;br /&gt;
  var html = this.format_block( &#039;jstpl_myDialogTemplate&#039;, { &lt;br /&gt;
                arg1: myArg1,&lt;br /&gt;
                arg2: myArg2,&lt;br /&gt;
                ...&lt;br /&gt;
            } );  &lt;br /&gt;
  &lt;br /&gt;
  // Show the dialog&lt;br /&gt;
  this.myDlg.setContent( html ); // Must be set before calling show() so that the size of the content is defined before positioning the dialog&lt;br /&gt;
  this.myDlg.show();&lt;br /&gt;
  &lt;br /&gt;
  // Now that the dialog has been displayed, you can connect your method to some dialog elements&lt;br /&gt;
  // Example, if you have an &amp;quot;OK&amp;quot; button in the HTML of your dialog:&lt;br /&gt;
  dojo.connect($(&#039;my_ok_button&#039;), &#039;onclick&#039;, this, (event) =&amp;gt; {&lt;br /&gt;
                event.preventDefault();&lt;br /&gt;
                this.myDlg.destroy();&lt;br /&gt;
            });&lt;br /&gt;
&lt;br /&gt;
If necessary, you can remove the default top right corner &#039;close&#039; icon, or replace the function called when it is clicked:&lt;br /&gt;
  // Removes the default close icon&lt;br /&gt;
  this.myDlg.hideCloseIcon();&lt;br /&gt;
&lt;br /&gt;
  // Replace the function call when it&#039;s clicked&lt;br /&gt;
  this.myDlg.replaceCloseCallback((event) =&amp;gt; { ... });&lt;br /&gt;
&lt;br /&gt;
=== Scoring dialogs ===&lt;br /&gt;
&lt;br /&gt;
Sometimes at the end of a round you want to display a big table that details the points wins in each section of the game.&lt;br /&gt;
&lt;br /&gt;
Example: in Hearts game, we display at the end of each round the number of &amp;quot;heart&amp;quot; cards collected by each player, the player who collected the Queen of Spades, and the total number of points loose by each player.&lt;br /&gt;
&lt;br /&gt;
Scoring dialogs are managed entirely on &#039;&#039;&#039;PHP side&#039;&#039;&#039;, but they are described here as their effects are visible only on client side.&lt;br /&gt;
&lt;br /&gt;
Displaying a scoring dialog is quite simple and is using a special notification type: &amp;quot;tableWindow&amp;quot;:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  // on PHP side:&lt;br /&gt;
  $this-&amp;gt;notifyAllPlayers( &amp;quot;tableWindow&amp;quot;, &#039;&#039;, array(&lt;br /&gt;
            &amp;quot;id&amp;quot; =&amp;gt; &#039;finalScoring&#039;,&lt;br /&gt;
            &amp;quot;title&amp;quot; =&amp;gt; clienttranslate(&amp;quot;Title of the scoring dialog&amp;quot;),&lt;br /&gt;
            &amp;quot;table&amp;quot; =&amp;gt; $table&lt;br /&gt;
        )); &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The &amp;quot;table&amp;quot; argument is a 2 dimensional PHP array that describes the table you want to display, line by line and column by column.&lt;br /&gt;
&lt;br /&gt;
Example: display an 3x3 array of strings&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
   $table = [&lt;br /&gt;
      [ &amp;quot;one&amp;quot;, &amp;quot;two&amp;quot;, &amp;quot;three&amp;quot; ],    // This is my first line&lt;br /&gt;
      [ &amp;quot;four&amp;quot;, &amp;quot;five&amp;quot;, &amp;quot;six&amp;quot; ],    // This is my second line&lt;br /&gt;
      [ &amp;quot;seven&amp;quot;, &amp;quot;height&amp;quot;, &amp;quot;nine&amp;quot; ]    // This is my third line&lt;br /&gt;
   ];&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
As you can see above, in each &amp;quot;cell&amp;quot; of your array you can display a simple string value. But you can also display a complex value with a template and associated arguments like this:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
   $table = [&lt;br /&gt;
      [ &amp;quot;one&amp;quot;, &amp;quot;two&amp;quot;, [ &amp;quot;str&amp;quot; =&amp;gt; clienttranslate(&amp;quot;a string with an ${argument}&amp;quot;), &amp;quot;args&amp;quot; =&amp;gt; [ &#039;argument&#039; =&amp;gt; &#039;argument_value&#039; ] ] ],&lt;br /&gt;
      [ &amp;quot;four&amp;quot;, &amp;quot;five&amp;quot;, &amp;quot;six&amp;quot; ], &lt;br /&gt;
      [ &amp;quot;seven&amp;quot;, &amp;quot;height&amp;quot;, &amp;quot;nine&amp;quot; ]&lt;br /&gt;
   ];&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This is especially useful when you want to display player names with colors. Example from &amp;quot;Hearts&amp;quot;:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        $firstRow = [ &#039;&#039; ];&lt;br /&gt;
        foreach( $players as $player_id =&amp;gt; $player )    {&lt;br /&gt;
            $cell = [ &#039;str&#039; =&amp;gt; &#039;${player_name}&#039;,&lt;br /&gt;
                      &#039;args&#039; =&amp;gt; [ &#039;player_name&#039; =&amp;gt; $player[&#039;player_name&#039;] ],&lt;br /&gt;
                      &#039;type&#039; =&amp;gt; &#039;header&#039;&lt;br /&gt;
                    ];&lt;br /&gt;
            $firstRow[] = $cell;&lt;br /&gt;
        }&lt;br /&gt;
        $table[] = $firstRow;&lt;br /&gt;
        ...&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You can also use three extra attributes in the parameter array for the notification:&lt;br /&gt;
* &#039;&#039;&#039;header&#039;&#039;&#039;: the content for this parameter displays before the table (also, the html will be parsed and player names will be colored according to the current game colors). &lt;br /&gt;
* &#039;&#039;&#039;footer&#039;&#039;&#039;: the content for this parameter displays after the table (no parsing for coloring the player names)&lt;br /&gt;
* &#039;&#039;&#039;closing&#039;&#039;&#039;: if this parameter is used, a button will be displayed with this label at the bottom of the popup and will allow players to close it (more easily than by clicking the top right &#039;cross&#039; icon).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
   $this-&amp;gt;notifyAllPlayers( &amp;quot;tableWindow&amp;quot;, &#039;&#039;, [&lt;br /&gt;
            &amp;quot;id&amp;quot; =&amp;gt; &#039;finalScoring&#039;,&lt;br /&gt;
            &amp;quot;title&amp;quot; =&amp;gt; clienttranslate(&amp;quot;Title of the scoring dialog&amp;quot;),&lt;br /&gt;
            &amp;quot;table&amp;quot; =&amp;gt; $table,&lt;br /&gt;
            &amp;quot;header&amp;quot; =&amp;gt; [&#039;str&#039; =&amp;gt; clienttranslate(&#039;Table header with parameter ${number}&#039;),&lt;br /&gt;
                                 &#039;args&#039; =&amp;gt; [ &#039;number&#039; =&amp;gt; 3 ],&lt;br /&gt;
                               ],&lt;br /&gt;
            &amp;quot;footer&amp;quot; =&amp;gt; &#039;&amp;lt;div class=&amp;quot;myfoot&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&#039;,&lt;br /&gt;
            &amp;quot;closing&amp;quot; =&amp;gt; clienttranslate( &amp;quot;Closing button label&amp;quot; )&lt;br /&gt;
        ] ); &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note: currently id is not used - so you cannot access resulting div by id on js side&lt;br /&gt;
Note: any traslatable stirng have to be wrapped by clienttranslate() on top level OR it has to be recursive template. &lt;br /&gt;
&lt;br /&gt;
DO NOT DO THIS: &lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
   &amp;quot;footer&amp;quot; =&amp;gt; &#039;&amp;lt;div&amp;gt;&#039;.clienttranslate( &amp;quot;The end&amp;quot; ).&#039;&amp;lt;/div&amp;gt;&#039;, // this will not work for translations!!!&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Scoring animated display ===&lt;br /&gt;
&lt;br /&gt;
Sometimes, you may want to display a score value over an element to make the scoring easier to follow for the players (Terra Mystica final scoring for example).&lt;br /&gt;
You can do it with:&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.displayScoring(anchor_id: string, color: string, score: number | string, duration?: number, offset_x?: number, offset_y?: number): void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;anchor_id&#039;&#039;&#039;: ID of the html element to place the animated score onto (without the &#039;#&#039;) &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;color&#039;&#039;&#039;: hexadecimal RGB representation of the color (should be the color of the scoring player), but without a leading &#039;#&#039;.  For instance, &#039;ff0000&#039; for red.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;score&#039;&#039;&#039;: numeric score to display, prefixed by a &#039;+&#039; or &#039;-&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;duration&#039;&#039;&#039;: animation duration in milliseconds (optional, default is 1000)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;offset_x&#039;&#039;&#039; and &#039;&#039;&#039;offset_y&#039;&#039;&#039;: if both offset_x and offset_y are defined and not null, apply the following offset (in pixels) to the scoring animation. &lt;br /&gt;
Note that the score is centered in the anchor, so the offsets might have to be negative if you calculate the position.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Note: if you want to display successively each score, you can use &#039;&#039;this.notifqueue.setSynchronous()&#039;&#039; function.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    setupNotifications: function()   {&lt;br /&gt;
           dojo.subscribe( &#039;displayScoring&#039;, this, &amp;quot;notif_displayScoring&amp;quot; );&lt;br /&gt;
           ...&lt;br /&gt;
    }&lt;br /&gt;
...&lt;br /&gt;
&lt;br /&gt;
    notif_displayScoring: function(notif) {&lt;br /&gt;
            const duration = notif.args.duration?notif.args.duration:1000;&lt;br /&gt;
            this.notifqueue.setSynchronous(&#039;displayScoring&#039;, duration );&lt;br /&gt;
	    this.displayScoring( notif.args.target, notif.args.color, notif.args.score, duration);&lt;br /&gt;
    },&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Speech bubble ===&lt;br /&gt;
&lt;br /&gt;
For better interactivity in some games (Love Letter for example), you may use comic book style speech bubbles to express the players voices.&lt;br /&gt;
This is done with showBubble:&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.showBubble(anchor_id: string, text: string, delay?: number, duration?: number, custom_class?: string): void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
* anchor_id - where to attach the bubble&lt;br /&gt;
* text - what to put in bubble, can be html&lt;br /&gt;
* delay - delay in milliseconds (optional, default 0)&lt;br /&gt;
* duration -  duration of animation in milliseconds (optional, default 3000)&lt;br /&gt;
* custom_class - extra class to add to bubble (optional), if you need to override the default bubble style&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
   this.showBubble(&#039;meeple_2&#039;, _(&#039;Hello&#039;), 0, 1000, &#039;pink_bubble&#039;);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  notif_speechBubble(notif) {&lt;br /&gt;
    var html = this.format_string_recursive(notif.args.text, notif.args.args);&lt;br /&gt;
    this.showBubble(notif.args.target, html, notif.args.delay ?? 0, notif.args.duration ?? 1000);&lt;br /&gt;
  },&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Warning&#039;&#039;&#039;: if your bubble could overlap other active elements of the interface (buttons in particular), as it stays in place even after disappearing, you should use a custom class to give it the style &amp;quot;pointer-events: none;&amp;quot; in order to intercept click events.&lt;br /&gt;
&lt;br /&gt;
Note: If you want this visually, but want to take complete control over this bubble and its animation (for example to make it permanent) you can just use div with &#039;discussion_bubble&#039; class on it, and content of div is what will be shown.&lt;br /&gt;
&lt;br /&gt;
== Translations ==&lt;br /&gt;
&lt;br /&gt;
See [[Translations]]&lt;br /&gt;
&lt;br /&gt;
== Players panels ==&lt;br /&gt;
&lt;br /&gt;
=== Update players score ===&lt;br /&gt;
&lt;br /&gt;
The column player_score from the player table is automatically loaded into this.scoreCtrl and therefore into the stars location on the player board. This occurs sometime after the game setup() function. However this score must be updated as the game progresses using notifications.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Note: this.scoreCtrl[player_id] is object of class [[Counter]], you can use other counter API.&lt;br /&gt;
&lt;br /&gt;
Increase a player score (with a positive or negative number):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  this.scoreCtrl[ player_id ].incValue( score_delta );&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Set a player score to a specific value:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  this.scoreCtrl[ player_id ].setValue( new_score );&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Set a player score to a specific value with animation:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  this.scoreCtrl[ player_id ].toValue( new_score );&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Typical usage would be (that will process &#039;score&#039; notification):&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        setupNotifications : function() {&lt;br /&gt;
              ...&lt;br /&gt;
             dojo.subscribe(&#039;score&#039;, this, &amp;quot;notif_score&amp;quot;);&lt;br /&gt;
        },&lt;br /&gt;
        notif_score: function(notif) {&lt;br /&gt;
            this.scoreCtrl[notif.args.player_id].setValue(notif.args.player_score);&lt;br /&gt;
        },&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Adding stuff to player&#039;s panel ===&lt;br /&gt;
&lt;br /&gt;
At first, create a new &amp;quot;JS template&amp;quot; string in your template (tpl) file:&lt;br /&gt;
&lt;br /&gt;
(from Gomoku example)&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
var jstpl_player_board = &#039;\&amp;lt;div class=&amp;quot;cp_board&amp;quot;&amp;gt;\&lt;br /&gt;
    &amp;lt;div id=&amp;quot;stoneicon_p${id}&amp;quot; class=&amp;quot;gmk_stoneicon gmk_stoneicon_${color}&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&amp;lt;span id=&amp;quot;stonecount_p${id}&amp;quot;&amp;gt;0&amp;lt;/span&amp;gt;\&lt;br /&gt;
&amp;lt;/div&amp;gt;&#039;;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Then, you add this piece of code in your JS file to add this template to each player panel:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
            // Setting up player boards&lt;br /&gt;
            for( var player_id in gamedatas.players )&lt;br /&gt;
            {&lt;br /&gt;
                var player = gamedatas.players[player_id];&lt;br /&gt;
                         &lt;br /&gt;
                // Setting up players boards if needed&lt;br /&gt;
                var player_board_div = $(&#039;player_board_&#039;+player_id);&lt;br /&gt;
                dojo.place( this.format_block(&#039;jstpl_player_board&#039;, player ), player_board_div );&lt;br /&gt;
            }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
(Note: the code above is of course from your &amp;quot;setup&amp;quot; function in your Javascript).&lt;br /&gt;
&lt;br /&gt;
Very often, you have to distinguish current player and others players. In this case, you just have to create another JS template (ex: jstpl_otherplayer_board) and use it when &amp;quot;player_id&amp;quot; is different than &amp;quot;this.player_id&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Fixing Player Panel heights ===&lt;br /&gt;
&lt;br /&gt;
You may find that the player panels don&#039;t automatically resize when adding something to (or removing something from) a player panel while the display is in portrait mode (i.e. the player summary panels are at the top of the screen rather than down the right side).&lt;br /&gt;
&lt;br /&gt;
When this happens, call &amp;lt;pre&amp;gt;this.adaptPlayersPanels();&amp;lt;/pre&amp;gt; This recalculates the layout and also adjusts the position of the actionbar for you.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Player&#039;s panel disabling/enabling ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.disablePlayerPanel(player_id: number): void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Disable given player panel (the panel background become gray).&lt;br /&gt;
&lt;br /&gt;
Usually, this is used to signal that this played passes, or will be inactive during a while.&lt;br /&gt;
&lt;br /&gt;
Note that the only effect of this is visual. There are no consequences on the behaviour of the panel itself.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.enablePlayerPanel(player_id:number): void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Enable a player panel that has been disabled before.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.enableAllPlayerPanels(): void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Enable all player panels that has been disabled before.&lt;br /&gt;
&lt;br /&gt;
=== Player order ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.updatePlayerOrdering(): void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
This function makes sure that player order in player&#039;s panel matches this.gamedatas.playerorder and its normally called by framework.&lt;br /&gt;
You can call it yoursel if you change this.gamedatas.playerorder from notification.&lt;br /&gt;
Also you can override this function to change defaults  OR insert a non-player panel [[BGA_Studio_Cookbook#Inserting_non-player_panel]].&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Counters ===&lt;br /&gt;
Note: there is bga component called  &amp;quot;ebg/counter&amp;quot; this API is not using it, these methods&lt;br /&gt;
below declared right in core game. If you need animation for counters use ebg/counter&lt;br /&gt;
&lt;br /&gt;
To use this API just create a counter dom element like this (class does not really matter)&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 &amp;lt;div class=&amp;quot;counter&amp;quot; id=&amp;quot;bread&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
 &amp;lt;div class=&amp;quot;counter&amp;quot; id=&amp;quot;coin&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
The &amp;quot;bread&amp;quot; will the counter name.&lt;br /&gt;
&lt;br /&gt;
The php code should send all &amp;quot;counters&amp;quot; data from getAllDatas() method like this&lt;br /&gt;
&lt;br /&gt;
game.php&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  protected function getAllDatas() {&lt;br /&gt;
    // (the key must match counter_name)&lt;br /&gt;
    $result[&#039;counters&#039;]=[&lt;br /&gt;
        &#039;bread&#039; =&amp;gt; [ &lt;br /&gt;
         &#039;counter_name&#039; =&amp;gt; &#039;bread&#039;, &lt;br /&gt;
         &#039;counter_value&#039; =&amp;gt; 3&lt;br /&gt;
         ], &lt;br /&gt;
        &#039;coin&#039; =&amp;gt; [&lt;br /&gt;
          &#039;counter_name&#039; =&amp;gt; &#039;coin&#039;, &lt;br /&gt;
          &#039;counter_value&#039; =&amp;gt; 5&lt;br /&gt;
        ]&lt;br /&gt;
   ];&lt;br /&gt;
   return $result;&lt;br /&gt;
  }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;setCounter(counter_name: stirng, new_value: string | number): void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
updates the global this.gamedatas.counters and value of node $(counter_name)&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  notif_counter: function(notif) { &lt;br /&gt;
    this.setCounter(notif.args.counter_name, notif.args.counter_value);&lt;br /&gt;
  },&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;incCounter(counter_name: string, delta: number): void&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  notif_counter : function(notif) {&lt;br /&gt;
    this.incCounter(notif.args.counter_name, notif.args.inc);&lt;br /&gt;
  },&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;updateCounters(counters: object): void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Useful for updating game counters in the player panel (such as resources). &lt;br /&gt;
&#039;counters&#039; arg is map of counters (the key must match counter_name)&lt;br /&gt;
  {&lt;br /&gt;
    &#039;bread&#039;: { &lt;br /&gt;
         &#039;counter_name&#039; : &#039;bread&#039;, &lt;br /&gt;
         &#039;counter_value&#039; =&amp;gt; 3&lt;br /&gt;
    }, &lt;br /&gt;
    &#039;coin&#039;: { &lt;br /&gt;
         &#039;counter_name&#039; : &#039;coin&#039;, &lt;br /&gt;
         &#039;counter_value&#039; =&amp;gt; 5&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
All counters MUST be referenced in this.gamedatas.counters (means they should be send from php) and will be updated.&lt;br /&gt;
DOM objects referenced by &#039;counter_name&#039; will have their innerHTML updated with &#039;counter_value&#039;.&lt;br /&gt;
&lt;br /&gt;
Usually you call this from notification&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
                        notif_counter : function(notif) {&lt;br /&gt;
                            this.updateCounters(notif.args.counters);&lt;br /&gt;
                        },&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== BGA GUI components ==&lt;br /&gt;
&lt;br /&gt;
BGA framework provides some useful ready-to-use components for the game interface:&lt;br /&gt;
&lt;br /&gt;
[[Studio#BGA_Studio_game_components_reference]]&lt;br /&gt;
&lt;br /&gt;
Note that each time you are using an additional component, you must declare it at the top of your Javascript file in the list of modules used.&lt;br /&gt;
&lt;br /&gt;
Example if you are using &amp;quot;ebg.stock&amp;quot;:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
define([&lt;br /&gt;
    &amp;quot;dojo&amp;quot;,&amp;quot;dojo/_base/declare&amp;quot;,&lt;br /&gt;
    &amp;quot;ebg/core/gamegui&amp;quot;,&lt;br /&gt;
    &amp;quot;ebg/counter&amp;quot;,&lt;br /&gt;
    &amp;quot;ebg/stock&amp;quot;  /// &amp;lt;=== we are using ebg.stock module&lt;br /&gt;
],&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== BGA Buttons ==&lt;br /&gt;
&lt;br /&gt;
=== Basic Button ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.addActionButton(id: string, label: string, method: string | eventhandler, destination?: string, blinking?: boolean, color?: string): void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
You can use this method to add an action button in the main action status bar (or other places).&lt;br /&gt;
&lt;br /&gt;
Arguments:&lt;br /&gt;
* id: an element ID that should be unique in your HTML DOM document.&lt;br /&gt;
* label: the text of the button. Should be translatable (use _() function). Note: this can also be any html, such as &amp;quot;&amp;lt;div class=&#039;brick&#039;&amp;gt;&amp;lt;/div&amp;gt;&amp;quot;, see example below on how to make image action buttons.&lt;br /&gt;
* method: the name of your method that must be triggered when the player clicks on this button (can be name of the method on game class or handler).&lt;br /&gt;
* destination (optional): id of parent on where to add button, ONLY use in rare cases if location is not action bar. Use &#039;&#039;&#039;null&#039;&#039;&#039; as value if you need to specify other arguments.&lt;br /&gt;
* blinking (optional): if set to &#039;&#039;&#039;true&#039;&#039;&#039;, the button is going blink to catch player&#039;s attention. Please DO NOT abuse blinking button. If you need button to blink after some time passed add class &#039;blinking&#039; to the button later.&lt;br /&gt;
* color: could be &#039;&#039;&#039;blue&#039;&#039;&#039; (default), &#039;&#039;&#039;red&#039;&#039;&#039;,&#039;&#039;&#039;gray&#039;&#039;&#039; or &#039;&#039;&#039;none&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
You should only use this method in your &amp;quot;onUpdateActionButtons&amp;quot; method. Usually, you use it like this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        onUpdateActionButtons: function( stateName, args ) {                      &lt;br /&gt;
            if (this.isCurrentPlayerActive()) {            &lt;br /&gt;
                switch( stateName ) {&lt;br /&gt;
                case &#039;giveCards&#039;:&lt;br /&gt;
                    this.addActionButton( &#039;giveCards_button&#039;, _(&#039;Give selected cards&#039;), &#039;onGiveCards&#039; ); &lt;br /&gt;
                    this.addActionButton( &#039;pass_button&#039;, _(&#039;Pass&#039;), () =&amp;gt; this.bgaPerformAction(&#039;actPass&#039;) ); &lt;br /&gt;
                    break;&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        },   &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In the example above, we are adding a &amp;quot;Give selected cards&amp;quot; button in the case we are on game state &amp;quot;giveCards&amp;quot;. When player clicks on this button, it triggers our &amp;quot;onGiveCards&amp;quot; method.&lt;br /&gt;
&lt;br /&gt;
Example using blinking red button:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    this.addActionButton( &#039;button_confirm&#039;, _(&#039;Confirm?&#039;), &#039;onConfirm&#039;, null, true, &#039;red&#039;); &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If you want to call the handler with arguments, you can use arrow functions, like this:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
     this.addActionButton( &#039;commit_button&#039;, _(&#039;Confirm&#039;), () =&amp;gt; this.onConfirm(this.selectedCardId), null, false, &#039;red&#039;); &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Image Button ===&lt;br /&gt;
&lt;br /&gt;
You can use the same method, but add extra class to a button to disable the padding and style it, i.e.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
this.addActionButton( &#039;button_brick&#039;, &#039;&amp;lt;div class=&amp;quot;brick&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&#039;, ()=&amp;gt;{... on brick ...}, null, null, &#039;gray&#039;); &lt;br /&gt;
dojo.addClass(&#039;button_brick&#039;,&#039;bgaimagebutton&#039;);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
where&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
.bgaimagebutton {&lt;br /&gt;
  padding: 0px 12px;&lt;br /&gt;
  min-height: 28px;&lt;br /&gt;
  border: none;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If you use this a lot, you can define a helper function, i.e.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
 * This method can be used instead of addActionButton, to add a button which is an image (i.e. resource). Can be useful when player&lt;br /&gt;
 * need to make a choice of resources or tokens.&lt;br /&gt;
 */&lt;br /&gt;
addImageActionButton: function(id, div, handler, bcolor, tooltip) {&lt;br /&gt;
	if (typeof bcolor == &amp;quot;undefined&amp;quot;) {&lt;br /&gt;
		bcolor = &amp;quot;gray&amp;quot;;&lt;br /&gt;
	}&lt;br /&gt;
	// this will actually make a transparent button id color = gray&lt;br /&gt;
	this.addActionButton(id, div, handler, null, false, bcolor);&lt;br /&gt;
	// remove border, for images it better without&lt;br /&gt;
	dojo.style(id, &amp;quot;border&amp;quot;, &amp;quot;none&amp;quot;);&lt;br /&gt;
	// but add shadow style (box-shadow, see css)&lt;br /&gt;
	dojo.addClass(id, &amp;quot;shadow bgaimagebutton&amp;quot;);&lt;br /&gt;
	// you can also add additional styles, such as background&lt;br /&gt;
	if (tooltip) {&lt;br /&gt;
		dojo.attr(id, &amp;quot;title&amp;quot;, tooltip);&lt;br /&gt;
	}&lt;br /&gt;
	return $(id);&lt;br /&gt;
},&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Disabling Button ===&lt;br /&gt;
&lt;br /&gt;
You can disable the &#039;&#039;&#039;bgabutton&#039;&#039;&#039; by adding the css class &#039;&#039;&#039;disabled&#039;&#039;&#039; in you js. The disabled button is still visible but is grey and not clickable.&lt;br /&gt;
For example in the &#039;&#039;&#039;onUpdateActionButtons&#039;&#039;&#039; : &lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
this.addActionButton(&#039;play_button_id&#039;, _(&#039;Play 1 to 3 cards&#039;), &#039;playFunctionButton&#039;); &lt;br /&gt;
if (condition) {&lt;br /&gt;
  dojo.addClass(&#039;play_button_id&#039;, &#039;disabled&#039;);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Custom Buttons ===&lt;br /&gt;
&lt;br /&gt;
You can create a custom button, but the BGA framework provides a standard button that requires only .css classes: &#039;&#039;&#039;bgabutton&#039;&#039;&#039; and &#039;&#039;&#039;bgabutton_${color}&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Examples:&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;a href=&amp;quot;#&amp;quot; id=&amp;quot;my_button_id&amp;quot; class=&amp;quot;bgabutton bgabutton_blue&amp;quot;&amp;gt;&amp;lt;span&amp;gt;My blue button&amp;lt;/span&amp;gt;&amp;lt;/a&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;a href=&amp;quot;#&amp;quot; id=&amp;quot;my_button_id&amp;quot; class=&amp;quot;bgabutton bgabutton_red bgabutton_big&amp;quot;&amp;gt;&amp;lt;span&amp;gt;My big red button&amp;lt;/span&amp;gt;&amp;lt;/a&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note&#039;&#039;&#039;: To see it in action, check out &#039;&#039;Coloretto&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
=== Button outside of action bar ===&lt;br /&gt;
&lt;br /&gt;
Use addActionButton() method with destination argument set&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
this.addActionButton( &#039;commit_button&#039;, _(&#039;Confirm&#039;), &#039;onConfirm&#039;, &#039;player_board&#039;, true, &#039;red&#039;); &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
in example above the button will be place on object with id &#039;player_board&#039;&lt;br /&gt;
&lt;br /&gt;
== Image loading ==&lt;br /&gt;
&lt;br /&gt;
See also [[Game_art:_img_directory]].&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Be careful&#039;&#039;&#039;: by default, ALL images of your img directory are loaded on a player&#039;s browser when he loads the game. For this reason, don&#039;t let in your img directory images that are not useful, otherwise it&#039;s going to slowdown the game load.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.dontPreloadImage(image_file_name: string)&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Using dontPreloadImage, you tell the interface to not preload a specific image in your img directory.&lt;br /&gt;
&lt;br /&gt;
Example of use:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
this.dontPreloadImage( &#039;cards.png&#039; );&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This is particularly useful if for example you have 2 different themes for a game. To accelerate the loading of the game, you can specify to not preload images corresponding to the other theme.&lt;br /&gt;
&lt;br /&gt;
Another example of use: in &amp;quot;Gosu&amp;quot; game with Kamakor extension, you play with 5 sets of cards among 10 available. Cards images are organized by sets, and we only preload the images corresponding to the 5 current sets with &#039;&#039;&#039;ensureSpecificGameImageLoading( image_file_names_array )&#039;&#039;&#039;.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
// By default, do not preload anything&lt;br /&gt;
this.dontPreloadImage( &#039;cards.png&#039; );&lt;br /&gt;
this.dontPreloadImage( &#039;clan1.png&#039; );&lt;br /&gt;
this.dontPreloadImage( &#039;clan2.png&#039; );&lt;br /&gt;
this.dontPreloadImage( &#039;clan3.png&#039; );&lt;br /&gt;
this.dontPreloadImage( &#039;clan4.png&#039; );&lt;br /&gt;
this.dontPreloadImage( &#039;clan5.png&#039; );&lt;br /&gt;
this.dontPreloadImage( &#039;clan6.png&#039; );&lt;br /&gt;
this.dontPreloadImage( &#039;clan7.png&#039; );&lt;br /&gt;
this.dontPreloadImage( &#039;clan8.png&#039; );&lt;br /&gt;
this.dontPreloadImage( &#039;clan9.png&#039; );&lt;br /&gt;
this.dontPreloadImage( &#039;clan10.png&#039; );&lt;br /&gt;
var to_preload = [];&lt;br /&gt;
for( i in this.gamedatas.clans )&lt;br /&gt;
{&lt;br /&gt;
	var clan_id = this.gamedatas.clans[i];&lt;br /&gt;
	to_preload.push( &#039;clan&#039;+clan_id+&#039;.png&#039; );&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
this.ensureSpecificGameImageLoading( to_preload );&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note:&#039;&#039;&#039; You don&#039;t need to specify to not preload game box images (game_box.png, game_box75.png...) since they are not preloaded by default.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.ensureSpecificGameImageLoading(list: string[])&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
This is oppostive of dontPreloadImage - its ensure specific images is loaded. Note: only makes sense if preload list is empty, otherwise everything is loaded anyway&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;load specific images&#039;&#039;&#039;&lt;br /&gt;
All images that will be preloaded stored in g_img_preload. If you want to override it directly - there is no API, but you can do this in GAME constructor&lt;br /&gt;
&lt;br /&gt;
          g_img_preload = [&#039;tokens.png&#039;, &#039;trains.png&#039;, &#039;loc_plan.png&#039;, &#039;eng.png&#039;, &#039;eng-back.png&#039;];&lt;br /&gt;
&lt;br /&gt;
You can also set it to empty array and call ensureSpecificGameImageLoading() on specific images&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Sounds ==&lt;br /&gt;
&lt;br /&gt;
Add a custom sound and make it load with your interface:&lt;br /&gt;
&lt;br /&gt;
Add this in your template (.tpl) file:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;audio id=&amp;quot;audiosrc_&amp;lt;gamename&amp;gt;_&amp;lt;yoursoundname&amp;gt;&amp;quot; src=&amp;quot;{GAMETHEMEURL}img/&amp;lt;gamename&amp;gt;_&amp;lt;yoursoundname&amp;gt;.mp3&amp;quot; preload=&amp;quot;none&amp;quot; autobuffer&amp;gt;&amp;lt;/audio&amp;gt;&lt;br /&gt;
&amp;lt;audio id=&amp;quot;audiosrc_o_&amp;lt;gamename&amp;gt;_&amp;lt;yoursoundname&amp;gt;&amp;quot; src=&amp;quot;{GAMETHEMEURL}img/&amp;lt;gamename&amp;gt;_&amp;lt;yoursoundname&amp;gt;.ogg&amp;quot; preload=&amp;quot;none&amp;quot; autobuffer&amp;gt;&amp;lt;/audio&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note: this is a requirement to provide both a mp3 and a ogg file with the names &amp;lt;code&amp;gt;&amp;lt;gamename&amp;gt;_&amp;lt;yoursoundname&amp;gt;[.ogg][.mp3]&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Play the sound (from your .js file):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
playSound(&#039;&amp;lt;gamename&amp;gt;_&amp;lt;yoursoundname&amp;gt;&#039;);   // do not add &#039;this.&#039; - its a global function&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Disable the standard &amp;quot;move&amp;quot; sound for this move (to replace it with your custom sound):&lt;br /&gt;
&lt;br /&gt;
Add this to your notification handler:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
this.disableNextMoveSound();&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note: it only disable the sound for the next move.&lt;br /&gt;
&lt;br /&gt;
== Title bar and states ==&lt;br /&gt;
&lt;br /&gt;
=== Client states ===&lt;br /&gt;
&lt;br /&gt;
Client states is a way to simulate the state transition but without actually going&lt;br /&gt;
to server. It is usefull when you need to ask user multiple questions before you&lt;br /&gt;
send things to server&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.setClientState(newState: string, args: object)&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
     this.setClientState(&amp;quot;client_playerPicksLocation&amp;quot;, {&lt;br /&gt;
                               descriptionmyturn : _(&amp;quot;${you} must select location&amp;quot;),&lt;br /&gt;
                           });&lt;br /&gt;
&lt;br /&gt;
For more information see [[BGA_Studio_Cookbook#Multi_Step_Interactions:_Select_Worker.2FPlace_Worker_-_Using_Client_States]]&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.restoreServerGameState()&#039;&#039;&#039;&lt;br /&gt;
If you are in client state it will restore the current server state (cheap undo)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.on_client_state&#039;&#039;&#039;&lt;br /&gt;
Boolean indicating that we are in client state&lt;br /&gt;
&lt;br /&gt;
=== Title bar ===&lt;br /&gt;
If you simply want to show something in title bar you can do it directly &lt;br /&gt;
     $(&#039;pagemaintitletext&#039;).innerHTML = text;&lt;br /&gt;
&lt;br /&gt;
This however will not work with parameters and will not draw You in color,&lt;br /&gt;
if you want to do proper args rendering use method below&lt;br /&gt;
&lt;br /&gt;
;&#039;&#039;&#039;this.removeActionButtons()&#039;&#039;&#039;&lt;br /&gt;
Removes all buttons from title bar&lt;br /&gt;
&lt;br /&gt;
;&#039;&#039;&#039;this.updatePageTitle()&#039;&#039;&#039;&lt;br /&gt;
:This function allows to update the current page title and turn description according to the game state arguments. If the current game state description this.gamedatas.gamestate.descriptionmyturn is modified before calling this function it allows to update the turn description without changing state. This will handle arguments substitutions properly.&lt;br /&gt;
&lt;br /&gt;
Note: this functional also will calls this.onUpdateActionButtons, if you want different buttons then state defaults, use method in example to replace them, if it becomes too clumsy use client states (see above)&lt;br /&gt;
&lt;br /&gt;
Example from Terra Mystica:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
onClickFavorTile: function( evt ) {&lt;br /&gt;
    ...&lt;br /&gt;
    if ( ... ) {&lt;br /&gt;
        this.gamedatas.gamestate.descriptionmyturn = _(&#039;Special action: &#039;) + _(&#039;Advance 1 space	on a Cult track&#039;);&lt;br /&gt;
        this.updatePageTitle();&lt;br /&gt;
        this.removeActionButtons();&lt;br /&gt;
        this.addActionButton( ... );&lt;br /&gt;
         ...&lt;br /&gt;
        return;&lt;br /&gt;
    }&lt;br /&gt;
    ...&lt;br /&gt;
&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== User preferences ==&lt;br /&gt;
&#039;&#039;&#039;this.getGameUserPreference(pref_id)&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Return the value of a user preference. It will return the value currently selected in the select combo box, in the top-right menu.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.setGameUserPreference(pref_id, value)&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Programmatically change a user preference. It will have the same effect as if the player changed the value in the select combo box, in the top-right menu.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.onGameUserPreferenceChanged&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
A callback you can define if you want to be notified when a user changes a user preference.&lt;br /&gt;
&lt;br /&gt;
Example:&amp;lt;pre&amp;gt;&lt;br /&gt;
onGameUserPreferenceChanged: function(pref_id, pref_value) {&lt;br /&gt;
  switch (pref_id) {&lt;br /&gt;
    case 201: &lt;br /&gt;
      document.getElementsByTagName(&#039;html&#039;)[0].classList.toggle(&#039;dark-background&#039;, pref_value == 2);&lt;br /&gt;
      break;&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Other useful stuff ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;dojo.hitch&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
With dojo.hitch, you can create a callback function that will run with your game object context whatever happen.&lt;br /&gt;
&lt;br /&gt;
Typical example: display a BGA confirmation dialog with a callback function created with dojo.hitch:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        this.confirmationDialog( _(&#039;Are you sure you want to make this?&#039;), dojo.hitch( this, function() {&lt;br /&gt;
            this.bgaPerformAction(&#039;makeThis&#039;);&lt;br /&gt;
        } ) );   &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In the example above, using dojo.hitch, we ensure that the &amp;quot;this&amp;quot; object will be set when the callback is called.&lt;br /&gt;
&lt;br /&gt;
NOTE: In modern JS there are lambdas that eliminate need for that, the example above will look like this&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        this.confirmationDialog( _(&#039;Are you sure you want to make this?&#039;), () =&amp;gt; this.bgaPerformAction( &#039;makeThis&#039;) );   &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
;&#039;&#039;&#039;onScreenWidthChange()&#039;&#039;&#039;&lt;br /&gt;
:This function can be overridden in your game to manage some resizing on the client side when the browser window is resized. This function is also triggered at load time, so it can be used to adapt to the :viewport size at the start of the game too.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
; this.bRealtime&lt;br /&gt;
: Return true if the game is in realtime. Note that having a distinct behavior in realtime and turn-based should be exceptional.&lt;br /&gt;
&lt;br /&gt;
; g_replayFrom&lt;br /&gt;
: Global contains replay number in live game, it is set to undefined (i.e. not set) when it is not a replay mode, so consequentially the good check is &#039;&#039;&#039;typeof g_replayFrom != &#039;undefined&#039;&#039;&#039;&#039; which returns true if the game is in replay mode &amp;lt;i&amp;gt;during the game&amp;lt;/i&amp;gt; (the game is ongoing but the user clicked &amp;quot;replay from this move&amp;quot; in the log)&lt;br /&gt;
&lt;br /&gt;
; g_archive_mode&lt;br /&gt;
: Returns true if the game is in archive mode &amp;lt;i&amp;gt;after the game&amp;lt;/i&amp;gt; (the game has ended)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
; this.instantaneousMode&lt;br /&gt;
: Returns true during replay/archive mode if animations should be skipped. Only needed if you are doing custom animations. (The BGA-provided animation functions like &amp;lt;i&amp;gt;this.slideToObject()&amp;lt;/i&amp;gt; automatically handle instantaneous mode.)&lt;br /&gt;
: Technically, when you click &amp;quot;replay from move #20&amp;quot;, the system replays the game from the very beginning with moves 0 - 19 happening in instantaneous mode and moves 20+ happening in normal mode.&lt;br /&gt;
&lt;br /&gt;
; g_tutorialwritten&lt;br /&gt;
: Returns an object like the below if the game is in tutorial mode, or undefined otherwise. Tutorial mode is a special case of archive mode where comments have been added to a previous game to teach new players the rules.&lt;br /&gt;
    {&lt;br /&gt;
        author: &amp;quot;91577332&amp;quot;,&lt;br /&gt;
        id: &amp;quot;576&amp;quot;,&lt;br /&gt;
        mode: &amp;quot;view&amp;quot;&lt;br /&gt;
        status: &amp;quot;alpha&amp;quot;&lt;br /&gt;
        version_override: null&lt;br /&gt;
        viewer_id: &amp;quot;84554161&amp;quot;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;getBgaEnvironment(): string&#039;&#039;&#039;&lt;br /&gt;
: Returns &amp;quot;studio&amp;quot; for studio and &amp;quot;prod&amp;quot; for production environment (i.e. where games current runs). Only useful for debbugging hooks.&lt;br /&gt;
Note: alpha server is also &amp;quot;prod&amp;quot;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Category:Studio]]&lt;/div&gt;</summary>
		<author><name>Sguzzer Gunayer</name></author>
	</entry>
	<entry>
		<id>https://en.doc.boardgamearena.com/index.php?title=Game_interface_logic:_Game.js&amp;diff=22700</id>
		<title>Game interface logic: Game.js</title>
		<link rel="alternate" type="text/html" href="https://en.doc.boardgamearena.com/index.php?title=Game_interface_logic:_Game.js&amp;diff=22700"/>
		<updated>2024-09-23T10:01:00Z</updated>

		<summary type="html">&lt;p&gt;Sguzzer Gunayer: /* Style */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Studio_Framework_Navigation}}&lt;br /&gt;
&lt;br /&gt;
__TOC__&lt;br /&gt;
&lt;br /&gt;
This is the main file for your game interface. Here you will define:&lt;br /&gt;
&lt;br /&gt;
* Which actions on the page will generate calls to the server.&lt;br /&gt;
* What happens when you get a notification for a change from the server and how it will show in the browser. &lt;br /&gt;
* Setup user interface&lt;br /&gt;
&lt;br /&gt;
== File structure ==&lt;br /&gt;
&lt;br /&gt;
The details of how the file is structured are described below with comments in the code skeleton provided to you.&lt;br /&gt;
&lt;br /&gt;
Here is the basic structure:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;constructor&#039;&#039;&#039;: here you can define global variables for your whole interface.&lt;br /&gt;
* &#039;&#039;&#039;setup&#039;&#039;&#039;: this method is called when the page is refreshed, and sets up the game interface.&lt;br /&gt;
* &#039;&#039;&#039;onEnteringState&#039;&#039;&#039;: this method is called when entering a new game state. You can use it to customize the view for each game state.&lt;br /&gt;
* &#039;&#039;&#039;onLeavingState&#039;&#039;&#039;: this method is called when leaving a game state.&lt;br /&gt;
* &#039;&#039;&#039;onUpdateActionButtons&#039;&#039;&#039;: called on state changes, in order to add action buttons to the status bar. Note: in a multipleactiveplayer state, it will be called when another player has become inactive.&lt;br /&gt;
* &#039;&#039;(utility methods)&#039;&#039;: this is where you can define your utility methods.&lt;br /&gt;
* &#039;&#039;(player&#039;s actions)&#039;&#039;: this is where you can write your handlers for player actions on the interface (example: click on an item).&lt;br /&gt;
* &#039;&#039;&#039;setupNotifications&#039;&#039;&#039;: this method associates notifications with notification handlers. For each game notification, you can trigger a javascript method to handle it and update the game interface.&lt;br /&gt;
* &#039;&#039;(notification handlers)&#039;&#039;: this is where you define the notifications handlers associated with notifications in &#039;&#039;&#039;setupNotifications&#039;&#039;&#039;, above.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
More details:&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;setup(gamedatas: object)            &#039;&#039;&#039;&lt;br /&gt;
This method must set up the game user interface according to current game situation specified in parameters.&lt;br /&gt;
The method is called each time the game interface is displayed to a player, ie:&lt;br /&gt;
&lt;br /&gt;
* when the game starts&lt;br /&gt;
* when a player opens a game in the browser later &lt;br /&gt;
* when a player refreshes the game page (F5)&lt;br /&gt;
* when player does a server side Undo&lt;br /&gt;
&lt;br /&gt;
&amp;quot;gamedatas&amp;quot; argument contains all data retrieved by your &amp;quot;getAllDatas&amp;quot; PHP method and some more.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;onEnteringState(stateName: string, args: { args: any } | null): void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
This method is called each time we enter a new game state.&lt;br /&gt;
You can use this method to perform some user interface changes at this moment.&lt;br /&gt;
To access state arguments passed via calling php arg* method use args?.args.&lt;br /&gt;
Typically you would do something only for active player, using this.isCurrentPlayerActive() check.&lt;br /&gt;
It is also called (for the current game state only) when doing a browser refresh (after the setup method is called).&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Warning&#039;&#039;&#039;: for multipleactiveplayer states:&lt;br /&gt;
the active players are NOT active yet so you must use onUpdateActionButtons to perform the client side operation which depends on a player active/inactive status.&lt;br /&gt;
If you are doing initialization of some structures which do not depend on the active player, you can just replace (this.isCurrentPlayerActive()) with (!this.isSpectator) &lt;br /&gt;
for the main switch in that method.&lt;br /&gt;
&lt;br /&gt;
See more details in [[Your_game_state_machine:_states.inc.php#Difference_between_Single_active_and_Multi_active_states]]&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;onLeavingState(stateName: string): void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
This method is called each time we leave a game state.&lt;br /&gt;
You can use this method to perform some user interface changes at this point (i.e. cleanup).&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;onUpdateActionButtons(stateName: string, args: object | null): void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
In this method you can manage &amp;quot;action buttons&amp;quot; that are displayed in the action status bar and highlight active UI elements.&lt;br /&gt;
To access state arguments passed via calling php arg* method use &#039;&#039;&#039;args&#039;&#039;&#039; parameter. Note: args can be null! For &#039;&#039;&#039;game&#039;&#039;&#039; states and when you don&#039;t supply state args function - it is null.&lt;br /&gt;
This method is called when the active or multiactive player changes. In a classic &amp;quot;activePlayer&amp;quot; state this method is called before the onEnteringState state.&lt;br /&gt;
In multipleactiveplayer state it is a mess. The sequencing of calls depends on whether you get into that state from transitions OR from reloading the whole game (i.e. F5).&lt;br /&gt;
&lt;br /&gt;
See more details in [[Your_game_state_machine:_states.inc.php#Difference_between_Single_active_and_Multi_active_states]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Dojo framework ==&lt;br /&gt;
&lt;br /&gt;
BGA uses the [http://dojotoolkit.org/ Dojo Javascript framework].&lt;br /&gt;
&lt;br /&gt;
The Dojo framework allows us to do complex things more easily. The BGA framework uses Dojo extensively.&lt;br /&gt;
&lt;br /&gt;
To implement a game, you only need to use a few parts of the Dojo framework. All the Dojo methods you need are described on this page.&lt;br /&gt;
&lt;br /&gt;
== Javascript minimization (after July 2020) ==&lt;br /&gt;
&lt;br /&gt;
For performance reasons, when deploying a game the javascript code is minimized using &#039;&#039;&#039;terser&#039;&#039;&#039; (https://github.com/terser/terser). This minifier works with modern javascript syntax. From your project &amp;quot;Manage game&amp;quot; page, you can now test a minified version of your javascript on the studio (and revert to the original).&lt;br /&gt;
&lt;br /&gt;
NB: it has been reported that there is an issue with this minifier and percentage values for opacity.&lt;br /&gt;
&lt;br /&gt;
== Accessing Players Information ==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.player_id: number&#039;&#039;&#039;&lt;br /&gt;
id of the player who is looking at the game. The player may not be part of the game (i.e. spectator)&lt;br /&gt;
  if (notif.args.player_id == this.player_id) {&lt;br /&gt;
    ...&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.isSpectator: boolean&#039;&#039;&#039;&lt;br /&gt;
Flag set to true if the user at the table is a spectator (not a player).&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    if (this.isSpectator) {&lt;br /&gt;
        this.player_color = &#039;ffffff&#039;;&lt;br /&gt;
    } else {&lt;br /&gt;
        this.player_color = gamedatas.players[this.player_id].color;&lt;br /&gt;
    }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note: If you want to hide an element from spectators, you should use [[Game_interface_stylesheet:_yourgamename.css#spectatorMode|CSS &#039;spectatorMode&#039; class]].&lt;br /&gt;
&lt;br /&gt;
You may consider making a function like this, to detect if the game is in a read-only state (i.e. non-interactive):&lt;br /&gt;
  // Returns true for spectators, instant replay (during game), archive mode (after game end)&lt;br /&gt;
  isReadOnly: function () {&lt;br /&gt;
    return this.isSpectator || typeof g_replayFrom != &#039;undefined&#039; || g_archive_mode;&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.gamedatas: object&#039;&#039;&#039;&lt;br /&gt;
Contains the initial set of data to init the game, created at game start or by game refresh (F5).&lt;br /&gt;
You can update it as needed to keep an up-to-date reference of the game on the client side if you need it, however most of the time this is unnecessary.&lt;br /&gt;
&lt;br /&gt;
Note: In hotseat mode, the framework does not keep this.gamedatas of hotseat players and shares the same set as the main player to store data.&lt;br /&gt;
&lt;br /&gt;
Note: be careful when you update this data structurally, many framework functions expect data to be certain way and they will break if they see something else.&lt;br /&gt;
&lt;br /&gt;
Typical example of accessing player&#039;s info&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
for (var player_id in this.gamedatas.players) { &lt;br /&gt;
    var playerInfo = this.gamedatas.players [player_id];&lt;br /&gt;
    var c = playerInfo.color;&lt;br /&gt;
    var name = playerInfo.name;&lt;br /&gt;
    // do something &lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.isCurrentPlayerActive(): boolean&#039;&#039;&#039;&lt;br /&gt;
Returns true if the player on whose browser the code is running is currently active (it&#039;s his turn to play). Note: see remarks above about usage of this function inside onEnteringState method.&lt;br /&gt;
  if (this.isCurrentPlayerActive()) {&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.getActivePlayerId(): number&#039;&#039;&#039;&lt;br /&gt;
Return the ID of the active player, or null if we are not in an &amp;quot;activeplayer&amp;quot; type state.&lt;br /&gt;
  if (this.player_id == this.getActivePlayerId()) ...&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.getActivePlayers(): number[]&#039;&#039;&#039;&lt;br /&gt;
Return an array with the IDs of players who are currently active (or an empty array if there are none).&lt;br /&gt;
&lt;br /&gt;
== Accessing and manipulating the DOM ==&lt;br /&gt;
&lt;br /&gt;
=== Element by Id ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;$(elementId: ElementOrId)&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
The $ function is used to get an HTML element using its &amp;quot;id&amp;quot; attribute.&lt;br /&gt;
&lt;br /&gt;
Example: modify the content of a &amp;quot;span&amp;quot; element:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
In your HTML code:&lt;br /&gt;
   &amp;lt;span id=&amp;quot;a_value_in_the_game_interface&amp;quot;&amp;gt;1234&amp;lt;/span&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In your Javascript code:&lt;br /&gt;
   $(&#039;a_value_in_the_game_interface&#039;).innerHTML = &amp;quot;9999&amp;quot;;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Note: It is safe to use if you don&#039;t know if variable is string (id of element) or element itself, i.e. &lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  foo: function(card) {&lt;br /&gt;
       card = $(card); // now its node, no need to write if (typeof card === &#039;string&#039;) ...&lt;br /&gt;
       // but its good idea to check for null here&lt;br /&gt;
       ...&lt;br /&gt;
  }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;getElementById(elementId: string)&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Note: $() is the standard method to access some HTML element with the BGA Framework. You can use &#039;&#039;&#039;getElementById&#039;&#039;&#039; but a longer to type and less handy as it does not do some checks.&lt;br /&gt;
&lt;br /&gt;
=== Style ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;dojo.style(node: ElementOrId, styleName: string, styleValue: any): void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
With dojo.style you can modify the CSS property of any HTML element in your interface.&lt;br /&gt;
&lt;br /&gt;
Examples:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
     // Make an element disappear&lt;br /&gt;
     dojo.style( &#039;my_element&#039;, &#039;display&#039;, &#039;none&#039; );&lt;br /&gt;
&lt;br /&gt;
     // Give an element a 2px border&lt;br /&gt;
     dojo.style( &#039;my_element&#039;, &#039;borderWidth&#039;, &#039;2px&#039; );&lt;br /&gt;
&lt;br /&gt;
     // Change the background position of an element&lt;br /&gt;
     // (very practical when you are using CSS sprites to transform an element to another)&lt;br /&gt;
     dojo.style( &#039;my_element&#039;, &#039;backgroundPosition&#039;, &#039;-20px -50px&#039; );&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note: if you have to modify several CSS properties of an element, or if you have a complex CSS transformation to do, you should consider using dojo.addClass/dojo.removeClass (see below).&lt;br /&gt;
&lt;br /&gt;
You can also use object to set multiple values&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
dojo.setStyle(&amp;quot;thinger&amp;quot;, {&lt;br /&gt;
  &amp;quot;opacity&amp;quot;: 0.5,&lt;br /&gt;
  &amp;quot;border&amp;quot;: &amp;quot;3px solid black&amp;quot;,&lt;br /&gt;
  &amp;quot;height&amp;quot;: &amp;quot;300px&amp;quot;&lt;br /&gt;
});&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.addStyleToClass(cssClassName: string, styleName: string, styleValue: any):&#039;&#039;&#039; &#039;&#039;&#039;void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Same as dojo.style(), but for all the nodes set with the specified cssClassName&lt;br /&gt;
Equivalent of &lt;br /&gt;
  &lt;br /&gt;
  dojo.query(`.${aclass}`).style(styleName, styleValue)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
dojo.query(&amp;quot;#baz &amp;gt; div&amp;quot;).style({&lt;br /&gt;
  opacity:0.75,&lt;br /&gt;
  fontSize:&amp;quot;13pt&amp;quot;&lt;br /&gt;
});&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Vanilla JS style&#039;&#039;&#039;&lt;br /&gt;
  $(&#039;my_element&#039;).style.display=&#039;none&#039;; // set&lt;br /&gt;
  var display = $(&#039;my_element&#039;).style.display; // get&lt;br /&gt;
  $(&#039;my_element&#039;).style.removeProperty(&#039;display&#039;); // remove&lt;br /&gt;
&lt;br /&gt;
=== Classes ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;dojo.addClass(node: ElementOrId, classes: string): void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;dojo.removeClass(node: ElementOrId, classes: string): void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;dojo.hasClass(node: ElementOrId, aclass: string): void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;dojo.toggleClass(node: ElementOrId, aclass: string): void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
In many situations, many small CSS property updates can be replaced by a CSS class change (i.e., you add a CSS class to your element instead of applying all modifications manually).&lt;br /&gt;
&lt;br /&gt;
Advantages are:&lt;br /&gt;
* All your CSS stuff remains in your CSS file.&lt;br /&gt;
* You can add/remove a list of CSS modifications with a simple function and without error.&lt;br /&gt;
* You can test whether you applied the CSS to an element with the &#039;&#039;&#039;dojo.hasClass&#039;&#039;&#039; method.&lt;br /&gt;
&lt;br /&gt;
Example from &#039;&#039;Reversi&#039;&#039;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    // We add &amp;quot;possibleMove&amp;quot; to an element&lt;br /&gt;
    dojo.addClass( &#039;square_&#039;+x+&#039;_&#039;+y, &#039;possibleMove&#039; );&lt;br /&gt;
&lt;br /&gt;
    // In our CSS file, the class is defined as:&lt;br /&gt;
    .possibleMove {&lt;br /&gt;
      background-color: white;&lt;br /&gt;
      opacity: 0.2;&lt;br /&gt;
      filter:alpha(opacity=20); /* For IE8 and earlier */  &lt;br /&gt;
      cursor: pointer;  &lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
     // So we&#039;ve applied 4 CSS property changes in one line of code.&lt;br /&gt;
&lt;br /&gt;
     // ... and when we need to check if a square is a possible move on the client side:&lt;br /&gt;
     if( dojo.hasClass( &#039;square_&#039;+x+&#039;_&#039;+y, &#039;possibleMove&#039; ) )&lt;br /&gt;
     { ... }&lt;br /&gt;
&lt;br /&gt;
     // ... and if we want to remove all possible moves in one line of code (see &amp;quot;dojo.query&amp;quot; method):&lt;br /&gt;
     dojo.query( &#039;.possibleMove&#039; ).removeClass( &#039;possibleMove&#039; );&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Vanila JS classList&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
This is the only exception where dojo versions are better&lt;br /&gt;
  // add class&lt;br /&gt;
  $(token_id).classList.addClass(&#039;possibleMove&#039;);&lt;br /&gt;
  // remove class&lt;br /&gt;
  $(token_id).classList.removeClass(&#039;possibleMove&#039;);&lt;br /&gt;
  // add 2 classes&lt;br /&gt;
  const myclasses = [&#039;a&#039;,&#039;b&#039;];&lt;br /&gt;
  $(token_id).classList.addClass(...myclasses);&lt;br /&gt;
  // add classes to query result&lt;br /&gt;
  document.querySelectorAll(&amp;quot;.hand .card&amp;quot;).forEach((node)=&amp;gt;node.classList.addClass(&#039;possibleMove&#039;));&lt;br /&gt;
&lt;br /&gt;
=== Attributes ===&lt;br /&gt;
&lt;br /&gt;
;dojo.attr&lt;br /&gt;
&lt;br /&gt;
With dojo.attr you can access or change the value of an attribute or property of any HTML element in your interface.&lt;br /&gt;
&lt;br /&gt;
Exemple:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
     // Get the title of a node&lt;br /&gt;
     var title = dojo.attr( id, &#039;title&#039; );&lt;br /&gt;
     // Change the height of a node&lt;br /&gt;
     dojo.attr( &#039;img_growing_tree&#039;, &#039;height&#039;, 100 );&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Vanila JS attr&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
   $(token).id=new_id; // set attr for &amp;quot;id&amp;quot;&lt;br /&gt;
   var id = $(token).id; // get&lt;br /&gt;
&lt;br /&gt;
=== Queries ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;dojo.query(cssSelector: string): Element[]&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
With dojo.query, you can query a bunch of HTML elements with a single function, with a &amp;quot;CSS selector&amp;quot; style.&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
     // All elements with class &amp;quot;possibleMove&amp;quot;:&lt;br /&gt;
     var elements = dojo.query( &#039;.possibleMove&#039; );&lt;br /&gt;
&lt;br /&gt;
     // Count number of tokens (i.e., elements of class &amp;quot;token&amp;quot;) on the board (i.e., the element with id &amp;quot;board&amp;quot;):&lt;br /&gt;
     dojo.query( &#039;#board .token&#039; ).length;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
But what is really cool with dojo.query is that you can combine it with almost all methods above.&lt;br /&gt;
&lt;br /&gt;
Examples:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
     // Trigger a method when the mouse enter in any element with class &amp;quot;meeple&amp;quot;:&lt;br /&gt;
     dojo.query( &#039;.meeple&#039; ).connect( &#039;onmouseenter&#039;, this, &#039;myMethodToTrigger&#039; );&lt;br /&gt;
&lt;br /&gt;
     // Hide all meeples who are on the board&lt;br /&gt;
     dojo.query( &#039;#board .meeple&#039; ).style( &#039;display&#039;, &#039;none&#039; );&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Vanila JS query&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
  var cards=document.querySelectorAll(&amp;quot;.hand .card&amp;quot;);// all cards in all hands&lt;br /&gt;
  var cards=$(&#039;hand&#039;).querySelectorAll(&amp;quot;.card&amp;quot;);// all cards in specific hand&lt;br /&gt;
  var card=document.querySelector(&amp;quot;.hand .card&amp;quot;);// first card or null if none (super handy)&lt;br /&gt;
&lt;br /&gt;
=== Creating and Destroying elements ===&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;dojo.empty(node: ElementOrId)&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Remove all children of the node element&lt;br /&gt;
   dojo.empty(&#039;my_hand&#039;);&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;dojo.destroy(node: ElementOrId)&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Remove the element&lt;br /&gt;
   dojo.destroy(&#039;my_token&#039;);&lt;br /&gt;
&lt;br /&gt;
   dojo.query(&amp;quot;.green&amp;quot;, mynode).forEach(dojo.destroy); // this remove all subnode of class green from mynode&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;dojo.create(tag: string, attributes?: obj, parent?: ElementOrId): Element&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Create element&lt;br /&gt;
&lt;br /&gt;
    dojo.create(&amp;quot;div&amp;quot;, { class: &amp;quot;yellow_arrow&amp;quot; }, parent); // this creates div with class yellow_array and places it in &amp;quot;parent&amp;quot;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.format_block(name: string, args: object): string&#039;&#039;&#039;&lt;br /&gt;
This bga function that takes global var from template file and substitute variables, typical use would be&lt;br /&gt;
&lt;br /&gt;
                var player = gamedatas.players[player_id];&lt;br /&gt;
                var div = this.format_block(&#039;jstpl_player_board&#039;, player ); // var jstpl_player_board = ... is defined in .tpl file &lt;br /&gt;
Note: result is trimmed&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.format_string(name: string, args: object): string&#039;&#039;&#039;&lt;br /&gt;
This bga function just substitute variables in a string, i.e.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
     var div = this.format_string(&#039;&amp;lt;div color=&amp;quot;${player_color}&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&#039;, {player_color: &#039;#ff0000&#039;} );&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Note: result is trimmed&lt;br /&gt;
&lt;br /&gt;
Note: this can be replaced by using backquoted string now: &lt;br /&gt;
     const player_color =  &#039;#ff0000&#039;;&lt;br /&gt;
     const div = `&amp;lt;div color=&amp;quot;${player_color}&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;`;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.format_string_recursive&#039;&#039;&#039;&lt;br /&gt;
This bga function is similar to this.format_string but is capable of processing recursive argument structures and translations. It is used to format server notifications.&lt;br /&gt;
&lt;br /&gt;
TODO: find better place for these function docs&lt;br /&gt;
&lt;br /&gt;
=== Moving elements ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;dojo.place(node: string | Element, refNode: ElementOrId, pos?: string | number): Element&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
dojo.place is the best function to insert HTML code somewhere in your game interface without breaking something. It is much better to use than the &#039;&#039;&#039;innerHTML=&#039;&#039;&#039; method if you must insert HTML tags and not only values.&lt;br /&gt;
&lt;br /&gt;
node: &lt;br /&gt;
&lt;br /&gt;
Can be a String or a DOM node. If it is a string starting with “&amp;lt;”, it is assumed to be an HTML fragment, which will be created. Otherwise it is assumed to be an id of a DOM node.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
     // Insert your HTML code as a child of a container element&lt;br /&gt;
     dojo.place( &amp;quot;&amp;lt;div class=&#039;foo&#039;&amp;gt;&amp;lt;/div&amp;gt;&amp;quot;, &amp;quot;your_container_element_id&amp;quot; );&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
pos:&lt;br /&gt;
&lt;br /&gt;
Optional argument. Can be a number or one of the following strings: “before”, “after”, “replace”, “only”, “first”, or “last”. If omitted, “last” is assumed. &lt;br /&gt;
&lt;br /&gt;
&amp;quot;replace&amp;quot;: Replace the container element with my_node element&lt;br /&gt;
&lt;br /&gt;
&amp;quot;first&amp;quot;: Places the node as a child of the reference node. The node is placed as the first child.&lt;br /&gt;
&lt;br /&gt;
&amp;quot;last&amp;quot; (default): Places the node as a child of the reference node. The node is placed as the last child.&lt;br /&gt;
&lt;br /&gt;
&amp;quot;before&amp;quot;: places the node right before the reference node.&lt;br /&gt;
&lt;br /&gt;
&amp;quot;after&amp;quot;: places the node right after the reference node.&lt;br /&gt;
&lt;br /&gt;
&amp;quot;only&amp;quot;: replaces all children of the reference node with the node.&lt;br /&gt;
&lt;br /&gt;
positive integer: This parameter can be a positive integer. In this case, the node will be placed as a child of the reference node with this number (counting from 0). If the number is more than number of children, the node will be appended to the reference node making it the last child. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
     // Replace all children of container with my_node &lt;br /&gt;
     dojo.place( $(&#039;my_node&#039;), &amp;quot;your_container_element_id&amp;quot;, &amp;quot;only&amp;quot; );&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
See also full doc on dojo.place: [https://dojotoolkit.org/reference-guide/1.7/dojo/place.html]&lt;br /&gt;
&lt;br /&gt;
Usually, when you want to insert some piece of HTML in your game interface, you should use &amp;quot;[[Game_layout:_view_and_template:_yourgamename.view.php_and_yourgamename_yourgamename.tpl#Javascript_templates|Javascript templates]]&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
But you can also relocate elements like that. Note: it won&#039;t animate if you do that.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.placeOnObject(mobile_obj: ElementOrId, target_obj: ElementOrId): void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
places mobile_obj on target_obj, set the absolute positions and centers the mobile_obj on target_obj,&lt;br /&gt;
effect is immediate&lt;br /&gt;
&lt;br /&gt;
This is not really an animation, but placeOnObject is frequently used before starting an animation.&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  // (We just created an object &amp;quot;my_new_token&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
  // Place the new token on current player board&lt;br /&gt;
  this.placeOnObject( &amp;quot;my_new_token&amp;quot;, &amp;quot;overall_player_board_&amp;quot;+this.player_id );&lt;br /&gt;
  &lt;br /&gt;
  // Then slide it to its position on the board&lt;br /&gt;
  this.slideToObject( &amp;quot;my_new_token&amp;quot;, &amp;quot;a_place_on_board&amp;quot; ).play();&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.placeOnObjectPos(mobile_obj: ElementOrId, target_obj: ElementOrId, target_x: number, target_y: number): void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
This method works exactly like placeOnObject, except than you can specify some (x,y) coordinates (in px). This way, the center of &amp;quot;mobile_obj&amp;quot; will be placed to the specified x,y position relatively to the center of &amp;quot;target_obj&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Note: the placement works differently from this.slideToObjectPos&#039;&#039;, since coordinates are calculated based on the center of objects.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.attachToNewParent(mobile_obj: ElementOrId, target_obj: ElementOrId): void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
With this method, you change the HTML parent of &amp;quot;mobile_obj&amp;quot; element without moving it. &lt;br /&gt;
&amp;quot;target_obj&amp;quot; is the new parent of this element. The beauty of &lt;br /&gt;
attachToNewParent is that the mobile_obj element DOES NOT MOVE during this process.&lt;br /&gt;
&lt;br /&gt;
What happens is that the method calculate a relative position of mobile_obj to make sure it does not move after the HTML parent changes.&lt;br /&gt;
&lt;br /&gt;
Why using this method?&lt;br /&gt;
&lt;br /&gt;
Changing the HTML parent of an element can be useful for the following reasons:&lt;br /&gt;
* When the HTML parent moves, all its child are moving with them. If some game elements is no more linked with a parent HTML object, you may want to attach it to another place.&lt;br /&gt;
* The z_order (vertical order of display) depends on the position in the DOM, so you may need to change the parent of some game elements when they are moving in your game area.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;CAREFUL&#039;&#039;&#039;: this function destroys original object and places a clone onto a new parent, this will break all references to this HTML element (ex: dojo.connect).&lt;br /&gt;
If you need version that does not destroy the object but the same otherwise see [[BGA_Studio_Cookbook#Attach_to_new_parent_without_destroying_the_object]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Animations ==&lt;br /&gt;
&lt;br /&gt;
===Dojo Animations===&lt;br /&gt;
&lt;br /&gt;
BGA animations is based on Dojo Animation ([http://dojotoolkit.org/documentation/tutorials/1.8/animation/ see tutorial here]).&lt;br /&gt;
&lt;br /&gt;
However, most of the time, you can just use methods below, which are built on top of Dojo Animation.&lt;br /&gt;
&lt;br /&gt;
Note: one interesting method from Dojo that could be useful from time to time is &amp;quot;Dojo.Animation&amp;quot;. It allows you to make any CSS property &amp;quot;slide&amp;quot; from one value to another.&lt;br /&gt;
&lt;br /&gt;
Note 2: the slideTo methods are not compatible with CSS transform (scale, zoom, rotate...). If possible, avoid using CSS transform on nodes that are being slided. Eventually, the only possible solution to make these 2 compatible is to disable all CSS transform properties, use slideToObjectPos/placeOnObjectPos, and then apply them again.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Sliding===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.slideToObject(mobile_obj: ElementOrId, target_obj: ElementOrId, duration?: number, delay?: number): Animation&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
You can use slideToObject to &amp;quot;slide&amp;quot; an element to a target position.&lt;br /&gt;
&lt;br /&gt;
Sliding element on the game area is the recommended and the most used way to animate your game interface. Using slides allow players to figure out what is happening on the game, as if they were playing with the real boardgame.&lt;br /&gt;
&lt;br /&gt;
The parameters are:&lt;br /&gt;
* mobile_obj: the ID of the object to move. This object must be &amp;quot;relative&amp;quot; or &amp;quot;absolute&amp;quot; positioned.&lt;br /&gt;
* target_obj: the ID of the target object. This object must be &amp;quot;relative&amp;quot; or &amp;quot;absolute&amp;quot; positioned. Note that it is not mandatory that mobile_obj and target_obj have the same size. If their size are different, the system slides the center of mobile_obj to the center of target_obj.&lt;br /&gt;
* duration: (optional) defines the duration in millisecond of the slide. The default is 500 milliseconds.&lt;br /&gt;
* delay: (optional). If you defines a delay, the slide will start only after this delay. This is particularly useful when you want to slide several object from the same position to the same position: you can give a 0ms delay to the first object, a 100ms delay to the second one, a 200ms delay to the third one, ... this way they won&#039;t be superposed during the slide.&lt;br /&gt;
&lt;br /&gt;
BE CAREFUL: The method returns an dojo.fx animation, so you can combine it with other animation if you want to. It means that you have to call the &amp;quot;play()&amp;quot; method, otherwise the animation WON&#039;T START.&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
   this.slideToObject( &amp;quot;some_token&amp;quot;, &amp;quot;some_place_on_board&amp;quot; ).play();&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.slideToObjectPos(mobile_obj: ElementOrId, target_obj: ElementOrId, target_x: number, target_y: number, duration?: number, delay?: number): Animation&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
This method does exactly the same as &amp;quot;slideToObject&amp;quot;, except than you can specify some (x,y) coordinates. This way, &amp;quot;mobile_obj&amp;quot; will slide to the specified x,y position relatively to &amp;quot;target_obj&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
Example: slide a token to some place on the board, 10 pixels from the top:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
   this.slideToObjectPos( &amp;quot;some_token&amp;quot;, &amp;quot;some_place_on_board&amp;quot;, 0, 10 ).play();&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.slideTemporaryObject(mobile_obj_html: string, parent: ElementOrId, from: ElementOrId, to: ElementOrId, duration?: number, delay?: number): Animation&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
This method is useful when you want to slide a temporary HTML object from one place to another. As this object does not exists before the animation and won&#039;t remain after, it could be complex to create this object (with dojo.place), to place it at its origin (with placeOnObject) to slide it (with slideToObject) and to make it disappear at the end.&lt;br /&gt;
&lt;br /&gt;
slideTemporaryObject does all of this for you:&lt;br /&gt;
* mobile_obj_html is a piece of HTML code that represent the object to slide.&lt;br /&gt;
* parent is the ID of an HTML element of your interface that will be the parent of this temporary HTML object.&lt;br /&gt;
* from is the ID of the origin of the slide.&lt;br /&gt;
* to is the ID of the target of the slide.&lt;br /&gt;
* duration/delay works exactly like in &amp;quot;slideToObject&amp;quot;&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
this.slideTemporaryObject( &#039;&amp;lt;div class=&amp;quot;token_icon&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&#039;, &#039;tokens&#039;, &#039;my_origin_div&#039;, &#039;my_target_div&#039; ).play();&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Destroy===&lt;br /&gt;
&#039;&#039;&#039;this.slideToObjectAndDestroy(mobile_obj: ElementOrId, target_obj: ElementOrId, duration?: number, delay?: number): void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
This method is a handy shortcut to slide an existing HTML object to some place then destroy it upon arrival. It can be used for example to move a victory token or a card from the board to the player panel to show that the player earns it, then destroy it when we don&#039;t need to keep it visible on the player panel.&lt;br /&gt;
&lt;br /&gt;
It works the same as this.slideToObject and takes the same arguments, but it starts the animation. &lt;br /&gt;
&lt;br /&gt;
CAREFUL: Make sure nothing is creating the same object at the same time the animation is running, because this will cause some random disappearing effects&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
this.slideToObjectAndDestroy( &amp;quot;some_token&amp;quot;, &amp;quot;some_place_on_board&amp;quot;, 1000, 0 );&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.fadeOutAndDestroy( node: string | Element, duration?: number, delay?: number):&#039;&#039;&#039; &#039;&#039;&#039;void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
This function fade out the target node, then destroy it. Its starts the animation.&lt;br /&gt;
* duration/delay works exactly like in &amp;quot;slideToObject&amp;quot;&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
   this.fadeOutAndDestroy( &amp;quot;a_card_that_must_disappear&amp;quot; );&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
CAREFUL: the HTML node still exists until during few milliseconds, until the fadeOut has been completed.&lt;br /&gt;
Make sure nothing is creating same object at the same time as animation is running, because you will be some random dissapearing effects&lt;br /&gt;
&lt;br /&gt;
===Rotating elements===&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
This example combines &amp;quot;Dojo.Animation&amp;quot; method and a CSS property transform that allow you to rotate the element.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
// node is Element we rotating&lt;br /&gt;
		    var animation = new dojo.Animation({&lt;br /&gt;
			    curve: [fromDegree, toDegree],&lt;br /&gt;
			    onAnimate: (v) =&amp;gt; {&lt;br /&gt;
				    node.style.transform = &#039;rotate(&#039; + v + &#039;deg)&#039;;&lt;br /&gt;
			    } &lt;br /&gt;
		    });&lt;br /&gt;
		    &lt;br /&gt;
		    animation.play();  &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
BGA has its own interface to rotate&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.rotateTo(node: string | Element, degree: number): void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
It starts the animation, and stored the rotation degree in the class, so next time you rotate object - it is additive.&lt;br /&gt;
There is no animation hooks in this one, if you need to change any parameters use dojo animation above.&lt;br /&gt;
&lt;br /&gt;
There is also &#039;&#039;&#039;rotateInstantTo&#039;&#039;&#039; with same signature which does not animate&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Animation Callbacks===&lt;br /&gt;
&lt;br /&gt;
If you wish to run some code only after an animation has completed you can do this by linking a callback method to &#039;onEnd&#039;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
var animation_id = this.slideToObject( mobile_obj, target_obj, 500 );&lt;br /&gt;
dojo.connect(animation_id, &#039;onEnd&#039;, () =&amp;gt; {&lt;br /&gt;
   // do something here&lt;br /&gt;
});&lt;br /&gt;
animation_id.play();&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If you wish to call a second animation after the first (rather than general code) then you can use a dojo animation chain (see tutorial referenced above).&lt;br /&gt;
&lt;br /&gt;
== Players input ==&lt;br /&gt;
&lt;br /&gt;
=== Connecting ===&lt;br /&gt;
&#039;&#039;&#039;dojo.connect(element: Element, event: string, context: object, method: eventHandler): any&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;dojo.connect(element: Element, event: string, hander: eventHandler): any&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Used to associate a player event with one of your notification methods.&lt;br /&gt;
&lt;br /&gt;
Example: associate a click on an element (&amp;quot;my_element&amp;quot;) with one of our methods (&amp;quot;onClickOnMyElement&amp;quot;):&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
      dojo.connect( $(&#039;my_element&#039;), &#039;onclick&#039;, this, &#039;onClickOnMyElement&#039; );&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Same idea but base on query (i.e. all element of &#039;pet&#039; class)&lt;br /&gt;
      dojo.query(&amp;quot;.pet&amp;quot;).connect(&#039;onclick&#039;, this, &#039;onPet&#039;);&lt;br /&gt;
&lt;br /&gt;
Note: if you need to disconnect the handler you have to store handler returned from this method, i.e.&lt;br /&gt;
   &lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    var handler = dojo.connect(...);&lt;br /&gt;
    ...&lt;br /&gt;
    dojo.disconnect(handler);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If you don&#039;t store the handler - you have to destroy the object to disconnect it&lt;br /&gt;
&lt;br /&gt;
Typical function that implements the input handler will look like this&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
onPet: function(event) {&lt;br /&gt;
    var id = event.currentTarget.id;&lt;br /&gt;
    console.log(&#039;onPet &#039; + id);&lt;br /&gt;
    dojo.stopEvent(event);&lt;br /&gt;
    if (this.gamedatas.gamestate.name == &#039;playerTurnPet&#039;) {&lt;br /&gt;
          this.bgaPerformAction(&#039;actPlayPet&#039;, {card: id});&lt;br /&gt;
    } else {&lt;br /&gt;
          this.showMoveUnauthorized();&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.connect(element: ElementOrId, event: string, method: eventHandler): void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Used to associate a player event with one of your notification methods.&lt;br /&gt;
&lt;br /&gt;
      this.connect( $(&#039;my_element&#039;), &#039;onclick&#039;, &#039;onClickOnMyElement&#039; );&lt;br /&gt;
&lt;br /&gt;
Or you can use an in-place handler&lt;br /&gt;
&lt;br /&gt;
      this.connect( $(&#039;my_element&#039;), &#039;onclick&#039;, (e) =&amp;gt; { console.log(&#039;boo&#039;); } );&lt;br /&gt;
&lt;br /&gt;
Note that this function stores the connection handler. That is the only real difference between &#039;&#039;&#039;this.connect&#039;&#039;&#039; and &#039;&#039;&#039;dojo.connect&#039;&#039;&#039;. If you plan to destroy the element you connected, you &#039;&#039;&#039;must&#039;&#039;&#039; call this.disconnect() to prevent memory leaks.&lt;br /&gt;
This function is mainly for permanent objects - if you just want to connect the temp object you should probably not use this method but use dojo.connect which won&#039;t require any clean-up.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.connectClass(cssClassName: string, event: string, method: eventHandler): void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Same as connect(), but for all the nodes set with the specified cssClassName.&lt;br /&gt;
&lt;br /&gt;
	this.connectClass(&#039;pet&#039;, &#039;onclick&#039;, &#039;onPet&#039;);&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.disconnect(element: ElementOrId, event: string): void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Disconnect event handler (previously registered with this.connect or this.connectClass).&lt;br /&gt;
&lt;br /&gt;
   this.disconnect( $(&#039;my_element&#039;), &#039;onclick&#039;);&lt;br /&gt;
&lt;br /&gt;
Note: dynamic connect/disconnect is for advanced cases ONLY, you should always connect elements statically if possible, i.e. in setup() method.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.disconnectAll(): void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Disconnect all previously registed event handlers (registered via this.connect or this.connectClass)&lt;br /&gt;
&lt;br /&gt;
  this.disconnectAll();&lt;br /&gt;
&lt;br /&gt;
=== Actions ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.bgaPerformAction(action: string, args?: object, options: object = { lock: true, checkAction: true }): Promise&amp;lt;void&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Triggers an action on the backend. This is a combination of checkAction and ajaxcall, returning a Promise which resoves when ajaxcall ends.&lt;br /&gt;
&lt;br /&gt;
This method must be used to send a player input to the game server. &#039;&#039;&#039;It should not be triggered programmatically&#039;&#039;&#039;, especially not in loops, in callbacks, in notifications, or in onEnteringState/onUpdateActionButtons/onLeavingState, in order not to create race conditions or break replay game and tutorial features. It should be used only in reaction to a user action in the interface.&lt;br /&gt;
&lt;br /&gt;
* action: name of the action, as it is written in &amp;quot;possibleactions&amp;quot; of the current state.&lt;br /&gt;
* args: an object containing the call parameters to send to the action&lt;br /&gt;
* options: options to tweak the call with some defaults. Default is &amp;lt;code&amp;gt;{ lock: true, checkAction: true }&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Example of a standard call without args:&lt;br /&gt;
  this.bgaPerformAction(&#039;pass&#039;);&lt;br /&gt;
&lt;br /&gt;
Example of a standard call with action args:&lt;br /&gt;
  this.bgaPerformAction(&#039;actPlayCard&#039;, { id: this.selectedCardId });&lt;br /&gt;
&lt;br /&gt;
Example of a call without checking action (because player is inactive in a multiactive state):&lt;br /&gt;
&lt;br /&gt;
 this.bgaPerformAction(&#039;actChangeMind&#039;, {}, { checkAction: false });&lt;br /&gt;
&lt;br /&gt;
Example of a call without lock (because of a special action not directly related to the game flow):&lt;br /&gt;
&lt;br /&gt;
 this.bgaPerformAction(&#039;actSetAutoBid&#039;, { alwaysBidUntil: 500 }, { lock: false, checkAction: false });&lt;br /&gt;
&lt;br /&gt;
Example of call with reaction to exception:&lt;br /&gt;
  this.bgaPerformAction(&#039;actPlayCard&#039;, { id: this.selectedCardId }).catch(()=&amp;gt;{ this.selectedCardId = undefined; });&lt;br /&gt;
&lt;br /&gt;
Example of call with reaction to success:&lt;br /&gt;
  this.bgaPerformAction(&#039;actPlayCard&#039;, { id: this.selectedCardId }).then(()=&amp;gt;{ this.unselectAll(); });&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.ajaxcall(url, parameters, obj_callback, callback, callback_anycase?, ajax_method?: string)&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Note: bgaPerformAction is a simpler way to use ajax calls, ajaxcall stays in the doc for legacy reasons only and should not be used in new projects.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Same warning as &#039;&#039;&#039;this.bgaPerformAction&#039;&#039;&#039; about using on user action only.&lt;br /&gt;
&lt;br /&gt;
* url: the url of the action to perform. For a game, it must be: &amp;quot;/&amp;lt;mygame&amp;gt;/&amp;lt;mygame&amp;gt;/myAction.html&amp;quot;&lt;br /&gt;
* parameters: an array of parameter to send to the game server. &lt;br /&gt;
** Note that &amp;quot;lock: true&amp;quot; must always be specified in this list of parameters in order the interface can be locked during the server call. Cannot use lock: false - to not lock it has to be undefined.&lt;br /&gt;
** Note: Restricted parameter names (please don&#039;t use them):&lt;br /&gt;
*** &amp;quot;action&amp;quot;&lt;br /&gt;
*** &amp;quot;module&amp;quot;&lt;br /&gt;
*** &amp;quot;class&amp;quot;&lt;br /&gt;
* obj_callback: must be set to &amp;quot;this&amp;quot;.&lt;br /&gt;
* callback (non-optional but rarely used): a function to trigger when the server returns result and everything went fine (not used, as all data handling is done via notifications).&lt;br /&gt;
* callback_anycase: (optional) a function to trigger when the server returns ok OR error.  If no error this function is called with parameter value false. If an error occurred, the first parameter will be set to true, the second will contain the error message sent by the PHP back-end, and the third will contain an error code.&lt;br /&gt;
* ajax_method: (optional and rarely used) if you need to send large amounts of data (over 2048 bytes), you can set this parameter to &#039;post&#039; (all lower-case) to send a POST request as opposed to the default GET. This works, but was not officially documented, so only use if you really need to.&lt;br /&gt;
&lt;br /&gt;
Usage:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
this.ajaxcall( &#039;/mygame/mygame/actMyAction.html&#039;, { lock: true, &lt;br /&gt;
   arg1: myarg1, &lt;br /&gt;
   arg2: myarg2&lt;br /&gt;
}, this, (result)=&amp;gt;{} );&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.checkAction(action: string, nomessage?: boolean): boolean &#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Check if player can do the specified action by taking into account:&lt;br /&gt;
* if interface is locked it will return false and show message &amp;quot;An action is already in progress&amp;quot;,  unless nomessage set to true &lt;br /&gt;
* if player is not active it will return false and show message &amp;quot;This is not your turn&amp;quot;, unless nomessage set to true &lt;br /&gt;
* if action is not in list in possible actions (defined by &amp;quot;possibleaction&amp;quot; in current game state) it will return false and show &amp;quot;This move is not authorized now&amp;quot; error (unconditionally).&lt;br /&gt;
* otherwise returns true&lt;br /&gt;
Example:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  function onClickOnGameElement( evt )  {&lt;br /&gt;
     if( this.checkAction( &amp;quot;actMyAction&amp;quot; ) ) {&lt;br /&gt;
        // Do the action&lt;br /&gt;
     }&lt;br /&gt;
  }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.checkPossibleActions(action: string): boolean&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
* this is independent of the player being active, so can be used instead of this.checkAction(). This is particularly useful for multiplayer states when the player is not active in a &#039;player may like to change their mind&#039; scenario. Unlike this.checkAction, this function does NOT take interface locking into account &lt;br /&gt;
&lt;br /&gt;
* if action is not in list in possible actions (defined by &amp;quot;possibleaction&amp;quot; in current game state) it will return false and show &amp;quot;This move is not authorized now&amp;quot; error (unconditionally).&lt;br /&gt;
* otherwise returns true&lt;br /&gt;
&lt;br /&gt;
  function onChangeMyMind( evt )  {&lt;br /&gt;
     if( this.checkPossibleActions( &amp;quot;actMyAction&amp;quot; ) ) {&lt;br /&gt;
        // Do the action&lt;br /&gt;
     }&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.checkLock(nomessage?: boolean): boolean&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
When using &amp;quot;lock: true&amp;quot; in ajax call you can use this function to check if interface is in lock state (it will be locked during server call and notification processing).&lt;br /&gt;
This check can be used to block some other interactions which do not result in ajaxcall or if you want to suppress errors. Note: normally you only need to use this.checkAction(...), this is for advanced cases.&lt;br /&gt;
&lt;br /&gt;
It will also show error unless nomessage is set to true&lt;br /&gt;
&lt;br /&gt;
  function onChangeMyMind( evt )  {&lt;br /&gt;
     if( this.checkLock() ) {&lt;br /&gt;
        // Do the action&lt;br /&gt;
     }&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
== Notifications ==&lt;br /&gt;
&lt;br /&gt;
When something happens on the server side, your game interface Javascript logic received a notification.&lt;br /&gt;
If you have not done so yet check what notification are in [[Main_game_logic:_yourgamename.game.php#Notifications]]&lt;br /&gt;
&lt;br /&gt;
Here&#039;s how you can handle these notifications on the client side.&lt;br /&gt;
&lt;br /&gt;
=== Subscribe to notifications ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;dojo.subscribe(notif_type: string, callback_obj: Object, handler: string|handler)&#039;&#039;&#039;&lt;br /&gt;
* notif_type - notification type/name send by php server&lt;br /&gt;
* callback_obj - usually this&lt;br /&gt;
* handler - if string method of callback_obj with name name is called, when notification is called, with notification object as parameter (see below)&lt;br /&gt;
&lt;br /&gt;
Your Javascript &amp;quot;setupNotifications&amp;quot; method is the place where you can subscribe to notifications from your PHP code.&lt;br /&gt;
&lt;br /&gt;
Here&#039;s how you associate one of your Javascript method to a notification &amp;quot;playDisc&amp;quot; (from Reversi example):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
   setupNotifications: function() {&lt;br /&gt;
      ...&lt;br /&gt;
      dojo.subscribe(&#039;playDisc&#039;, this, &amp;quot;notif_playDisc&amp;quot;);&lt;br /&gt;
   },&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note: the &amp;quot;playDisc&amp;quot; corresponds to the name of the notification you define it in your PHP code, in your &amp;quot;notifyAllPlayers&amp;quot; or &amp;quot;notifyPlayer&amp;quot; method.&lt;br /&gt;
&lt;br /&gt;
Then, you have to define your &amp;quot;notif_playDisc&amp;quot; method:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
   notif_playDisc: function(notif) {&lt;br /&gt;
     // Remove current possible moves (makes the board more clear)&lt;br /&gt;
     dojo.query( &#039;.possibleMove&#039; ).removeClass( &#039;possibleMove&#039; );          &lt;br /&gt;
     this.addDiscOnBoard( notif.args.x, notif.args.y, notif.args.player_id );&lt;br /&gt;
   },&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In a notification handler like our &amp;quot;notif_playDisc&amp;quot; method, you can access all notifications arguments with &amp;quot;notif.args&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&lt;br /&gt;
PHP&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    $this-&amp;gt;notifyAllPlayers( &amp;quot;apples&amp;quot;, clienttranslate(&#039;player takes ${count} apples&#039;), [ &amp;quot;count&amp;quot; =&amp;gt; 3 ] );&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
JavaScript&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    setupNotifications: function() {&lt;br /&gt;
       dojo.subscribe( &#039;apples&#039;, this, &#039;notif_apples&#039; );&lt;br /&gt;
    },&lt;br /&gt;
&lt;br /&gt;
    notif_apples: function(notif) {&lt;br /&gt;
      //You can access the &amp;quot;count&amp;quot; like this:&lt;br /&gt;
       alert(&amp;quot;count = &amp;quot; + notif.args.count);&lt;br /&gt;
    }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== The notification Object received by client ===&lt;br /&gt;
&lt;br /&gt;
When sending a notification on your PHP, the client side will receive an Object with the following attributes:&lt;br /&gt;
&lt;br /&gt;
* type - type of the notification (as passed by php function)&lt;br /&gt;
* log - the log string passed from php notification&lt;br /&gt;
* args - This is the arguments that you passed on your notification method on php&lt;br /&gt;
* bIsTableMsg - is true when you use [[Main_game_logic:_yourgamename.game.php#NotifyAllPlayers|NotifyAllPlayers]] method (false otherwise)&lt;br /&gt;
* channelorig - information about table ID (formatted as : &amp;quot;/table/t[TABLE_NUMBER]&amp;quot;)&lt;br /&gt;
* gamenameorig - name of the game&lt;br /&gt;
* move_id - ID of the move associated with the notification&lt;br /&gt;
* table_id - ID of the table (comes as string)&lt;br /&gt;
* time - UNIX GMT timestamp&lt;br /&gt;
* uid - unique identifier of the notification&lt;br /&gt;
* h - unknown&lt;br /&gt;
&lt;br /&gt;
&#039;&#039; Note that those information were inferred from observation on console log. If an Admin can confirm/correct (and remove this line), you&#039;re welcome :)&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
=== Ignoring notifications ===&lt;br /&gt;
&lt;br /&gt;
Sometimes you need to ignore some notification on client side. You don&#039;t want them to be shown in game log and you don&#039;t want them to be handled.&lt;br /&gt;
&lt;br /&gt;
The most common use case is when a player gets private information. They will receive a specific notification (such as &amp;quot;You received Ace of Heart&amp;quot;), while other players would receive more generic notification (&amp;quot;Player received a card&amp;quot;).&lt;br /&gt;
&lt;br /&gt;
In X.game.php&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        $this-&amp;gt;notifyAllPlayers(&amp;quot;dealCard&amp;quot;, clienttranslate(&#039;${player_name} received a card&#039;), [&lt;br /&gt;
            &#039;player_id&#039; =&amp;gt; $playerId,&lt;br /&gt;
            &#039;player_name&#039; =&amp;gt; $this-&amp;gt;getActivePlayerName()&lt;br /&gt;
        ]);&lt;br /&gt;
&lt;br /&gt;
        $this-&amp;gt;notifyPlayer($playerId, &amp;quot;dealCardPrivate&amp;quot;, clienttranslate(&#039;You received ${cardName}&#039;), [&lt;br /&gt;
            &amp;quot;type&amp;quot; =&amp;gt; $card[&amp;quot;type&amp;quot;],&lt;br /&gt;
            &amp;quot;cardName&amp;quot; =&amp;gt; $this-&amp;gt;getCardName($card[&amp;quot;type&amp;quot;])&lt;br /&gt;
        ]);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The problem with this approach is that the active player will receive two notifications:&lt;br /&gt;
* Player1 received a card&lt;br /&gt;
* You received Ace of Hearts&lt;br /&gt;
&lt;br /&gt;
Hence, notification ignoring.&lt;br /&gt;
&lt;br /&gt;
NOTE: You can think that it would be possible to send such notification to all players except active just by using notifyPlayer and it seems to work. The problem however is that table spectators would miss such notification and their user interface (and game log) wouldn&#039;t be updated. Since there is no way to send notification just to spectators, ignoring the notification (or &amp;quot;filtering&amp;quot;) is the only reasonable solution.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;setIgnoreNotificationCheck(notif_type: string, predicate: ((notif: Notif)=&amp;gt;boolean))&#039;&#039;&#039;&lt;br /&gt;
This method will set a check whether any of notifications of specific type should be ignored.&lt;br /&gt;
&lt;br /&gt;
The parameters are:&lt;br /&gt;
* notif_type: type of the notification &lt;br /&gt;
* predicate (notif =&amp;gt; boolean): a function that will receive notif object and will return true if this specific notification should be ignored&lt;br /&gt;
&lt;br /&gt;
Before dispatching any notification of this type, the framework will call predicate to check whether notification should be ignored, if it return true - the notification will be dispatched, i.e. logged or handled.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    this.notifqueue.setIgnoreNotificationCheck( &#039;dealCard&#039;, (notif) =&amp;gt; (notif.args.player_id == this.player_id) );&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
IMPORTANT: Remember that this notification is ignored on the client side, but was still received by the client. Therefore it shouldn&#039;t contain any private information as cheaters can get it. In other words this is not a way to hide information.&lt;br /&gt;
&lt;br /&gt;
IMPORTANT: When a game is reloaded with F5 or when opening a turn based game, old notifications are replayed as history notification. They are used just to update the game log and are stripped of all arguments except player_id, i18n and any argument present in message. If you use and other argument in your predicate you should &#039;&#039;&#039;preserve&#039;&#039;&#039; it as explained [[Main_game_logic:_yourgamename.game.php#Notify_players|here]].&lt;br /&gt;
&lt;br /&gt;
=== Synchronous notifications ===&lt;br /&gt;
&lt;br /&gt;
When several notifications are received by your game interface, these notifications are processed immediately, one after the other, in the same exact order they have been generated in your PHP game logic.&lt;br /&gt;
&lt;br /&gt;
However, sometimes, you need to give some time to the players to figure out what happened on the game before jumping to the next notification. Indeed, in many games, there are a lot of automatic actions, and the computer is going to resolve all these actions very fast if you don&#039;t tell it not to do so.&lt;br /&gt;
&lt;br /&gt;
As an example, for Reversi, when someone is playing a disc, we want to wait 500 milliseconds before doing anything else in order the opponent player can figure out what move has been played.&lt;br /&gt;
&lt;br /&gt;
Here&#039;s how we do this, right after our subscription:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    dojo.subscribe( &#039;playDisc&#039;, this, &amp;quot;notif_playDisc&amp;quot; );&lt;br /&gt;
    this.notifqueue.setSynchronous( &#039;playDisc&#039;, 500 );   // Wait 500 milliseconds after executing the playDisc handler&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
-----&lt;br /&gt;
&lt;br /&gt;
It is also possible to control the delay timing dynamically (e.g., using notification args). As an example, maybe your notification &#039;cardPlayed&#039; should pause for a different amount of time depending on the number or type of cards played.&lt;br /&gt;
&lt;br /&gt;
For this case, use &#039;&#039;&#039;setSynchronous&#039;&#039;&#039; without specifying the duration and use &#039;&#039;&#039;setSynchronousDuration&#039;&#039;&#039; within the notification callback.&lt;br /&gt;
&lt;br /&gt;
* NOTE: If you forget to invoke &#039;&#039;&#039;setSynchronousDuration&#039;&#039;&#039;, the game will remain paused forever!&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
setupNotifications: function () {&lt;br /&gt;
    dojo.subscribe( &#039;cardPlayed&#039;, this, &#039;notif_cardPlayed&#039; );&lt;br /&gt;
    this.notifqueue.setSynchronous( &#039;cardPlayed&#039; ); // wait time is dynamic&lt;br /&gt;
    ...&lt;br /&gt;
},&lt;br /&gt;
&lt;br /&gt;
notif_cardPlayed: function (notif) {&lt;br /&gt;
    // MUST call setSynchronousDuration&lt;br /&gt;
&lt;br /&gt;
    // Example 1: From notification args (PHP)&lt;br /&gt;
    this.notifqueue.setSynchronousDuration(notif.args.duration);&lt;br /&gt;
    ...&lt;br /&gt;
&lt;br /&gt;
    // Or, example 2: Match the duration to a Dojo animation&lt;br /&gt;
    var anim = dojo.fx.combine([&lt;br /&gt;
        ...&lt;br /&gt;
    ]);&lt;br /&gt;
    anim.play();&lt;br /&gt;
    this.notifqueue.setSynchronousDuration(anim.duration);&lt;br /&gt;
},&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You can also manually call this.notifqueue.setSynchronousDuration(0) once client operations are finished, but be careful that even fast replay still has a path to call it.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;WARNING: combining synchronous and ignored notifications&#039;&#039;&#039;&lt;br /&gt;
You must be careful when combining dynamic synchronous durations (as described above) with ignored notifications. If you have a conditionally ignored notification like this (see below section):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;this.notifqueue.setIgnoreNotificationCheck( &#039;myNotif&#039;, (notif) =&amp;gt; (notif.args.player_id == this.player_id) /* or any other condition */ )&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
then you CANNOT do&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;this.notifqueue.setSynchronous(&#039;myNotif&#039;);&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
as, when the ignored check passes, the notification handler, in which `this.notifqueue.setSychronousDuration` is called, is never called and so the duration is never set and interface locking results.&lt;br /&gt;
&lt;br /&gt;
The workaround is to set a &amp;quot;dummy&amp;quot; time:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;this.notifqueue.setSynchronous(&#039;myNotif&#039;, 5000);&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
whose value is irrelevant but must be large enough to cover the time before the notification handler is called. The large value never actually comes into play because the notification is either ignored, or the synchronous duration is reset to a sensible value inside the handler.&lt;br /&gt;
&lt;br /&gt;
=== Pre-defined notification types ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;tableWindow&#039;&#039;&#039; - This defines notification to display [[Game_interface_logic:_yourgamename.js#Scoring_dialogs|Scoring Dialogs]], see below.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;message&#039;&#039;&#039; - This defines notification that shows on players log and have no other effect (technically any unhandled notification will do the same but its recommended to use this keyword for consistency)&lt;br /&gt;
&lt;br /&gt;
   // You can call this on php side without doing anything on client side&lt;br /&gt;
    self::notifyAllPlayers( &#039;message&#039;, clienttranslate(&#039;hello&#039;), [] );&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;simplePause&#039;&#039;&#039; - This notification will just delay other notifications, maybe useful if you know you need some extra time for animation or something. Requires a time parameter.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    self::notifyAllPlayers( &#039;simplePause&#039;, &#039;&#039;, [ &#039;time&#039; =&amp;gt; 500] ); // time is in milliseconds&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note: the following types are RESERVED by framework, do not use:&lt;br /&gt;
&lt;br /&gt;
gameStateChange gameStateChangePrivateArg gameStateMultipleActiveUpdate newActivePlayer playerstatus yourturnack clockalert tableInfosChanged playerEliminated tableDecision  archivewaitingdelay end_archivewaitingdelay replaywaitingdelay end_replaywaitingdelay replayinitialwaitingdelay end_replayinitialwaitingdelay aiPlayerWaitingDelay replay_has_ended updateSpectatorList  wouldlikethink updateReflexionTime undoRestorePoint resetInterfaceWithAllDatas zombieModeFail zombieModeFailWarning aiError skipTurnOfPlayer zombieBack allPlayersAreZombie gameResultNeutralized playerConcedeGame showTutorial showCursor showCursorClick skipTurnOfPlayerWarning  banFromTable resultsAvailable switchToTurnbased newPrivateState infomsg&lt;br /&gt;
&lt;br /&gt;
== Tooltips ==&lt;br /&gt;
&lt;br /&gt;
=== Adding static tooltips ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.addTooltip(nodeId: string, helpStringTranslated: string, actionStringTranslated: string, delay?: number): void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Add a simple text tooltip to the DOM node.&lt;br /&gt;
&lt;br /&gt;
Specify &#039;helpStringTranslated&#039; to display some information about &amp;quot;what is this game element?&amp;quot;.&lt;br /&gt;
Specify &#039;actionStringTranslated&#039; to display some information about &amp;quot;what happens when I click on this element?&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
You must specify both of the strings. You can only use one and specify an empty string (&#039;&#039;) for the other one.&lt;br /&gt;
&lt;br /&gt;
When you pass text directly function _() must be used for the text to be marked for translation! Except for empty string.&lt;br /&gt;
&lt;br /&gt;
Parameter &amp;quot;delay&amp;quot; is optional. It is primarily used to specify a zero delay for some game element when the tooltip gives really important information for the game - but remember: no essential information must be placed in tooltips as they won&#039;t be displayed in some browsers (see [[BGA_Studio_Guidelines|Guidelines]]).&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
   this.addTooltip( &#039;cardcount&#039;, _(&#039;Number of cards in hand&#039;), &#039;&#039; );&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note: this generates static tooltip and attaches to existing dom element, if you need to generate tooltip more dynamically you have to call that method every time information about object is updated or use completely different tehnique, see dynamic tooltips below.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.addTooltipHtml(nodeId: string, html: string, delay?: number): void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Add an HTML tooltip to the DOM node (for more elaborate content such as presenting a bigger version of a card).&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.addTooltipToClass(cssClass: string, helpStringTranslated: string, actionStringTranslated: string, delay?: number ): void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Add a simple text tooltip to all the DOM nodes set with this cssClass. See more details above for this.addTooltip.&lt;br /&gt;
     this.addTooltipToClass( &#039;meeple&#039;, _(&#039;This is A Meeple&#039;), _(&#039;Click to tickle&#039;) );&lt;br /&gt;
&lt;br /&gt;
IMPORTANT: all concerned nodes must exist and have IDs to get tooltips.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.addTooltipHtmlToClass(cssClass: string, html: string, delay?: number): void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Add an HTML tooltip to to all the DOM nodes set with this cssClass (for more elaborate content such as presenting a bigger version of a card).&lt;br /&gt;
&lt;br /&gt;
IMPORTANT: all concerned nodes must exist and have IDs to get tooltips.&lt;br /&gt;
&lt;br /&gt;
=== Removing static tooltips ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.removeTooltip(nodeId: string): void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Remove a tooltip from the DOM node with given id.&lt;br /&gt;
&lt;br /&gt;
=== Advanced tooltips ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;force tooltip to open&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
If you want to force tooltip to open in reaction to some other action, i.e. click you can do this&lt;br /&gt;
&lt;br /&gt;
   this.tooltips[id].open(id)&lt;br /&gt;
&lt;br /&gt;
where id is the id of the tooltip node where tooltip was installed.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;dynamic tooltips&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
See [[BGA_Studio_Cookbook#Dynamic_tooltips]]&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;tooltips on mobile&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Tooltips is very unreliable on mobile, it is recommended to implement some other method to obtaining same information,&lt;br /&gt;
such as simple click handler in dedicated &amp;quot;Help&amp;quot; mode or provide dedicated clickable areas such as corner of card.&lt;br /&gt;
&lt;br /&gt;
== Warning messages ==&lt;br /&gt;
&lt;br /&gt;
Sometimes, there is something important that is happening in the game and you have to make sure all players get the message. Most of the time, the evolution of the game situation or the game log is enough, but sometimes you need something more visible.&lt;br /&gt;
&lt;br /&gt;
Ex: someone fulfills one of the end of the game conditions, so this is the last turn.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.showMessage(msg: string, type: string): void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
showMessage shows a message in a big rectangular area on the top of the screen of the current player, and it dissapears after few seconds (also it will be in the log in some cases).&lt;br /&gt;
&lt;br /&gt;
* &amp;quot;msg&amp;quot; is the string to display. It should be translated.&lt;br /&gt;
* &amp;quot;type&amp;quot; can be set to &amp;quot;info&amp;quot;, &amp;quot;error&amp;quot;, &amp;quot;only_to_log&amp;quot; or custom string. If set to &amp;quot;info&amp;quot;, the message will be an informative message on a white background. If set to &amp;quot;error&amp;quot;, the message will be an error message on a red background and it will be added to log. If set to &amp;quot;only_to_log&amp;quot;, the message will be added to the game log but will not popup at the top of the screen.&lt;br /&gt;
If set to custom string, it will be transparent, to use custom type define &amp;quot;head_xxx&amp;quot; in css, where xxx is the type. For example if you want yellow warning, use &amp;quot;warning&amp;quot; as type and add this to css:&lt;br /&gt;
 .head_warning {&lt;br /&gt;
    background-color: #e6c66e;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
Important: the normal way to inform players about the progression of the game is the game log. The &amp;quot;showMessage&amp;quot; is intrusive and should not be used often.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    notif_messageinfo: function(notif) {&lt;br /&gt;
	if (!g_archive_mode) {&lt;br /&gt;
        	var message = this.format_string_recursive(notif.log, notif.args);&lt;br /&gt;
		this.showMessage(_(&#039;Announcement:&#039;) + &amp;quot; &amp;quot; + message, &#039;info&#039;);		&lt;br /&gt;
         }&lt;br /&gt;
    },&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Show message could be used on the client side to prevent user wrong moves before it is send to server.&lt;br /&gt;
Example from &#039;battleship&#039;:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
onGrid: function(event) {&lt;br /&gt;
     if (checkIfPlayerTriesToFireOnThemselves(event)) {&lt;br /&gt;
        this.showMessage(_(&#039;This is your own board silly!&#039;), &#039;error&#039;);&lt;br /&gt;
        return;&lt;br /&gt;
     }&lt;br /&gt;
     ...&lt;br /&gt;
},&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.showMoveUnauthorized(): void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Shows predefined user error that move is unauthorized now&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
onPet: function(event) {&lt;br /&gt;
     if (checkPet(event)==false) {&lt;br /&gt;
        this.showMoveUnauthorized();&lt;br /&gt;
        return;&lt;br /&gt;
     }&lt;br /&gt;
     ...&lt;br /&gt;
},&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Dialogs ==&lt;br /&gt;
&lt;br /&gt;
=== Confirmation dialog ===&lt;br /&gt;
&lt;br /&gt;
When an important action with a lot of consequences is triggered by the player, you may want to propose a confirmation dialog.&lt;br /&gt;
&lt;br /&gt;
CAREFUL: the general guideline of BGA is to AVOID the use of confirmation dialogs. Confirmation dialogs slow down the game and bother players. The players know that they have to pay attention to each move when they are playing online.&lt;br /&gt;
&lt;br /&gt;
The situations where you should use a confirmation dialog are the following:&lt;br /&gt;
* It must not happen very often during a game.&lt;br /&gt;
* It must be linked to an action that can really &amp;quot;kill a game&amp;quot; if the player does not pay attention.&lt;br /&gt;
* It must be something that can be done by mistake (ex: a link on the action status bar).&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.confirmationDialog(message: string, yesHandler: (param: any) =&amp;gt; void, noHandler?: (param: any) =&amp;gt; void, param?: any): void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
* message - message will be shown to user, use _() to translate&lt;br /&gt;
* yesHandler - non-optional handler to be called on yes&lt;br /&gt;
* noHandler - optional handler to called on no&lt;br /&gt;
* param - if specified, it will be passed to both handlers&lt;br /&gt;
NOTE: this is async function, it does not return anything and you should not do anything after, you must do everything in handlers&lt;br /&gt;
&lt;br /&gt;
How to display a confirmation dialog:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    this.confirmationDialog(_(&amp;quot;Are you sure you want to bake a pie?&amp;quot;), () =&amp;gt; {&lt;br /&gt;
      this.bakeThePie();&lt;br /&gt;
    });&lt;br /&gt;
    return; // nothing should be called or done after calling this, all action must be done in the handler&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
With param and both handlers&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    this.confirmationDialog(_(&amp;quot;Are you sure you want to bake a pie?&amp;quot;), &lt;br /&gt;
           (ingredient) =&amp;gt; this.bakeThePie(ingredient), &lt;br /&gt;
           (ingredient) =&amp;gt; console.log(`cancelled baking of ${ingredient}`), &lt;br /&gt;
           &#039;apple&#039;);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Multiple choice dialog ===&lt;br /&gt;
&lt;br /&gt;
You can use this dialog to give user a choice with small amount of options&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.multipleChoiceDialog(message: string, choices: string[], callback: (choice: number) =&amp;gt; void): void&#039;&#039;&#039;&lt;br /&gt;
* message - message will be shown to user, use _() to translate&lt;br /&gt;
* choices - array of choices&lt;br /&gt;
* callback - non-optional handler to be called on choice made, the choice parameter is the INDEX of the choice from the array of choices&lt;br /&gt;
&lt;br /&gt;
NOTE: this is async function, it does not return anything and you should not do anything after, you must do everything in handlers&lt;br /&gt;
NOTE: there is no cancel handler, so make sure you gave user a choice to get out of it&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    const keys = [&amp;quot;0&amp;quot;, &amp;quot;1&amp;quot;, &amp;quot;5&amp;quot;, &amp;quot;10&amp;quot;];&lt;br /&gt;
    this.multipleChoiceDialog(_(&amp;quot;How many bugs to fix?&amp;quot;), keys, (choice) =&amp;gt; {&lt;br /&gt;
      if (choice==0) return; // cancel operation, do not call server action&lt;br /&gt;
      var bugchoice = keys[choice]; // choice will be 0,1,2,3 here&lt;br /&gt;
      this.bgaPerformAction(&amp;quot;fixBugs&amp;quot;, { number: bugchoice });&lt;br /&gt;
    });&lt;br /&gt;
    return; // must return here&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Generic Dialogs ===&lt;br /&gt;
&lt;br /&gt;
As a general rule, you shouldn&#039;t use dialogs windows.&lt;br /&gt;
&lt;br /&gt;
BGA guidelines specify that all game elements should be displayed on the main screen. Players can eventually scroll down to see game elements they don&#039;t need to see anytime, and you may eventually create anchors to move between game area section. Of course dialogs windows are very practical, but the thing is: all players know how to scroll down, and not all players know how to show up your dialog window. In addition, when the dialog shows up, players can&#039;t access the other game components.&lt;br /&gt;
&lt;br /&gt;
Sometimes although, you need to display a dialog window. Here is how you do this:&lt;br /&gt;
&lt;br /&gt;
  // Create the new dialog over the play zone. You should store the handler in a member variable to access it later&lt;br /&gt;
  this.myDlg = new ebg.popindialog();&lt;br /&gt;
  this.myDlg.create( &#039;myDialogUniqueId&#039; );&lt;br /&gt;
  this.myDlg.setTitle( _(&amp;quot;my dialog title to translate&amp;quot;) );&lt;br /&gt;
  this.myDlg.setMaxWidth( 500 ); // Optional&lt;br /&gt;
  &lt;br /&gt;
  // Create the HTML of my dialog. &lt;br /&gt;
  // The best practice here is to use [[Game_layout:_view_and_template:_yourgamename.view.php_and_yourgamename_yourgamename.tpl#Javascript_templates|Javascript templates]]&lt;br /&gt;
  var html = this.format_block( &#039;jstpl_myDialogTemplate&#039;, { &lt;br /&gt;
                arg1: myArg1,&lt;br /&gt;
                arg2: myArg2,&lt;br /&gt;
                ...&lt;br /&gt;
            } );  &lt;br /&gt;
  &lt;br /&gt;
  // Show the dialog&lt;br /&gt;
  this.myDlg.setContent( html ); // Must be set before calling show() so that the size of the content is defined before positioning the dialog&lt;br /&gt;
  this.myDlg.show();&lt;br /&gt;
  &lt;br /&gt;
  // Now that the dialog has been displayed, you can connect your method to some dialog elements&lt;br /&gt;
  // Example, if you have an &amp;quot;OK&amp;quot; button in the HTML of your dialog:&lt;br /&gt;
  dojo.connect($(&#039;my_ok_button&#039;), &#039;onclick&#039;, this, (event) =&amp;gt; {&lt;br /&gt;
                event.preventDefault();&lt;br /&gt;
                this.myDlg.destroy();&lt;br /&gt;
            });&lt;br /&gt;
&lt;br /&gt;
If necessary, you can remove the default top right corner &#039;close&#039; icon, or replace the function called when it is clicked:&lt;br /&gt;
  // Removes the default close icon&lt;br /&gt;
  this.myDlg.hideCloseIcon();&lt;br /&gt;
&lt;br /&gt;
  // Replace the function call when it&#039;s clicked&lt;br /&gt;
  this.myDlg.replaceCloseCallback((event) =&amp;gt; { ... });&lt;br /&gt;
&lt;br /&gt;
=== Scoring dialogs ===&lt;br /&gt;
&lt;br /&gt;
Sometimes at the end of a round you want to display a big table that details the points wins in each section of the game.&lt;br /&gt;
&lt;br /&gt;
Example: in Hearts game, we display at the end of each round the number of &amp;quot;heart&amp;quot; cards collected by each player, the player who collected the Queen of Spades, and the total number of points loose by each player.&lt;br /&gt;
&lt;br /&gt;
Scoring dialogs are managed entirely on &#039;&#039;&#039;PHP side&#039;&#039;&#039;, but they are described here as their effects are visible only on client side.&lt;br /&gt;
&lt;br /&gt;
Displaying a scoring dialog is quite simple and is using a special notification type: &amp;quot;tableWindow&amp;quot;:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  // on PHP side:&lt;br /&gt;
  $this-&amp;gt;notifyAllPlayers( &amp;quot;tableWindow&amp;quot;, &#039;&#039;, array(&lt;br /&gt;
            &amp;quot;id&amp;quot; =&amp;gt; &#039;finalScoring&#039;,&lt;br /&gt;
            &amp;quot;title&amp;quot; =&amp;gt; clienttranslate(&amp;quot;Title of the scoring dialog&amp;quot;),&lt;br /&gt;
            &amp;quot;table&amp;quot; =&amp;gt; $table&lt;br /&gt;
        )); &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The &amp;quot;table&amp;quot; argument is a 2 dimensional PHP array that describes the table you want to display, line by line and column by column.&lt;br /&gt;
&lt;br /&gt;
Example: display an 3x3 array of strings&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
   $table = [&lt;br /&gt;
      [ &amp;quot;one&amp;quot;, &amp;quot;two&amp;quot;, &amp;quot;three&amp;quot; ],    // This is my first line&lt;br /&gt;
      [ &amp;quot;four&amp;quot;, &amp;quot;five&amp;quot;, &amp;quot;six&amp;quot; ],    // This is my second line&lt;br /&gt;
      [ &amp;quot;seven&amp;quot;, &amp;quot;height&amp;quot;, &amp;quot;nine&amp;quot; ]    // This is my third line&lt;br /&gt;
   ];&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
As you can see above, in each &amp;quot;cell&amp;quot; of your array you can display a simple string value. But you can also display a complex value with a template and associated arguments like this:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
   $table = [&lt;br /&gt;
      [ &amp;quot;one&amp;quot;, &amp;quot;two&amp;quot;, [ &amp;quot;str&amp;quot; =&amp;gt; clienttranslate(&amp;quot;a string with an ${argument}&amp;quot;), &amp;quot;args&amp;quot; =&amp;gt; [ &#039;argument&#039; =&amp;gt; &#039;argument_value&#039; ] ] ],&lt;br /&gt;
      [ &amp;quot;four&amp;quot;, &amp;quot;five&amp;quot;, &amp;quot;six&amp;quot; ], &lt;br /&gt;
      [ &amp;quot;seven&amp;quot;, &amp;quot;height&amp;quot;, &amp;quot;nine&amp;quot; ]&lt;br /&gt;
   ];&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This is especially useful when you want to display player names with colors. Example from &amp;quot;Hearts&amp;quot;:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        $firstRow = [ &#039;&#039; ];&lt;br /&gt;
        foreach( $players as $player_id =&amp;gt; $player )    {&lt;br /&gt;
            $cell = [ &#039;str&#039; =&amp;gt; &#039;${player_name}&#039;,&lt;br /&gt;
                      &#039;args&#039; =&amp;gt; [ &#039;player_name&#039; =&amp;gt; $player[&#039;player_name&#039;] ],&lt;br /&gt;
                      &#039;type&#039; =&amp;gt; &#039;header&#039;&lt;br /&gt;
                    ];&lt;br /&gt;
            $firstRow[] = $cell;&lt;br /&gt;
        }&lt;br /&gt;
        $table[] = $firstRow;&lt;br /&gt;
        ...&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You can also use three extra attributes in the parameter array for the notification:&lt;br /&gt;
* &#039;&#039;&#039;header&#039;&#039;&#039;: the content for this parameter displays before the table (also, the html will be parsed and player names will be colored according to the current game colors). &lt;br /&gt;
* &#039;&#039;&#039;footer&#039;&#039;&#039;: the content for this parameter displays after the table (no parsing for coloring the player names)&lt;br /&gt;
* &#039;&#039;&#039;closing&#039;&#039;&#039;: if this parameter is used, a button will be displayed with this label at the bottom of the popup and will allow players to close it (more easily than by clicking the top right &#039;cross&#039; icon).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
   $this-&amp;gt;notifyAllPlayers( &amp;quot;tableWindow&amp;quot;, &#039;&#039;, [&lt;br /&gt;
            &amp;quot;id&amp;quot; =&amp;gt; &#039;finalScoring&#039;,&lt;br /&gt;
            &amp;quot;title&amp;quot; =&amp;gt; clienttranslate(&amp;quot;Title of the scoring dialog&amp;quot;),&lt;br /&gt;
            &amp;quot;table&amp;quot; =&amp;gt; $table,&lt;br /&gt;
            &amp;quot;header&amp;quot; =&amp;gt; [&#039;str&#039; =&amp;gt; clienttranslate(&#039;Table header with parameter ${number}&#039;),&lt;br /&gt;
                                 &#039;args&#039; =&amp;gt; [ &#039;number&#039; =&amp;gt; 3 ],&lt;br /&gt;
                               ],&lt;br /&gt;
            &amp;quot;footer&amp;quot; =&amp;gt; &#039;&amp;lt;div class=&amp;quot;myfoot&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&#039;,&lt;br /&gt;
            &amp;quot;closing&amp;quot; =&amp;gt; clienttranslate( &amp;quot;Closing button label&amp;quot; )&lt;br /&gt;
        ] ); &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note: currently id is not used - so you cannot access resulting div by id on js side&lt;br /&gt;
Note: any traslatable stirng have to be wrapped by clienttranslate() on top level OR it has to be recursive template. &lt;br /&gt;
&lt;br /&gt;
DO NOT DO THIS: &lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
   &amp;quot;footer&amp;quot; =&amp;gt; &#039;&amp;lt;div&amp;gt;&#039;.clienttranslate( &amp;quot;The end&amp;quot; ).&#039;&amp;lt;/div&amp;gt;&#039;, // this will not work for translations!!!&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Scoring animated display ===&lt;br /&gt;
&lt;br /&gt;
Sometimes, you may want to display a score value over an element to make the scoring easier to follow for the players (Terra Mystica final scoring for example).&lt;br /&gt;
You can do it with:&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.displayScoring(anchor_id: string, color: string, score: number | string, duration?: number, offset_x?: number, offset_y?: number): void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;anchor_id&#039;&#039;&#039;: ID of the html element to place the animated score onto (without the &#039;#&#039;) &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;color&#039;&#039;&#039;: hexadecimal RGB representation of the color (should be the color of the scoring player), but without a leading &#039;#&#039;.  For instance, &#039;ff0000&#039; for red.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;score&#039;&#039;&#039;: numeric score to display, prefixed by a &#039;+&#039; or &#039;-&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;duration&#039;&#039;&#039;: animation duration in milliseconds (optional, default is 1000)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;offset_x&#039;&#039;&#039; and &#039;&#039;&#039;offset_y&#039;&#039;&#039;: if both offset_x and offset_y are defined and not null, apply the following offset (in pixels) to the scoring animation. &lt;br /&gt;
Note that the score is centered in the anchor, so the offsets might have to be negative if you calculate the position.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Note: if you want to display successively each score, you can use &#039;&#039;this.notifqueue.setSynchronous()&#039;&#039; function.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    setupNotifications: function()   {&lt;br /&gt;
           dojo.subscribe( &#039;displayScoring&#039;, this, &amp;quot;notif_displayScoring&amp;quot; );&lt;br /&gt;
           ...&lt;br /&gt;
    }&lt;br /&gt;
...&lt;br /&gt;
&lt;br /&gt;
    notif_displayScoring: function(notif) {&lt;br /&gt;
            const duration = notif.args.duration?notif.args.duration:1000;&lt;br /&gt;
            this.notifqueue.setSynchronous(&#039;displayScoring&#039;, duration );&lt;br /&gt;
	    this.displayScoring( notif.args.target, notif.args.color, notif.args.score, duration);&lt;br /&gt;
    },&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Speech bubble ===&lt;br /&gt;
&lt;br /&gt;
For better interactivity in some games (Love Letter for example), you may use comic book style speech bubbles to express the players voices.&lt;br /&gt;
This is done with showBubble:&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.showBubble(anchor_id: string, text: string, delay?: number, duration?: number, custom_class?: string): void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
* anchor_id - where to attach the bubble&lt;br /&gt;
* text - what to put in bubble, can be html&lt;br /&gt;
* delay - delay in milliseconds (optional, default 0)&lt;br /&gt;
* duration -  duration of animation in milliseconds (optional, default 3000)&lt;br /&gt;
* custom_class - extra class to add to bubble (optional), if you need to override the default bubble style&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
   this.showBubble(&#039;meeple_2&#039;, _(&#039;Hello&#039;), 0, 1000, &#039;pink_bubble&#039;);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  notif_speechBubble(notif) {&lt;br /&gt;
    var html = this.format_string_recursive(notif.args.text, notif.args.args);&lt;br /&gt;
    this.showBubble(notif.args.target, html, notif.args.delay ?? 0, notif.args.duration ?? 1000);&lt;br /&gt;
  },&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Warning&#039;&#039;&#039;: if your bubble could overlap other active elements of the interface (buttons in particular), as it stays in place even after disappearing, you should use a custom class to give it the style &amp;quot;pointer-events: none;&amp;quot; in order to intercept click events.&lt;br /&gt;
&lt;br /&gt;
Note: If you want this visually, but want to take complete control over this bubble and its animation (for example to make it permanent) you can just use div with &#039;discussion_bubble&#039; class on it, and content of div is what will be shown.&lt;br /&gt;
&lt;br /&gt;
== Translations ==&lt;br /&gt;
&lt;br /&gt;
See [[Translations]]&lt;br /&gt;
&lt;br /&gt;
== Players panels ==&lt;br /&gt;
&lt;br /&gt;
=== Update players score ===&lt;br /&gt;
&lt;br /&gt;
The column player_score from the player table is automatically loaded into this.scoreCtrl and therefore into the stars location on the player board. This occurs sometime after the game setup() function. However this score must be updated as the game progresses using notifications.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Note: this.scoreCtrl[player_id] is object of class [[Counter]], you can use other counter API.&lt;br /&gt;
&lt;br /&gt;
Increase a player score (with a positive or negative number):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  this.scoreCtrl[ player_id ].incValue( score_delta );&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Set a player score to a specific value:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  this.scoreCtrl[ player_id ].setValue( new_score );&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Set a player score to a specific value with animation:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  this.scoreCtrl[ player_id ].toValue( new_score );&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Typical usage would be (that will process &#039;score&#039; notification):&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        setupNotifications : function() {&lt;br /&gt;
              ...&lt;br /&gt;
             dojo.subscribe(&#039;score&#039;, this, &amp;quot;notif_score&amp;quot;);&lt;br /&gt;
        },&lt;br /&gt;
        notif_score: function(notif) {&lt;br /&gt;
            this.scoreCtrl[notif.args.player_id].setValue(notif.args.player_score);&lt;br /&gt;
        },&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Adding stuff to player&#039;s panel ===&lt;br /&gt;
&lt;br /&gt;
At first, create a new &amp;quot;JS template&amp;quot; string in your template (tpl) file:&lt;br /&gt;
&lt;br /&gt;
(from Gomoku example)&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
var jstpl_player_board = &#039;\&amp;lt;div class=&amp;quot;cp_board&amp;quot;&amp;gt;\&lt;br /&gt;
    &amp;lt;div id=&amp;quot;stoneicon_p${id}&amp;quot; class=&amp;quot;gmk_stoneicon gmk_stoneicon_${color}&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&amp;lt;span id=&amp;quot;stonecount_p${id}&amp;quot;&amp;gt;0&amp;lt;/span&amp;gt;\&lt;br /&gt;
&amp;lt;/div&amp;gt;&#039;;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Then, you add this piece of code in your JS file to add this template to each player panel:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
            // Setting up player boards&lt;br /&gt;
            for( var player_id in gamedatas.players )&lt;br /&gt;
            {&lt;br /&gt;
                var player = gamedatas.players[player_id];&lt;br /&gt;
                         &lt;br /&gt;
                // Setting up players boards if needed&lt;br /&gt;
                var player_board_div = $(&#039;player_board_&#039;+player_id);&lt;br /&gt;
                dojo.place( this.format_block(&#039;jstpl_player_board&#039;, player ), player_board_div );&lt;br /&gt;
            }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
(Note: the code above is of course from your &amp;quot;setup&amp;quot; function in your Javascript).&lt;br /&gt;
&lt;br /&gt;
Very often, you have to distinguish current player and others players. In this case, you just have to create another JS template (ex: jstpl_otherplayer_board) and use it when &amp;quot;player_id&amp;quot; is different than &amp;quot;this.player_id&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Fixing Player Panel heights ===&lt;br /&gt;
&lt;br /&gt;
You may find that the player panels don&#039;t automatically resize when adding something to (or removing something from) a player panel while the display is in portrait mode (i.e. the player summary panels are at the top of the screen rather than down the right side).&lt;br /&gt;
&lt;br /&gt;
When this happens, call &amp;lt;pre&amp;gt;this.adaptPlayersPanels();&amp;lt;/pre&amp;gt; This recalculates the layout and also adjusts the position of the actionbar for you.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Player&#039;s panel disabling/enabling ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.disablePlayerPanel(player_id: number): void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Disable given player panel (the panel background become gray).&lt;br /&gt;
&lt;br /&gt;
Usually, this is used to signal that this played passes, or will be inactive during a while.&lt;br /&gt;
&lt;br /&gt;
Note that the only effect of this is visual. There are no consequences on the behaviour of the panel itself.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.enablePlayerPanel(player_id:number): void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Enable a player panel that has been disabled before.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.enableAllPlayerPanels(): void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Enable all player panels that has been disabled before.&lt;br /&gt;
&lt;br /&gt;
=== Player order ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.updatePlayerOrdering(): void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
This function makes sure that player order in player&#039;s panel matches this.gamedatas.playerorder and its normally called by framework.&lt;br /&gt;
You can call it yoursel if you change this.gamedatas.playerorder from notification.&lt;br /&gt;
Also you can override this function to change defaults  OR insert a non-player panel [[BGA_Studio_Cookbook#Inserting_non-player_panel]].&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Counters ===&lt;br /&gt;
Note: there is bga component called  &amp;quot;ebg/counter&amp;quot; this API is not using it, these methods&lt;br /&gt;
below declared right in core game. If you need animation for counters use ebg/counter&lt;br /&gt;
&lt;br /&gt;
To use this API just create a counter dom element like this (class does not really matter)&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 &amp;lt;div class=&amp;quot;counter&amp;quot; id=&amp;quot;bread&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
 &amp;lt;div class=&amp;quot;counter&amp;quot; id=&amp;quot;coin&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
The &amp;quot;bread&amp;quot; will the counter name.&lt;br /&gt;
&lt;br /&gt;
The php code should send all &amp;quot;counters&amp;quot; data from getAllDatas() method like this&lt;br /&gt;
&lt;br /&gt;
game.php&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  protected function getAllDatas() {&lt;br /&gt;
    // (the key must match counter_name)&lt;br /&gt;
    $result[&#039;counters&#039;]=[&lt;br /&gt;
        &#039;bread&#039; =&amp;gt; [ &lt;br /&gt;
         &#039;counter_name&#039; =&amp;gt; &#039;bread&#039;, &lt;br /&gt;
         &#039;counter_value&#039; =&amp;gt; 3&lt;br /&gt;
         ], &lt;br /&gt;
        &#039;coin&#039; =&amp;gt; [&lt;br /&gt;
          &#039;counter_name&#039; =&amp;gt; &#039;coin&#039;, &lt;br /&gt;
          &#039;counter_value&#039; =&amp;gt; 5&lt;br /&gt;
        ]&lt;br /&gt;
   ];&lt;br /&gt;
   return $result;&lt;br /&gt;
  }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;setCounter(counter_name: stirng, new_value: string | number): void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
updates the global this.gamedatas.counters and value of node $(counter_name)&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  notif_counter: function(notif) { &lt;br /&gt;
    this.setCounter(notif.args.counter_name, notif.args.counter_value);&lt;br /&gt;
  },&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;incCounter(counter_name: string, delta: number): void&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  notif_counter : function(notif) {&lt;br /&gt;
    this.incCounter(notif.args.counter_name, notif.args.inc);&lt;br /&gt;
  },&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;updateCounters(counters: object): void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Useful for updating game counters in the player panel (such as resources). &lt;br /&gt;
&#039;counters&#039; arg is map of counters (the key must match counter_name)&lt;br /&gt;
  {&lt;br /&gt;
    &#039;bread&#039;: { &lt;br /&gt;
         &#039;counter_name&#039; : &#039;bread&#039;, &lt;br /&gt;
         &#039;counter_value&#039; =&amp;gt; 3&lt;br /&gt;
    }, &lt;br /&gt;
    &#039;coin&#039;: { &lt;br /&gt;
         &#039;counter_name&#039; : &#039;coin&#039;, &lt;br /&gt;
         &#039;counter_value&#039; =&amp;gt; 5&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
All counters MUST be referenced in this.gamedatas.counters (means they should be send from php) and will be updated.&lt;br /&gt;
DOM objects referenced by &#039;counter_name&#039; will have their innerHTML updated with &#039;counter_value&#039;.&lt;br /&gt;
&lt;br /&gt;
Usually you call this from notification&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
                        notif_counter : function(notif) {&lt;br /&gt;
                            this.updateCounters(notif.args.counters);&lt;br /&gt;
                        },&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== BGA GUI components ==&lt;br /&gt;
&lt;br /&gt;
BGA framework provides some useful ready-to-use components for the game interface:&lt;br /&gt;
&lt;br /&gt;
[[Studio#BGA_Studio_game_components_reference]]&lt;br /&gt;
&lt;br /&gt;
Note that each time you are using an additional component, you must declare it at the top of your Javascript file in the list of modules used.&lt;br /&gt;
&lt;br /&gt;
Example if you are using &amp;quot;ebg.stock&amp;quot;:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
define([&lt;br /&gt;
    &amp;quot;dojo&amp;quot;,&amp;quot;dojo/_base/declare&amp;quot;,&lt;br /&gt;
    &amp;quot;ebg/core/gamegui&amp;quot;,&lt;br /&gt;
    &amp;quot;ebg/counter&amp;quot;,&lt;br /&gt;
    &amp;quot;ebg/stock&amp;quot;  /// &amp;lt;=== we are using ebg.stock module&lt;br /&gt;
],&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== BGA Buttons ==&lt;br /&gt;
&lt;br /&gt;
=== Basic Button ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.addActionButton(id: string, label: string, method: string | eventhandler, destination?: string, blinking?: boolean, color?: string): void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
You can use this method to add an action button in the main action status bar (or other places).&lt;br /&gt;
&lt;br /&gt;
Arguments:&lt;br /&gt;
* id: an element ID that should be unique in your HTML DOM document.&lt;br /&gt;
* label: the text of the button. Should be translatable (use _() function). Note: this can also be any html, such as &amp;quot;&amp;lt;div class=&#039;brick&#039;&amp;gt;&amp;lt;/div&amp;gt;&amp;quot;, see example below on how to make image action buttons.&lt;br /&gt;
* method: the name of your method that must be triggered when the player clicks on this button (can be name of the method on game class or handler).&lt;br /&gt;
* destination (optional): id of parent on where to add button, ONLY use in rare cases if location is not action bar. Use &#039;&#039;&#039;null&#039;&#039;&#039; as value if you need to specify other arguments.&lt;br /&gt;
* blinking (optional): if set to &#039;&#039;&#039;true&#039;&#039;&#039;, the button is going blink to catch player&#039;s attention. Please DO NOT abuse blinking button. If you need button to blink after some time passed add class &#039;blinking&#039; to the button later.&lt;br /&gt;
* color: could be &#039;&#039;&#039;blue&#039;&#039;&#039; (default), &#039;&#039;&#039;red&#039;&#039;&#039;,&#039;&#039;&#039;gray&#039;&#039;&#039; or &#039;&#039;&#039;none&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
You should only use this method in your &amp;quot;onUpdateActionButtons&amp;quot; method. Usually, you use it like this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        onUpdateActionButtons: function( stateName, args ) {                      &lt;br /&gt;
            if (this.isCurrentPlayerActive()) {            &lt;br /&gt;
                switch( stateName ) {&lt;br /&gt;
                case &#039;giveCards&#039;:&lt;br /&gt;
                    this.addActionButton( &#039;giveCards_button&#039;, _(&#039;Give selected cards&#039;), &#039;onGiveCards&#039; ); &lt;br /&gt;
                    this.addActionButton( &#039;pass_button&#039;, _(&#039;Pass&#039;), () =&amp;gt; this.bgaPerformAction(&#039;actPass&#039;) ); &lt;br /&gt;
                    break;&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        },   &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In the example above, we are adding a &amp;quot;Give selected cards&amp;quot; button in the case we are on game state &amp;quot;giveCards&amp;quot;. When player clicks on this button, it triggers our &amp;quot;onGiveCards&amp;quot; method.&lt;br /&gt;
&lt;br /&gt;
Example using blinking red button:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    this.addActionButton( &#039;button_confirm&#039;, _(&#039;Confirm?&#039;), &#039;onConfirm&#039;, null, true, &#039;red&#039;); &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If you want to call the handler with arguments, you can use arrow functions, like this:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
     this.addActionButton( &#039;commit_button&#039;, _(&#039;Confirm&#039;), () =&amp;gt; this.onConfirm(this.selectedCardId), null, false, &#039;red&#039;); &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Image Button ===&lt;br /&gt;
&lt;br /&gt;
You can use the same method, but add extra class to a button to disable the padding and style it, i.e.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
this.addActionButton( &#039;button_brick&#039;, &#039;&amp;lt;div class=&amp;quot;brick&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&#039;, ()=&amp;gt;{... on brick ...}, null, null, &#039;gray&#039;); &lt;br /&gt;
dojo.addClass(&#039;button_brick&#039;,&#039;bgaimagebutton&#039;);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
where&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
.bgaimagebutton {&lt;br /&gt;
  padding: 0px 12px;&lt;br /&gt;
  min-height: 28px;&lt;br /&gt;
  border: none;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If you use this a lot, you can define a helper function, i.e.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
 * This method can be used instead of addActionButton, to add a button which is an image (i.e. resource). Can be useful when player&lt;br /&gt;
 * need to make a choice of resources or tokens.&lt;br /&gt;
 */&lt;br /&gt;
addImageActionButton: function(id, div, handler, bcolor, tooltip) {&lt;br /&gt;
	if (typeof bcolor == &amp;quot;undefined&amp;quot;) {&lt;br /&gt;
		bcolor = &amp;quot;gray&amp;quot;;&lt;br /&gt;
	}&lt;br /&gt;
	// this will actually make a transparent button id color = gray&lt;br /&gt;
	this.addActionButton(id, div, handler, null, false, bcolor);&lt;br /&gt;
	// remove border, for images it better without&lt;br /&gt;
	dojo.style(id, &amp;quot;border&amp;quot;, &amp;quot;none&amp;quot;);&lt;br /&gt;
	// but add shadow style (box-shadow, see css)&lt;br /&gt;
	dojo.addClass(id, &amp;quot;shadow bgaimagebutton&amp;quot;);&lt;br /&gt;
	// you can also add additional styles, such as background&lt;br /&gt;
	if (tooltip) {&lt;br /&gt;
		dojo.attr(id, &amp;quot;title&amp;quot;, tooltip);&lt;br /&gt;
	}&lt;br /&gt;
	return $(id);&lt;br /&gt;
},&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Disabling Button ===&lt;br /&gt;
&lt;br /&gt;
You can disable the &#039;&#039;&#039;bgabutton&#039;&#039;&#039; by adding the css class &#039;&#039;&#039;disabled&#039;&#039;&#039; in you js. The disabled button is still visible but is grey and not clickable.&lt;br /&gt;
For example in the &#039;&#039;&#039;onUpdateActionButtons&#039;&#039;&#039; : &lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
this.addActionButton(&#039;play_button_id&#039;, _(&#039;Play 1 to 3 cards&#039;), &#039;playFunctionButton&#039;); &lt;br /&gt;
if (condition) {&lt;br /&gt;
  dojo.addClass(&#039;play_button_id&#039;, &#039;disabled&#039;);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Custom Buttons ===&lt;br /&gt;
&lt;br /&gt;
You can create a custom button, but the BGA framework provides a standard button that requires only .css classes: &#039;&#039;&#039;bgabutton&#039;&#039;&#039; and &#039;&#039;&#039;bgabutton_${color}&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Examples:&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;a href=&amp;quot;#&amp;quot; id=&amp;quot;my_button_id&amp;quot; class=&amp;quot;bgabutton bgabutton_blue&amp;quot;&amp;gt;&amp;lt;span&amp;gt;My blue button&amp;lt;/span&amp;gt;&amp;lt;/a&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;a href=&amp;quot;#&amp;quot; id=&amp;quot;my_button_id&amp;quot; class=&amp;quot;bgabutton bgabutton_red bgabutton_big&amp;quot;&amp;gt;&amp;lt;span&amp;gt;My big red button&amp;lt;/span&amp;gt;&amp;lt;/a&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note&#039;&#039;&#039;: To see it in action, check out &#039;&#039;Coloretto&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
=== Button outside of action bar ===&lt;br /&gt;
&lt;br /&gt;
Use addActionButton() method with destination argument set&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
this.addActionButton( &#039;commit_button&#039;, _(&#039;Confirm&#039;), &#039;onConfirm&#039;, &#039;player_board&#039;, true, &#039;red&#039;); &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
in example above the button will be place on object with id &#039;player_board&#039;&lt;br /&gt;
&lt;br /&gt;
== Image loading ==&lt;br /&gt;
&lt;br /&gt;
See also [[Game_art:_img_directory]].&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Be careful&#039;&#039;&#039;: by default, ALL images of your img directory are loaded on a player&#039;s browser when he loads the game. For this reason, don&#039;t let in your img directory images that are not useful, otherwise it&#039;s going to slowdown the game load.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.dontPreloadImage(image_file_name: string)&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Using dontPreloadImage, you tell the interface to not preload a specific image in your img directory.&lt;br /&gt;
&lt;br /&gt;
Example of use:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
this.dontPreloadImage( &#039;cards.png&#039; );&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This is particularly useful if for example you have 2 different themes for a game. To accelerate the loading of the game, you can specify to not preload images corresponding to the other theme.&lt;br /&gt;
&lt;br /&gt;
Another example of use: in &amp;quot;Gosu&amp;quot; game with Kamakor extension, you play with 5 sets of cards among 10 available. Cards images are organized by sets, and we only preload the images corresponding to the 5 current sets with &#039;&#039;&#039;ensureSpecificGameImageLoading( image_file_names_array )&#039;&#039;&#039;.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
// By default, do not preload anything&lt;br /&gt;
this.dontPreloadImage( &#039;cards.png&#039; );&lt;br /&gt;
this.dontPreloadImage( &#039;clan1.png&#039; );&lt;br /&gt;
this.dontPreloadImage( &#039;clan2.png&#039; );&lt;br /&gt;
this.dontPreloadImage( &#039;clan3.png&#039; );&lt;br /&gt;
this.dontPreloadImage( &#039;clan4.png&#039; );&lt;br /&gt;
this.dontPreloadImage( &#039;clan5.png&#039; );&lt;br /&gt;
this.dontPreloadImage( &#039;clan6.png&#039; );&lt;br /&gt;
this.dontPreloadImage( &#039;clan7.png&#039; );&lt;br /&gt;
this.dontPreloadImage( &#039;clan8.png&#039; );&lt;br /&gt;
this.dontPreloadImage( &#039;clan9.png&#039; );&lt;br /&gt;
this.dontPreloadImage( &#039;clan10.png&#039; );&lt;br /&gt;
var to_preload = [];&lt;br /&gt;
for( i in this.gamedatas.clans )&lt;br /&gt;
{&lt;br /&gt;
	var clan_id = this.gamedatas.clans[i];&lt;br /&gt;
	to_preload.push( &#039;clan&#039;+clan_id+&#039;.png&#039; );&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
this.ensureSpecificGameImageLoading( to_preload );&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note:&#039;&#039;&#039; You don&#039;t need to specify to not preload game box images (game_box.png, game_box75.png...) since they are not preloaded by default.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.ensureSpecificGameImageLoading(list: string[])&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
This is oppostive of dontPreloadImage - its ensure specific images is loaded. Note: only makes sense if preload list is empty, otherwise everything is loaded anyway&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;load specific images&#039;&#039;&#039;&lt;br /&gt;
All images that will be preloaded stored in g_img_preload. If you want to override it directly - there is no API, but you can do this in GAME constructor&lt;br /&gt;
&lt;br /&gt;
          g_img_preload = [&#039;tokens.png&#039;, &#039;trains.png&#039;, &#039;loc_plan.png&#039;, &#039;eng.png&#039;, &#039;eng-back.png&#039;];&lt;br /&gt;
&lt;br /&gt;
You can also set it to empty array and call ensureSpecificGameImageLoading() on specific images&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Sounds ==&lt;br /&gt;
&lt;br /&gt;
Add a custom sound and make it load with your interface:&lt;br /&gt;
&lt;br /&gt;
Add this in your template (.tpl) file:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;audio id=&amp;quot;audiosrc_&amp;lt;gamename&amp;gt;_&amp;lt;yoursoundname&amp;gt;&amp;quot; src=&amp;quot;{GAMETHEMEURL}img/&amp;lt;gamename&amp;gt;_&amp;lt;yoursoundname&amp;gt;.mp3&amp;quot; preload=&amp;quot;none&amp;quot; autobuffer&amp;gt;&amp;lt;/audio&amp;gt;&lt;br /&gt;
&amp;lt;audio id=&amp;quot;audiosrc_o_&amp;lt;gamename&amp;gt;_&amp;lt;yoursoundname&amp;gt;&amp;quot; src=&amp;quot;{GAMETHEMEURL}img/&amp;lt;gamename&amp;gt;_&amp;lt;yoursoundname&amp;gt;.ogg&amp;quot; preload=&amp;quot;none&amp;quot; autobuffer&amp;gt;&amp;lt;/audio&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note: this is a requirement to provide both a mp3 and a ogg file with the names &amp;lt;code&amp;gt;&amp;lt;gamename&amp;gt;_&amp;lt;yoursoundname&amp;gt;[.ogg][.mp3]&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Play the sound (from your .js file):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
playSound(&#039;&amp;lt;gamename&amp;gt;_&amp;lt;yoursoundname&amp;gt;&#039;);   // do not add &#039;this.&#039; - its a global function&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Disable the standard &amp;quot;move&amp;quot; sound for this move (to replace it with your custom sound):&lt;br /&gt;
&lt;br /&gt;
Add this to your notification handler:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
this.disableNextMoveSound();&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note: it only disable the sound for the next move.&lt;br /&gt;
&lt;br /&gt;
== Title bar and states ==&lt;br /&gt;
&lt;br /&gt;
=== Client states ===&lt;br /&gt;
&lt;br /&gt;
Client states is a way to simulate the state transition but without actually going&lt;br /&gt;
to server. It is usefull when you need to ask user multiple questions before you&lt;br /&gt;
send things to server&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.setClientState(newState: string, args: object)&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
     this.setClientState(&amp;quot;client_playerPicksLocation&amp;quot;, {&lt;br /&gt;
                               descriptionmyturn : _(&amp;quot;${you} must select location&amp;quot;),&lt;br /&gt;
                           });&lt;br /&gt;
&lt;br /&gt;
For more information see [[BGA_Studio_Cookbook#Multi_Step_Interactions:_Select_Worker.2FPlace_Worker_-_Using_Client_States]]&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.restoreServerGameState()&#039;&#039;&#039;&lt;br /&gt;
If you are in client state it will restore the current server state (cheap undo)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.on_client_state&#039;&#039;&#039;&lt;br /&gt;
Boolean indicating that we are in client state&lt;br /&gt;
&lt;br /&gt;
=== Title bar ===&lt;br /&gt;
If you simply want to show something in title bar you can do it directly &lt;br /&gt;
     $(&#039;pagemaintitletext&#039;).innerHTML = text;&lt;br /&gt;
&lt;br /&gt;
This however will not work with parameters and will not draw You in color,&lt;br /&gt;
if you want to do proper args rendering use method below&lt;br /&gt;
&lt;br /&gt;
;&#039;&#039;&#039;this.removeActionButtons()&#039;&#039;&#039;&lt;br /&gt;
Removes all buttons from title bar&lt;br /&gt;
&lt;br /&gt;
;&#039;&#039;&#039;this.updatePageTitle()&#039;&#039;&#039;&lt;br /&gt;
:This function allows to update the current page title and turn description according to the game state arguments. If the current game state description this.gamedatas.gamestate.descriptionmyturn is modified before calling this function it allows to update the turn description without changing state. This will handle arguments substitutions properly.&lt;br /&gt;
&lt;br /&gt;
Note: this functional also will calls this.onUpdateActionButtons, if you want different buttons then state defaults, use method in example to replace them, if it becomes too clumsy use client states (see above)&lt;br /&gt;
&lt;br /&gt;
Example from Terra Mystica:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
onClickFavorTile: function( evt ) {&lt;br /&gt;
    ...&lt;br /&gt;
    if ( ... ) {&lt;br /&gt;
        this.gamedatas.gamestate.descriptionmyturn = _(&#039;Special action: &#039;) + _(&#039;Advance 1 space	on a Cult track&#039;);&lt;br /&gt;
        this.updatePageTitle();&lt;br /&gt;
        this.removeActionButtons();&lt;br /&gt;
        this.addActionButton( ... );&lt;br /&gt;
         ...&lt;br /&gt;
        return;&lt;br /&gt;
    }&lt;br /&gt;
    ...&lt;br /&gt;
&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== User preferences ==&lt;br /&gt;
&#039;&#039;&#039;this.getGameUserPreference(pref_id)&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Return the value of a user preference. It will return the value currently selected in the select combo box, in the top-right menu.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.setGameUserPreference(pref_id, value)&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Programmatically change a user preference. It will have the same effect as if the player changed the value in the select combo box, in the top-right menu.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;this.onGameUserPreferenceChanged&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
A callback you can define if you want to be notified when a user changes a user preference.&lt;br /&gt;
&lt;br /&gt;
Example:&amp;lt;pre&amp;gt;&lt;br /&gt;
onGameUserPreferenceChanged: function(pref_id, pref_value) {&lt;br /&gt;
  switch (pref_id) {&lt;br /&gt;
    case 201: &lt;br /&gt;
      document.getElementsByTagName(&#039;html&#039;)[0].classList.toggle(&#039;dark-background&#039;, pref_value == 2);&lt;br /&gt;
      break;&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Other useful stuff ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;dojo.hitch&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
With dojo.hitch, you can create a callback function that will run with your game object context whatever happen.&lt;br /&gt;
&lt;br /&gt;
Typical example: display a BGA confirmation dialog with a callback function created with dojo.hitch:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        this.confirmationDialog( _(&#039;Are you sure you want to make this?&#039;), dojo.hitch( this, function() {&lt;br /&gt;
            this.bgaPerformAction(&#039;makeThis&#039;);&lt;br /&gt;
        } ) );   &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In the example above, using dojo.hitch, we ensure that the &amp;quot;this&amp;quot; object will be set when the callback is called.&lt;br /&gt;
&lt;br /&gt;
NOTE: In modern JS there are lambdas that eliminate need for that, the example above will look like this&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        this.confirmationDialog( _(&#039;Are you sure you want to make this?&#039;), () =&amp;gt; this.bgaPerformAction( &#039;makeThis&#039;) );   &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
;&#039;&#039;&#039;onScreenWidthChange()&#039;&#039;&#039;&lt;br /&gt;
:This function can be overridden in your game to manage some resizing on the client side when the browser window is resized. This function is also triggered at load time, so it can be used to adapt to the :viewport size at the start of the game too.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
; this.bRealtime&lt;br /&gt;
: Return true if the game is in realtime. Note that having a distinct behavior in realtime and turn-based should be exceptional.&lt;br /&gt;
&lt;br /&gt;
; g_replayFrom&lt;br /&gt;
: Global contains replay number in live game, it is set to undefined (i.e. not set) when it is not a replay mode, so consequentially the good check is &#039;&#039;&#039;typeof g_replayFrom != &#039;undefined&#039;&#039;&#039;&#039; which returns true if the game is in replay mode &amp;lt;i&amp;gt;during the game&amp;lt;/i&amp;gt; (the game is ongoing but the user clicked &amp;quot;replay from this move&amp;quot; in the log)&lt;br /&gt;
&lt;br /&gt;
; g_archive_mode&lt;br /&gt;
: Returns true if the game is in archive mode &amp;lt;i&amp;gt;after the game&amp;lt;/i&amp;gt; (the game has ended)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
; this.instantaneousMode&lt;br /&gt;
: Returns true during replay/archive mode if animations should be skipped. Only needed if you are doing custom animations. (The BGA-provided animation functions like &amp;lt;i&amp;gt;this.slideToObject()&amp;lt;/i&amp;gt; automatically handle instantaneous mode.)&lt;br /&gt;
: Technically, when you click &amp;quot;replay from move #20&amp;quot;, the system replays the game from the very beginning with moves 0 - 19 happening in instantaneous mode and moves 20+ happening in normal mode.&lt;br /&gt;
&lt;br /&gt;
; g_tutorialwritten&lt;br /&gt;
: Returns an object like the below if the game is in tutorial mode, or undefined otherwise. Tutorial mode is a special case of archive mode where comments have been added to a previous game to teach new players the rules.&lt;br /&gt;
    {&lt;br /&gt;
        author: &amp;quot;91577332&amp;quot;,&lt;br /&gt;
        id: &amp;quot;576&amp;quot;,&lt;br /&gt;
        mode: &amp;quot;view&amp;quot;&lt;br /&gt;
        status: &amp;quot;alpha&amp;quot;&lt;br /&gt;
        version_override: null&lt;br /&gt;
        viewer_id: &amp;quot;84554161&amp;quot;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;getBgaEnvironment(): string&#039;&#039;&#039;&lt;br /&gt;
: Returns &amp;quot;studio&amp;quot; for studio and &amp;quot;prod&amp;quot; for production environment (i.e. where games current runs). Only useful for debbugging hooks.&lt;br /&gt;
Note: alpha server is also &amp;quot;prod&amp;quot;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Category:Studio]]&lt;/div&gt;</summary>
		<author><name>Sguzzer Gunayer</name></author>
	</entry>
	<entry>
		<id>https://en.doc.boardgamearena.com/index.php?title=Translations&amp;diff=22699</id>
		<title>Translations</title>
		<link rel="alternate" type="text/html" href="https://en.doc.boardgamearena.com/index.php?title=Translations&amp;diff=22699"/>
		<updated>2024-09-23T09:37:25Z</updated>

		<summary type="html">&lt;p&gt;Sguzzer Gunayer: /* How to not make translators crazy ;) */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Studio_Framework_Navigation}}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Using BGA Studio, the game you create is ready to be translated to each language by the BGA community. To make this possible, you only need to specify which string must be translated and how to combine them.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
__TOC__&lt;br /&gt;
&lt;br /&gt;
== Localization Overview ==&lt;br /&gt;
&lt;br /&gt;
Localization for BGA games happens largely on the CLIENT. Games must be developed in English and English strings are sent to the client.&lt;br /&gt;
&lt;br /&gt;
It&#039;s only at the client that your English strings will be displayed with the translation for the user&#039;s language, when such a translation exists.&lt;br /&gt;
&lt;br /&gt;
For anyone who has worked on a system where translation happens at the server and localized strings are sent to the client: you must unlearn what you have learned. Just stick with English and send the untranslated English strings. The magic happens at the client.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== How will my strings be translated? ==&lt;br /&gt;
&lt;br /&gt;
When developing your game, all strings must be in English. Strings must be coherent with the English version of the game.&lt;br /&gt;
&lt;br /&gt;
Once your game enters Beta, the BGA player community will descend upon your game like a plague of locusts and translate it into dozens of languages before you can say &amp;quot;Je ne parle pas anglais&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== What do I have to do from a programming standpoint? ==&lt;br /&gt;
&lt;br /&gt;
Not as much as you think. Read on for full details, but the golden rules are:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
# Make sure that any string on the server side that needs to be translated on the client side is wrapped in a clienttranslate() function when defined. For example: $my_response = clienttranslate(&#039;Hey translators, please translate this string&#039;). clienttranslate doesn&#039;t actually do anything at all (it just passes the text through) but the translation engine searches your code for strings wrapped in that function and uses them to build the list of strings that need to be translated.&lt;br /&gt;
# On the client side, just display your text, but wrap it in _().&lt;br /&gt;
## If you pass a string constant to _() - such as _(&#039;This is my string&#039;) then the parser will automatically detect and add your string to the list of strings that need to be translated, AND it will display the local translation for it when displaying.&lt;br /&gt;
## If you pass a variable to _() - such as _(args.my_message) then MAKE SURE that the variable is set to an English string that is either defined somewhere in your PHP code in a clienttranslate() function or somewhere else in your javascript code in a _() function. As long as it is, the translators will provide translations for it, and the _() function will display the local translation of your English string.&lt;br /&gt;
# A string used as the message for notifyAllPlayers or notifyPlayer will automatically have its translation displayed on the client - you don&#039;t need to do anything EXCEPT make sure that it is wrapped in a clienttranslate() on the server, so that it gets translated.&lt;br /&gt;
# A string used as the &amp;quot;description&amp;quot; or &amp;quot;descriptionmyturn&amp;quot; for a state in your state machine will also be automatically translated on the client - you don&#039;t need to do anything EXCEPT make sure that it is wrapped in a clienttranslate() on the server, so that it gets translated.&lt;br /&gt;
# A string used in the pre-games option screen will also automatically have any translation displayed at the client - you don&#039;t need to do anything EXCEPT make sure that it is wrapped in a totranslate() on the server (nota bene: you should not use clienttranslate() here as this file is processed specifically and those strings will not be included in the game translation file but in the main site translation file - with a prefix to keep translations isolated by module - as they have to be translated on main site pages. If you need exactly the same string in your game for a client side translation, it should be declared somewhere else in your code wrapped inside a clienttranslate() to be included in the game translation file.&lt;br /&gt;
# A string used in the statistics screen will operate like a string in the pre-game options screen. It will automatically have any translation displayed at the client as long as you make sure that it is wrapped in a totranslate() on the server.&lt;br /&gt;
# If you are using parameters for a call to notifyAllPlayers or notifyPlayers, or for a state&#039;s &amp;quot;description&amp;quot; or &amp;quot;descriptionmyturn&amp;quot; and those parameters contain text that needs to be translated, you will need to tell the system to display the translated versions of them by using the &#039;i18n&#039; argument. See below for full details.&lt;br /&gt;
&lt;br /&gt;
== What strings should be marked for translation ==&lt;br /&gt;
&lt;br /&gt;
YES:&lt;br /&gt;
* Every text that can be visible by the player when the game is running normally. This includes tooltips, texts on cards, error messages.&lt;br /&gt;
&lt;br /&gt;
NO:&lt;br /&gt;
* Error messages that are not supposed to happen (unexpected errors).&lt;br /&gt;
* Player names (i.e. do not put player_name or any php key send via notification which is essentially a player name, such as &#039;other_player&#039; in &#039;i18n&#039; array)&lt;br /&gt;
* Proper names of characters or places in some cases (consult the publisher)&lt;br /&gt;
* Numbers (i.e  _(&amp;quot;42&amp;quot;))&lt;br /&gt;
* Keywords used internally&lt;br /&gt;
&lt;br /&gt;
== What rules should I follow for the original English strings? ==&lt;br /&gt;
&lt;br /&gt;
For a coherent and homogeneous interface, here are some rules about ending a sentence with a final period &#039;.&#039;&lt;br /&gt;
&lt;br /&gt;
* As a general rule:&lt;br /&gt;
** If a sentence is displayed isolated in the interface =&amp;gt; no final period&lt;br /&gt;
** If a sentence is followed or could be followed by another sentence in the same interface space =&amp;gt; final period.&lt;br /&gt;
&lt;br /&gt;
* In detail:&lt;br /&gt;
** No final period:&lt;br /&gt;
*** button labels&lt;br /&gt;
*** section titles&lt;br /&gt;
*** menu elements&lt;br /&gt;
*** links triggering an isolated action&lt;br /&gt;
*** anything that is not a full sentence&lt;br /&gt;
*** current actions in the status bar&lt;br /&gt;
** Final period:&lt;br /&gt;
*** complete sentences (e.g., explanations and descriptions) that can be chained with other sentences&lt;br /&gt;
** Either a period or no period is acceptable (but this should be consistent throughout the game) for:&lt;br /&gt;
*** isolated tooltips / small sentences&lt;br /&gt;
*** game logs (no period is usually preferable)&lt;br /&gt;
*** error messages (unless there is more than one sentence in the error message; final period is mandatory in this case)&lt;br /&gt;
&lt;br /&gt;
Otherwise, you should try to follow as closely as possible the general style and format (including capitalization) used in the published English rulebook and game materials.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Focus on translating notifications ==&lt;br /&gt;
&lt;br /&gt;
Usually, translating a website is simple: you just call a function on every string you have to translate, and the string is translated in the player&#039;s language. On Board Game Arena, this is exactly the same with the &amp;quot;_( string )&amp;quot; function.&lt;br /&gt;
&lt;br /&gt;
However, there is one difference on BGA: notifications. The server is sending notifications to players, and most of the time the notifications are the same for every players, no matter what language each player is using. This is why notifications are translated on client side in the proper language, even if the strings are defined on server side.&lt;br /&gt;
&lt;br /&gt;
== How to not make translators crazy ;) ==&lt;br /&gt;
&lt;br /&gt;
* Try to reuse the exact same strings (with the same case, etc.) to minimize the number of strings to translate.&lt;br /&gt;
** &#039;&#039;&#039;Example&#039;&#039;&#039;: Consider replacing &amp;lt;pre&amp;gt;self::_(&amp;quot;Winner&amp;quot;)&amp;lt;/pre&amp;gt; and &amp;lt;pre&amp;gt;self::_(&amp;quot;Winners&amp;quot;)&amp;lt;/pre&amp;gt; (two strings to translate) with &amp;lt;pre&amp;gt;self::_(&amp;quot;Winner(s)&amp;quot;)&amp;lt;/pre&amp;gt;&lt;br /&gt;
** &#039;&#039;&#039;Example 2&#039;&#039;&#039;: &amp;lt;pre&amp;gt;clienttranslate(&amp;quot;play a card&amp;quot;)&amp;lt;/pre&amp;gt; and &amp;lt;pre&amp;gt;clienttranslate(&amp;quot;Play a card&amp;quot;)&amp;lt;/pre&amp;gt; means there will be two strings to translate.&lt;br /&gt;
* Do not mark as translatable a game element that does not have to be translated (ex: if the name of a monster on a card is &amp;quot;Zzzzz&amp;quot;, maybe there&#039;s no need to translate it).&lt;br /&gt;
* Words does not come in the same order in each language. Thus, when you have to translate a string with an argument, do not write something like:&lt;br /&gt;
&amp;lt;pre&amp;gt;self::_(&amp;quot;First part of the string, &amp;quot;).$argument.&#039; &#039;.self::_(&amp;quot;second part of the string&amp;quot;)&amp;lt;/pre&amp;gt;&lt;br /&gt;
Write instead:&lt;br /&gt;
&amp;lt;pre&amp;gt;sprintf( self::_(&amp;quot;First part of the string, %s second part of the string&amp;quot;), $argument )&amp;lt;/pre&amp;gt;&lt;br /&gt;
(or the equivalent &amp;quot;dojo.string.substitute&amp;quot; in Javascript)&lt;br /&gt;
* This also applies to punctuation marks. I.e. this is not good: _(&amp;quot;Pick&amp;quot;)+&amp;quot;:&amp;quot;&lt;br /&gt;
* When translators are going to translate your game, the most difficult task for them is to get the context of the string to be translated. The shorter the string is, the more difficult the task is for them. As a rule of thumb, try to avoid short, insignificant strings that require knowledge of their surrounding context. You can also leave a comment on the context of the string in the translation program (English to English) if you are the developer of the game.&lt;br /&gt;
* Use same sentence for plural vs singular. We prefer to write &amp;quot;player gets 1 coin(s)&amp;quot; (or &amp;quot;coin/s&amp;quot;) rather than write two versions of the same string for plural and singular - it reduces the number of strings to translate. Also using the icon to represent coin in logs may solve this issue.&lt;br /&gt;
* Instead of writing elaborate strings like &amp;quot;With the effect of ZZZ, player XXX gains a new YYY&amp;quot;, which is very difficult to translate, write strings like &amp;quot;ZZZ: XXX gets YYY&amp;quot;.&lt;br /&gt;
* Use present tense instead of past. E.g., &amp;quot;player gets wood&amp;quot; instead of &amp;quot;player got wood&amp;quot;.&lt;br /&gt;
* Avoid using gender-specific wording as much as possible. &lt;br /&gt;
* Also avoid &amp;quot;their&amp;quot;. There is [[https://forum.boardgamearena.com/viewtopic.php?f=11&amp;amp;t=19432&amp;amp;start=10#p88592 a pronoun replacement system]] is in place, and cannot work if your use &amp;quot;their&amp;quot; as a singular genderless pronoun, as it removes the information that it&#039;s singular. E.g., you should write &amp;quot;playerX returns card to *his* hand&amp;quot; or &amp;quot;playerX returns card to *his/her* hand&amp;quot; and not &amp;quot;playerX returns card to *their* hand&amp;quot; as in the 2 first case the system will substitute the proper pronoun his/her/their depending on playerX declared/undeclared gender, but in the second case it will always stay &amp;quot;their&amp;quot; whatever the player preference setting. In some case its actually needed, for example if you say &amp;quot;King sends his troops&amp;quot; in the log and King is not a player name, but character in the game - it will be changed to &amp;quot;her&amp;quot; if a player is female, which is not correct, in this case their would be appropriate (or just &amp;quot;the troops&amp;quot;)&lt;br /&gt;
* Where two strings are identical apart from (say) a number, use the same string with a ${parameter}, and call format_string_recursive (on the client) or use args (for notifications and state descriptions) to provide the details. But *never* do that for composing multiple sentences with words: other languages have different grammar and it would most likely create untranslatable strings.&lt;br /&gt;
&lt;br /&gt;
== WARNING: Make sure your strings will be translated! ==&lt;br /&gt;
&lt;br /&gt;
For each game, our translation tool does a full scan of the code, looking for translation markers like &amp;quot;_()&amp;quot; or &amp;quot;clienttranslate()&amp;quot;. (See below for the full list of translation markers.)&lt;br /&gt;
&lt;br /&gt;
If your original string is not completely contained inside one of these markers, it won&#039;t be translated.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    // Examples: the following strings will be translated:&lt;br /&gt;
    var mystring_translated = _(&amp;quot;my string&amp;quot;);       // JS&lt;br /&gt;
    $mystring_translated = self::_(&amp;quot;my string&amp;quot;);    // PHP&lt;br /&gt;
    $mystring_translated = sprintf( self::_(&amp;quot;my string with an %s argument&amp;quot;), $argument );   // PHP&lt;br /&gt;
&lt;br /&gt;
    // Examples: the following strings WILL NOT be translated:&lt;br /&gt;
    $my_string = &amp;quot;my string&amp;quot;;&lt;br /&gt;
    $not_translated = self::_( $my_string );   // The original string is not contained within a translator marker =&amp;gt; no translation&lt;br /&gt;
    $not_translated = self::_( sprintf( &amp;quot;my string with a %s argument&amp;quot;, $argument ) ); // Ditto&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== On client side (Javascript) ==&lt;br /&gt;
&lt;br /&gt;
On client side, things are quite simple: you just have to use the &amp;quot;_()&amp;quot; function for all strings you want to translate.&lt;br /&gt;
&lt;br /&gt;
Examples:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
// Get a string in player&#039;s language:&lt;br /&gt;
var translated = _(&amp;quot;original english string&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
// Get a string in player&#039;s language with parameter:&lt;br /&gt;
var translated = dojo.string.substitute( _(&amp;quot;You can pick ${p} cards and discard ${d}&amp;quot;), {&lt;br /&gt;
    p: 2,&lt;br /&gt;
    d: 4&lt;br /&gt;
} );&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;WARNING:&#039;&#039;&#039; in Javascript strings to translate, you should never use &#039;\n&#039;, &#039;\t&#039; or such, as it will break the translation bundle and result in all the Javascript translation to fail. In any case, the strings will result in HTML code, and such character codes won&#039;t have any impact on the HTML rendering. You should use HTML markup instead.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;ANOTHER WARNING:&#039;&#039;&#039; you cannot use this function _() in the javascript object constructor, but you can achieve the same if you use it the setup method. If you do that you will see this error in browser debug console:&lt;br /&gt;
  Try to use a translated string in JS object declaration : impossible =&amp;gt; string is NOT translated&lt;br /&gt;
&lt;br /&gt;
=== Formatting on client side ===&lt;br /&gt;
&lt;br /&gt;
Sometimes you will want to apply some formatting on the client side, but don&#039;t want to put HTML tags within the source string (which may be confusing for translators).&lt;br /&gt;
&lt;br /&gt;
This can be achieved with the &amp;lt;code&amp;gt;bga_format&amp;lt;/code&amp;gt; function and Markdown-style syntax.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
 * @function bga_format&lt;br /&gt;
 * Replaces delimiters with HTML tags in translated text&lt;br /&gt;
 * @param {string} translated string&lt;br /&gt;
 * @param {Object} map of replacements to make, should be of the form&lt;br /&gt;
 *     {&lt;br /&gt;
 *         &#039;*&#039;: (t) =&amp;gt; t,&lt;br /&gt;
 *         &#039;_&#039;: &#039;classname&#039;,&lt;br /&gt;
 *     }&lt;br /&gt;
 *     keys are delimiters within the translated string&lt;br /&gt;
 *     values are either strings (classname of surrounding span) or function (flexible replacements)&lt;br /&gt;
 * @returns {string} Returns the original string, with replacements made.&lt;br /&gt;
 */&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
// Get a string in player&#039;s language:&lt;br /&gt;
bga_format(_(&#039;You receive a *special* _tile_&#039;), {&lt;br /&gt;
    &#039;*&#039;: (t) =&amp;gt; &#039;&amp;lt;b&amp;gt;&#039; + t + &#039;&amp;lt;/b&amp;gt;&#039;,&lt;br /&gt;
    &#039;_&#039;: &#039;tile-name&#039;&lt;br /&gt;
});&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The above will return something along the lines of:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
You receive a &amp;lt;b&amp;gt;special&amp;lt;/b&amp;gt; &amp;lt;span class=&amp;quot;tile-name&amp;quot;&amp;gt;tile&amp;lt;/span&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Or, if the user is playing in Spanish, for example:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Recibes una &amp;lt;span class=&amp;quot;tile-name&amp;quot;&amp;gt;loseta&amp;lt;/span&amp;gt; &amp;lt;b&amp;gt;especial&amp;lt;/b&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Notes:&lt;br /&gt;
* The text passed to &amp;lt;code&amp;gt;bga_format&amp;lt;/code&amp;gt; must still be translated using &amp;lt;code&amp;gt;_()&amp;lt;/code&amp;gt;, don&#039;t forget it!&lt;br /&gt;
* Good characters to demarcate formatting are: &amp;lt;code&amp;gt;[&#039;*&#039;, &#039;_&#039;]&amp;lt;/code&amp;gt; (other single characters will work, just make sure it will be clear to a translator)&lt;br /&gt;
* If the replacements object is a string, the inner text will be placed within a &amp;lt;code&amp;gt;&amp;amp;lt;span&amp;amp;gt;&amp;lt;/code&amp;gt; tag with the string as a class&lt;br /&gt;
* If the replacements object is a function, the inner text will be passed as an argument to the function, and the return value will replace the text and the delimiters&lt;br /&gt;
&lt;br /&gt;
== On server side (PHP) ==&lt;br /&gt;
&lt;br /&gt;
On PHP side, you can use 3 different functions to specify that a string must be translated.&lt;br /&gt;
&lt;br /&gt;
=== Function clienttranslate ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;clienttranslate( &#039;string to translate&#039; ):&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
This function is &#039;&#039;transparent&#039;&#039;: it will return the original English string without any change. Its only purpose is to mark this string as &amp;quot;must be translated&amp;quot;, and to make sure the translated version of the string will be available on client side.&lt;br /&gt;
&lt;br /&gt;
In general, you use clienttranslate:&lt;br /&gt;
* In your &#039;&#039;&#039;states.inc.php&#039;&#039;&#039;, for the fields &amp;quot;description&amp;quot; and &amp;quot;descriptionmyturn&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
      &amp;quot;description&amp;quot; =&amp;gt; clienttranslate(&#039;${card_name}: ${actplayer} must discard 4 identical energies&#039;),&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* In &#039;&#039;&#039;material.inc.php&#039;&#039;&#039;, when defining text for game materials that must be displayed on the client side.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$this-&amp;gt;card_types = array(&lt;br /&gt;
&lt;br /&gt;
     1 =&amp;gt; array(&lt;br /&gt;
        &#039;name&#039; =&amp;gt; clienttranslate(&#039;Amulet of Air&#039;), // Thus, we can use &amp;quot;_( card_name )&amp;quot; on Javascript side.&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* When sending a notification with &#039;&#039;notifyAllPlayers&#039;&#039; or &#039;&#039;notifyPlayer&#039;&#039;, in the game log string and all game log arguments that need a translation.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
     // A game log string with no argument:&lt;br /&gt;
     self::notifyAllPlayers( &#039;pickLibraryCards&#039;, clienttranslate(&#039;Everyone draw cards from their library&#039;), [] );&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
As a consequence there is no point passing variables to this function. E.g.:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    notif=&amp;quot;foo&amp;quot;;&lt;br /&gt;
    self::notifyAllPlayers( &#039;log&#039;, clienttranslate(notif),[]); // BAD&lt;br /&gt;
    &lt;br /&gt;
    notif=clienttranslate(&amp;quot;foo&amp;quot;);&lt;br /&gt;
    self::notifyAllPlayers( &#039;log&#039;, notif,[]); // GOOD&lt;br /&gt;
&lt;br /&gt;
    self::notifyAllPlayers( &#039;log&#039;, clienttranslate(&amp;quot;player gains ${num} gems&amp;quot;),[num=&amp;gt;2]); // BAD it is dynamic string enterpreted by php &lt;br /&gt;
    self::notifyAllPlayers( &#039;log&#039;, clienttranslate(&#039;player gains ${num} gems&#039;),[num=&amp;gt;2]); // GOOD, difference is single quotes&lt;br /&gt;
&lt;br /&gt;
    self::notifyAllPlayers( &#039;log&#039;, clienttranslate(&amp;quot;player gains &amp;quot;.${num}.&amp;quot; gems&amp;quot;),[num=&amp;gt;2]); // BAD concatenation &lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Translating arguments is a little bit more complex. This uses the &#039;&#039;&#039;i18n&#039;&#039;&#039; special argument as below:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 // In the following example, we translate the game log itself, but also the &amp;quot;card_name&amp;quot; argument:&lt;br /&gt;
&lt;br /&gt;
 self::notifyAllPlayers( &#039;winPoints&#039;, clienttranslate(&#039;${card_name}: ${player_name} gains ${points} point(s)&#039;), array(&lt;br /&gt;
                &#039;i18n&#039; =&amp;gt; array( &#039;card_name&#039; ),     // &amp;lt;===== We specify here that &amp;quot;card_name&amp;quot; argument must be translated&lt;br /&gt;
                &#039;player_id&#039; =&amp;gt; $player_id,&lt;br /&gt;
                &#039;player_name&#039; =&amp;gt; self::getActivePlayerName(),&lt;br /&gt;
                &#039;points&#039; =&amp;gt; $points,&lt;br /&gt;
                &#039;card_name&#039; =&amp;gt; $this-&amp;gt;card_types[8][&#039;name&#039;] // &amp;lt;==== Here, we provide original English string.&lt;br /&gt;
            ) ); &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
To ensure the translation of the i18n argument will be made, clienttranslate must have been used somewhere, for instance:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$this-&amp;gt;card_types = array(&lt;br /&gt;
...&lt;br /&gt;
     8 =&amp;gt; array(&lt;br /&gt;
        &#039;name&#039; =&amp;gt; clienttranslate(&amp;quot;Amulet of Fire&amp;quot;),&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Pay attention when using the &#039;&#039;&#039;i18n&#039;&#039;&#039; argument when translating arguments for the client: do NOT use same argument for both translations AND key codes for client-side actions (like using &#039;card_name&#039; to move it on the player board as described in the example). It&#039;s pretty obvious in the example, but it can be very tricky when translation is made at the end of the development (which is often the case). Use explicit argument names like &#039;card_name_translated&#039; by example.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;WARNING:&#039;&#039;&#039; you should NEVER use concatenation with &#039;&#039;clienttranslate&#039;&#039;, as it would result in a different string to translate at runtime than the one retrieved statically in the translation system, and so translation would not be applied. If you need to compose a string, use substitution and the i18n parameter (but you also have to pay attention not to compose sentences in a way that is dependent upon the English language specific syntax, or it may be impossible to translate correctly in another language: sometimes, you need multiple full sentences rather than relying on substitution).&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Method _ (underscore) ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;self::_( &amp;quot;my string to translate&amp;quot; ):&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
This function returns a string translated in the language of CURRENT user (i.e. player who send the request to the server) (be careful, this is NOT the active player).&lt;br /&gt;
&lt;br /&gt;
This can be used like self::_(&#039;bla&#039;) or this-&amp;gt;(&#039;bla&#039;). You cannot use static underscore function _(&#039;bla&#039;) in php, it is not the same, it will not translate strings from your game.&lt;br /&gt;
&lt;br /&gt;
The returned string will be surrounded by HTML tags, so you cannot use it in places where pure text is required or your string already has another html markup.&lt;br /&gt;
&lt;br /&gt;
Most of the time, you don&#039;t need to translate strings on server side, except on the following situations:&lt;br /&gt;
* Throwing user exceptions&lt;br /&gt;
* Creating the labels for the game interface used in your template&lt;br /&gt;
* Rarely, in your material.inc.php, if for example you need to use some string elements in your exceptions&lt;br /&gt;
* Rarely, in your &amp;quot;getAllDatas&amp;quot; PHP method, as the data return by this method is used only by current user&lt;br /&gt;
&lt;br /&gt;
Imporant! This function does two things:&lt;br /&gt;
* Mark string for translation&lt;br /&gt;
* Translates in runtime&lt;br /&gt;
As a consequence you absolutely cannot have $var in there! Or string concatenations.&lt;br /&gt;
I.e.&lt;br /&gt;
  $food=self::_(&amp;quot;Banana&amp;quot;);// good&lt;br /&gt;
  self::_(&amp;quot;User gives $food to a cat&amp;quot;); // bad&lt;br /&gt;
For the translator we will have two strings &amp;quot;Banana&amp;quot; and &amp;quot;User gives $food to a cat&amp;quot;, but in runtime we will be&lt;br /&gt;
&amp;quot;Banana&amp;quot; and &amp;quot;User gives Banana to a cat&amp;quot; and second string would not match anything. And this is as bad&lt;br /&gt;
  self::_(&amp;quot;User gives &amp;quot;.$food.&amp;quot; to a cat&amp;quot;);// bad&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Throwing an exception because the player did a forbidden move ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
// This will display a translatable red message to the player that just did some wrong action:&lt;br /&gt;
throw new BgaUserException( self::_(&#039;You must choose 3 cards&#039;) );&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note that the use of BgaUserException signals that this exception is &amp;quot;expected&amp;quot;. In theory, all exception that are expected should be translated.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
// this is the same but with variable&lt;br /&gt;
throw new BgaUserException(sprintf(self::_(&#039;You must choose %d cards&#039;), $card_num));&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Creating labels ====&lt;br /&gt;
&lt;br /&gt;
Simple label in tpl file (i.e. label which has same value independent of anything):&lt;br /&gt;
&lt;br /&gt;
in .tpl:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  &amp;lt;div&amp;gt;{CARDS_FOR_YEAR_2}&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
in .view.php:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$this-&amp;gt;tpl[&#039;CARDS_FOR_YEAR_2&#039;] = self::_(&amp;quot;Your cards for year II&amp;quot;);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Nota bene:&#039;&#039;&#039; it is recommended to set translated text in your interface client side rather than use template variables and server translation, so that translation works natively in replays (that don&#039;t have server side translations). For simple strings, the framework will handle moving the translation client side, but for more complex strings it may not work. In particular, you should not use server side translation for templates with substitution variables (or use the specific function &amp;quot;gameview_str_replace( $search, $replace, $string )&amp;quot; if not possible otherwise or for old code compatibility). Also, you should never use a &amp;quot;to_translate&amp;quot; class in your .tpl as it is used internally by the framework.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Label which is generated based of player&#039;s name, using server side template:&lt;br /&gt;
in .tpl:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  &amp;lt;div id=&amp;quot;empire_title_{COLOR}&amp;quot; class=&amp;quot;side_title color_{COLOR}&amp;quot;&amp;gt;{EMPIRE_LABEL}&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
in .view.php:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        $this-&amp;gt;page-&amp;gt;insert_block(&amp;quot;player_board&amp;quot;, array (&amp;quot;COLOR&amp;quot; =&amp;gt; $color,&amp;quot;PLAYER_NAME&amp;quot; =&amp;gt; $name,&amp;quot;PLAYER_NO&amp;quot; =&amp;gt; $no,&lt;br /&gt;
                &amp;quot;PLAYER_ID&amp;quot; =&amp;gt; $player_id, &amp;quot;CLASSES&amp;quot; =&amp;gt; $own?&amp;quot;own&amp;quot;:&amp;quot;&amp;quot;, &lt;br /&gt;
                &amp;quot;EMPIRE_LABEL&amp;quot; =&amp;gt; self::raw(gameview_str_replace(&#039;${player_name}&#039;, $name, self::_(&#039;${player_name}\&#039;s EMPIRE&#039;)))&lt;br /&gt;
              ));&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Label which is generated based of player&#039;s name, using client side (which is better):&lt;br /&gt;
in .tpl:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  &amp;lt;div id=&amp;quot;empire_title_{COLOR}&amp;quot; class=&amp;quot;side_title color_{COLOR}&amp;quot;&amp;gt;Stub&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
in .js:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  for (var player_id in this.gamedatas.players) {&lt;br /&gt;
      var player_color = this.gamedatas.players[player_id].color;&lt;br /&gt;
      var player_name = this.gamedatas.players[player_id].name;&lt;br /&gt;
      $(&#039;empire_title_&#039;+player_color).innerHTML=this.format_string_recursive(_(&amp;quot;${player_name}&#039;s EMPIRE&amp;quot;), {player_name: player_name});&lt;br /&gt;
  }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Translating strings in material file ====&lt;br /&gt;
&lt;br /&gt;
Rarely, in your material.inc.php, if for example you need to use some string elements in your exceptions.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
// In material.inc.php, $this-&amp;gt;energies[n][&#039;nametr&#039;] has been created with the self::_() method. Now we can do this:&lt;br /&gt;
throw new BgaUserException( self::_(&amp;quot;To execute this action you need more: &amp;quot;).&#039; &#039;.$this-&amp;gt;energies[$resource_id][&#039;nametr&#039;] );&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note: you could also do this, so you don&#039;t need to pollute your material file&lt;br /&gt;
   throw new BgaUserException( self::_(&amp;quot;To execute this action you need more: &amp;quot;).&#039; &#039;.self::_($this-&amp;gt;energies[$resource_id][&#039;name&#039;]) );&lt;br /&gt;
&lt;br /&gt;
where $this-&amp;gt;energies[$resource_id][&#039;name&#039;] were marked in material file using regular clienttranslate function&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  $this-&amp;gt;energies = [&lt;br /&gt;
      22 =&amp;gt; [&lt;br /&gt;
          &#039;name&#039; =&amp;gt; clienttranslate(&#039;Sun&#039;)&lt;br /&gt;
          ...&lt;br /&gt;
      ]&lt;br /&gt;
  ];&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Strings in getAllDatas ====&lt;br /&gt;
&lt;br /&gt;
Rarely, in your &amp;quot;getAllDatas&amp;quot; PHP method, as the data return by this method is used only by current user.&lt;br /&gt;
&lt;br /&gt;
Note: not sure why would you send strings from the server in this case, as same can be achieved on the client usually.&lt;br /&gt;
&lt;br /&gt;
=== Function totranslate ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;totranslate( &amp;quot;my string to translate&amp;quot; ):&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
This function works exactly like &#039;clienttranslate&#039;, except it tells BGA that the string is not needed on client side.&lt;br /&gt;
&lt;br /&gt;
You should not use this function, except on the following cases:&lt;br /&gt;
* Statistics name in stats.inc.php&lt;br /&gt;
* Option names and option values name in gameoptions.inc.php&lt;br /&gt;
&lt;br /&gt;
== Top Secret Undocumented Features ==&lt;br /&gt;
&lt;br /&gt;
If your string contains the clause &#039;$${value}&#039; (such as &#039;You gain $${value}.&#039;) then the translation system seems to move the position of the $ to a localized location (eg $5 in English but 5$ in French). This only seems to occur when using the argument &#039;value&#039;.&lt;br /&gt;
&lt;br /&gt;
In JavaScript, you can get the current user&#039;s language by retrieving the translation for the special string &amp;quot;$locale&amp;quot;:&lt;br /&gt;
&lt;br /&gt;
    var lang = _(&#039;$locale&#039;); // en, fr, etc.&lt;br /&gt;
&lt;br /&gt;
== On server side - advanced (PHP) ==&lt;br /&gt;
&lt;br /&gt;
If you want to use translation system in your custom static modules, you will first need to expose the _() function :&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
class mygame extends Table {&lt;br /&gt;
  // Exposing protected method translation&lt;br /&gt;
  public static function totranslate($text) {&lt;br /&gt;
    return self::_($text);&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Then you&#039;ll be able to use this directly in other modules by doing&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
throw new BgaUserException(mygame::totranslate(&amp;quot;Translated error from my awesome module file&amp;quot;));&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Notice how the &amp;quot;totranslate&amp;quot; is also used by the static analysis to detect your string. So the following will not work :&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$msg = &amp;quot;Translated error from my awesome module file&amp;quot;;&lt;br /&gt;
throw new BgaUserException(mygame::totranslate($msg));&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Preview another language ==&lt;br /&gt;
&lt;br /&gt;
Once a game is released, you can view a table as a specific language by appending a language code to the URL, such as &amp;lt;pre&amp;gt;&amp;amp;lang=es&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Analyze your project ==&lt;br /&gt;
&lt;br /&gt;
It looks super complex but there is help!&lt;br /&gt;
On studio control panel you can find a button &amp;quot;Check project&amp;quot; - it runs bunch of static analysis on your project including scanning for bad translations and missing translations.&lt;br /&gt;
It also will extact all you translation keys as translator will see them so you can double check - and run spell checker on them.&lt;br /&gt;
&lt;br /&gt;
== Other Useful Links ==&lt;br /&gt;
&lt;br /&gt;
* BLOG post about translations https://bga-devs.github.io/blog/posts/translations-summary/&lt;br /&gt;
&lt;br /&gt;
[[Category:Studio]]&lt;/div&gt;</summary>
		<author><name>Sguzzer Gunayer</name></author>
	</entry>
	<entry>
		<id>https://en.doc.boardgamearena.com/index.php?title=Main_game_logic:_Game.php&amp;diff=22645</id>
		<title>Main game logic: Game.php</title>
		<link rel="alternate" type="text/html" href="https://en.doc.boardgamearena.com/index.php?title=Main_game_logic:_Game.php&amp;diff=22645"/>
		<updated>2024-09-18T17:55:40Z</updated>

		<summary type="html">&lt;p&gt;Sguzzer Gunayer: /* Actions (autowired) */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Studio_Framework_Navigation}}&lt;br /&gt;
&lt;br /&gt;
This is the main file for your game logic. Here you initialize the game, persist data, implement the rules and notify the client interface of changes.&lt;br /&gt;
&lt;br /&gt;
This is the main  class that implements the &amp;quot;server&amp;quot; callbacks. As it is a server it cannot initiate any data communicate with the game client (running in browser) and only can respond to client using notifications.&lt;br /&gt;
&lt;br /&gt;
Your php class instance won&#039;t be in memory between two callbacks, every time client send a request a new class will be created, constructor will be called and eventually your callback function.&lt;br /&gt;
&lt;br /&gt;
== File Structure ==&lt;br /&gt;
&lt;br /&gt;
The details of how the file is structured are described directly with comments in the code skeleton provided to you.&lt;br /&gt;
 &lt;br /&gt;
Here is the basic structure:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;__construct&#039;&#039;&#039;: the game constructor, where you define global variables and initiaze class members.&lt;br /&gt;
* &#039;&#039;&#039;setupNewGame&#039;&#039;&#039;: initial setup of the game. Takes an array of players, indexed by player_id. Structure of each player includes player_name, player_canal, player_avatar, and flags indicating admin/ai/premium/order/language/beginner.&lt;br /&gt;
* &#039;&#039;&#039;getAllDatas&#039;&#039;&#039;: where you retrieve all game data during a complete reload of the game. Return value must be associative array. Value of &#039;players&#039; is reserved for returning players data from players table, if you set it it must follow certain rules &lt;br /&gt;
        $result [&#039;players&#039;] = $this-&amp;gt;getCollectionFromDb(&amp;quot;SELECT player_id id, player_score score, player_no no, player_color color FROM player&amp;quot;);&lt;br /&gt;
        // Returned value must include [&#039;players&#039;][$player_id]][&#039;score&#039;] for scores to populate when F5 is pressed.&lt;br /&gt;
* &#039;&#039;&#039;getGameProgression&#039;&#039;&#039;: where you compute the game progression indicator. Returns a number indicating percent of progression (0-100). Used to calculate ELO changes of remaining players when a player quits, or as a conceding requirement (in non-tournament 2 player games, a player may concede if the progression is at least 50%).&lt;br /&gt;
* Utility functions: your utility functions.&lt;br /&gt;
* Player actions: the entry points for players actions ([https://en.doc.boardgamearena.com/Players_actions:_yourgamename.action.php more info here]). &lt;br /&gt;
* Game state arguments: methods to return additional data on specific game states ([http://en.doc.boardgamearena.com/Your_game_state_machine:_states.inc.php#args more info here]).&lt;br /&gt;
* Game state actions: the logic to run when entering a new game state ([http://en.doc.boardgamearena.com/Your_game_state_machine:_states.inc.php#action more info here]).&lt;br /&gt;
* &#039;&#039;&#039;initTable&#039;&#039;&#039;: (not part of template) - this function is called for every php callback by the framework and it can be implement by the game (empty by default). You can use it in rare cases where you need to read database and manipulate some data before any ANY php entry functions are called (such as getAllDatas,action*,st*, etc). Note: it is not called before arg* methods &lt;br /&gt;
* &#039;&#039;&#039;zombieTurn&#039;&#039;&#039;: what to do it&#039;s the turn of a zombie player.&lt;br /&gt;
* &#039;&#039;&#039;upgradeTableDb&#039;&#039;&#039;: function to migrate database if you change it after release on production.&lt;br /&gt;
* &#039;&#039;&#039;getGameName&#039;&#039;&#039;: returns the game name. This will be setup when you create the project. If you are copying files in from another project, make sure you keep this function intact. It must return the right game name, or lots of things will be broken.&lt;br /&gt;
&lt;br /&gt;
== Accessing player information ==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Important&#039;&#039;&#039;: In the following methods, be mindful of the difference between the &amp;quot;active&amp;quot; player and the &amp;quot;current&amp;quot; player. The &#039;&#039;&#039;active&#039;&#039;&#039; player is the player whose turn it is - not necessarily the player who sent a request! The &#039;&#039;&#039;current&#039;&#039;&#039; player is the player who sent the request and will see the results returned by your methods: not necessarily the player whose turn it is!&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
; getPlayersNumber()&lt;br /&gt;
: Returns the number of players playing at the table&lt;br /&gt;
: Note: doesn&#039;t work in the beggining of setupNewGame (use count($players) instead). It will work after initialization of player table.&lt;br /&gt;
&lt;br /&gt;
; getActivePlayerId()&lt;br /&gt;
: Get the &amp;quot;active_player&amp;quot;, whatever what is the current state type.&lt;br /&gt;
: Note: it does NOT mean that this player is active right now, because state type could be &amp;quot;game&amp;quot; or &amp;quot;multiplayer&amp;quot;&lt;br /&gt;
: Note: avoid using this method in a &amp;quot;multiplayer&amp;quot; state because it does not mean anything.&lt;br /&gt;
&lt;br /&gt;
; getActivePlayerName()&lt;br /&gt;
: Get the &amp;quot;active_player&amp;quot; name&lt;br /&gt;
: Note: avoid using this method in a &amp;quot;multiplayer&amp;quot; state because it does not mean anything.&lt;br /&gt;
&lt;br /&gt;
; getPlayerNameById($player_id)&lt;br /&gt;
: Get the name by id&lt;br /&gt;
&lt;br /&gt;
; getPlayerColorById($player_id)&lt;br /&gt;
: Get the color by id&lt;br /&gt;
&lt;br /&gt;
; getPlayerNoById($player_id)&lt;br /&gt;
: Get &#039;player_no&#039; (number) by id&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
; loadPlayersBasicInfos()&lt;br /&gt;
: Get an associative array with generic data about players (ie: not game specific data).&lt;br /&gt;
: The key of the associative array is the player id. The returned table is cached, so ok to call multiple times without performance concerns.&lt;br /&gt;
: The content of each value is:&lt;br /&gt;
: * player_name - the name of the player&lt;br /&gt;
: * player_color (ex: ff0000) - the color code of the player (as string)&lt;br /&gt;
: * player_no - the position of the player at the start of the game in natural table order, i.e. 1,2,3&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
                $players = $this-&amp;gt;loadPlayersBasicInfos();&lt;br /&gt;
                foreach ($players as $player_id =&amp;gt; $info) {&lt;br /&gt;
                    $player_color = $info[&#039;player_color&#039;];&lt;br /&gt;
                    ...&lt;br /&gt;
                }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Note: if you want array of player ids only you can do this:&lt;br /&gt;
    $player_ids =  array_keys($this-&amp;gt;loadPlayersBasicInfos());  &lt;br /&gt;
&lt;br /&gt;
; getCurrentPlayerId(bool $bReturnNullIfNotLogged = false) int&lt;br /&gt;
: Get the &amp;quot;current_player&amp;quot;. The current player is the one from which the action originated (the one who sent the request).&lt;br /&gt;
: &#039;&#039;&#039;Be careful&#039;&#039;&#039;: This is not necessarily the active player!&lt;br /&gt;
: In general, you shouldn&#039;t use this method, unless you are in &amp;quot;multiplayer&amp;quot; state.&lt;br /&gt;
: &#039;&#039;&#039;Very important&#039;&#039;&#039;: in your setupNewGame and zombieTurn function, you must never use getCurrentPlayerId() or getCurrentPlayerName(), &lt;br /&gt;
: otherwise it will fail with a &amp;quot;Not logged&amp;quot; error message (these actions are triggered from the main site and propagated to the gameserver from a server, not from a browser. As a consequence, there is no current player associated to these actions).&lt;br /&gt;
&lt;br /&gt;
; getCurrentPlayerName(bool $bReturnEmptyIfNotLogged = false) string&lt;br /&gt;
: Get the &amp;quot;current_player&amp;quot; name. &lt;br /&gt;
: Note: this will throw an exception if current player is not at the table, i.e. spectator&lt;br /&gt;
: Be careful using this method (see above).&lt;br /&gt;
&lt;br /&gt;
; getCurrentPlayerColor()&lt;br /&gt;
: Get the &amp;quot;current_player&amp;quot; color. &lt;br /&gt;
: Note: this will throw an exception if current player is not at the table, i.e. spectator&lt;br /&gt;
: Be careful using this method (see above).&lt;br /&gt;
&lt;br /&gt;
; isCurrentPlayerZombie()&lt;br /&gt;
: Check the &amp;quot;current_player&amp;quot; zombie status. If true, player is zombie, i.e. left or was kicked out of the game.&lt;br /&gt;
: Note: this will throw an exception if current player is not at the table, i.e. spectator&lt;br /&gt;
&lt;br /&gt;
; isSpectator()&lt;br /&gt;
: Check the &amp;quot;current_player&amp;quot; spectator status. If true, the user accessing the game is a spectator (not part of the game). For this user, the interface should display all public information, and no private information (like a friend sitting at the same table as players and just spectating the game).&lt;br /&gt;
&lt;br /&gt;
; getActivePlayerColor()&lt;br /&gt;
: This function does not seems to exist in API, if you need it here is implementation&lt;br /&gt;
      function getActivePlayerColor() {&lt;br /&gt;
        $player_id = $this-&amp;gt;getActivePlayerId();&lt;br /&gt;
        $players = $this-&amp;gt;loadPlayersBasicInfos();&lt;br /&gt;
        if (isset($players[$player_id]))&lt;br /&gt;
            return $players[$player_id][&#039;player_color&#039;];&lt;br /&gt;
        else&lt;br /&gt;
            return null;&lt;br /&gt;
    }&lt;br /&gt;
; isPlayerZombie($player_id)&lt;br /&gt;
: This method does not exists, but if you need it it looks like this&lt;br /&gt;
    protected function isPlayerZombie($player_id) {&lt;br /&gt;
        $players = $this-&amp;gt;loadPlayersBasicInfos();&lt;br /&gt;
        if (! isset($players[$player_id]))&lt;br /&gt;
            throw new BgaSystemException(&amp;quot;Player $player_id is not playing here&amp;quot;);&lt;br /&gt;
        &lt;br /&gt;
        return ($players[$player_id][&#039;player_zombie&#039;] == 1);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
== Accessing the database ==&lt;br /&gt;
&lt;br /&gt;
The main game logic should be the only point from which you should access the game database. You access your database using SQL queries with the methods below.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;IMPORTANT&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
BGA uses [http://dev.mysql.com/doc/refman/5.0/en/sql-syntax-transactions.html database transactions]. This means that your database changes WON&#039;T BE APPLIED to the database until your request ends normally (web request, not database request). Using transactions is in fact very useful for you; at any time, if your game logic detects that something is wrong (example: a disallowed move), you just have to throw an exception and all changes to the game situation will be removed. This also means that you need not (and in fact cannot) use your own transactions for multiple related database operations.&lt;br /&gt;
&lt;br /&gt;
However there are sets of database operation that will do implicit commit (most common mistake is to use &amp;quot;TRUNCATE&amp;quot;), you cannot use these operations during the game, it breaks the unrolling of transactions and will lead to nasty issues&lt;br /&gt;
(https://mariadb.com/kb/en/sql-statements-that-cause-an-implicit-commit).&lt;br /&gt;
&lt;br /&gt;
All methods below are part of game class (and view class) and can be accessed using $this-&amp;gt;&lt;br /&gt;
&lt;br /&gt;
; DbQuery( string $sql )&lt;br /&gt;
: This is the generic method to access the database.&lt;br /&gt;
: It can execute any type of SELECT/UPDATE/DELETE/REPLACE/INSERT query on the database. Returns result of the query.&lt;br /&gt;
: For SELECT queries, the specialized methods below are much better.&lt;br /&gt;
: Do not use method for TRUNCATE, DROP and other table altering operations. See disclamer above about implicit commits. If you really need TRUNCATE use DELETE FROM xxx instead.&lt;br /&gt;
&lt;br /&gt;
; getUniqueValueFromDB( string $sql )&lt;br /&gt;
: Returns a unique value from DB or null if no value is found.&lt;br /&gt;
: $sql must be a SELECT query.&lt;br /&gt;
: Raise an exception if more than 1 row is returned.&lt;br /&gt;
&lt;br /&gt;
; getCollectionFromDB( string $sql, bool $bSingleValue=false ) array&lt;br /&gt;
: Returns an associative array of rows for a sql SELECT query.&lt;br /&gt;
: The key of the resulting associative array is the first field specified in the SELECT query.&lt;br /&gt;
: The value of the resulting associative array is an associative array with all the field specified in the SELECT query and associated values.&lt;br /&gt;
: First column must be a primary or alternate key (semantically, it does not actually have to declared in sql as such).&lt;br /&gt;
: The resulting collection can be empty (it won&#039;t be null).&lt;br /&gt;
: If you specified $bSingleValue=true and if your SQL query requests 2 fields A and B, the method returns an associative array &amp;quot;A=&amp;gt;B&amp;quot;, otherwise its A=&amp;gt;[A,B]&lt;br /&gt;
: Note: The name a bit misleading, it really return associative array, i.e. map and NOT a collection. You cannot use it to get list of values which may have duplicates (hence primary key requirement on first column). If you need simple array use getObjectListFromDB() method.&lt;br /&gt;
&lt;br /&gt;
Example 1:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$result = $this-&amp;gt;getCollectionFromDB( &amp;quot;SELECT player_id id, player_name name, player_score score FROM player&amp;quot; );&lt;br /&gt;
&lt;br /&gt;
Result:&lt;br /&gt;
[&lt;br /&gt;
 1234 =&amp;gt; [ &#039;id&#039;=&amp;gt;1234, &#039;name&#039;=&amp;gt;&#039;myuser0&#039;, &#039;score&#039;=&amp;gt;1 ],&lt;br /&gt;
 1235 =&amp;gt; [ &#039;id&#039;=&amp;gt;1235, &#039;name&#039;=&amp;gt;&#039;myuser1&#039;, &#039;score&#039;=&amp;gt;0 ]&lt;br /&gt;
]&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Example 2:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$result = $this-&amp;gt;getCollectionFromDB( &amp;quot;SELECT player_id id, player_name name FROM player&amp;quot;, true );&lt;br /&gt;
&lt;br /&gt;
Result:&lt;br /&gt;
[&lt;br /&gt;
 1234 =&amp;gt; &#039;myuser0&#039;,&lt;br /&gt;
 1235 =&amp;gt; &#039;myuser1&#039;&lt;br /&gt;
]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
; getNonEmptyCollectionFromDB(string $sql) array&lt;br /&gt;
: Same as getCollectionFromDB($sdl), but raise an exception if the collection is empty. Note: this function does NOT have 2nd argument as previous one does.&lt;br /&gt;
&lt;br /&gt;
; getObjectFromDB(string $sql) array&lt;br /&gt;
: Returns one row for the sql SELECT query as an associative array or null if there is no result (where fields are keys mapped to values)&lt;br /&gt;
: Raise an exception if the query return more than one row (you can use LIMIT 1 in the query to avoid the exception)&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$result = $this-&amp;gt;getObjectFromDB( &amp;quot;SELECT player_id id, player_name name, player_score score FROM player WHERE player_id=&#039;$player_id&#039;&amp;quot; );&lt;br /&gt;
&lt;br /&gt;
Result:&lt;br /&gt;
[&lt;br /&gt;
  &#039;id&#039;=&amp;gt;1234, &#039;name&#039;=&amp;gt;&#039;myuser0&#039;, &#039;score&#039;=&amp;gt;1 &lt;br /&gt;
]&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
; getNonEmptyObjectFromDB(string $sql) array&lt;br /&gt;
: Similar to previous one, but raise an exception if no row is found&lt;br /&gt;
&lt;br /&gt;
; getObjectListFromDB(string $sql, bool $bUniqueValue=false) array&lt;br /&gt;
: Return an array of rows for a sql SELECT query.&lt;br /&gt;
: The result is the same as &amp;quot;getCollectionFromDB&amp;quot; except that the result is a simple array (and not an associative array).&lt;br /&gt;
: The result can be empty.&lt;br /&gt;
: If you specified $bUniqueValue=true and if your SQL query request 1 field, the method returns directly an array of values.&lt;br /&gt;
&lt;br /&gt;
Example 1:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$result = $this-&amp;gt;getObjectListFromDB( &amp;quot;SELECT player_id id, player_name name, player_score score FROM player&amp;quot; );&lt;br /&gt;
&lt;br /&gt;
Result:&lt;br /&gt;
[&lt;br /&gt;
 [ &#039;id&#039;=&amp;gt;1234, &#039;name&#039;=&amp;gt;&#039;myuser0&#039;, &#039;score&#039;=&amp;gt;1 ],&lt;br /&gt;
 [ &#039;id&#039;=&amp;gt;1235, &#039;name&#039;=&amp;gt;&#039;myuser1&#039;, &#039;score&#039;=&amp;gt;0 ]&lt;br /&gt;
]&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Example 2:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$result = $this-&amp;gt;getObjectListFromDB( &amp;quot;SELECT player_name name FROM player&amp;quot;, true );&lt;br /&gt;
&lt;br /&gt;
Result:&lt;br /&gt;
[&lt;br /&gt;
 &#039;myuser0&#039;,&lt;br /&gt;
 &#039;myuser1&#039;&lt;br /&gt;
]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
; getDoubleKeyCollectionFromDB(string $sql, bool $bSingleValue=false) array&lt;br /&gt;
: Return an associative array of associative array, from a SQL SELECT query.&lt;br /&gt;
: First array level correspond to first column specified in SQL query.&lt;br /&gt;
: Second array level correspond to second column specified in SQL query.&lt;br /&gt;
: If $bSingleValue = true, keep only third column on result&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
; DbGetLastId()&lt;br /&gt;
: Return the PRIMARY key of the last inserted row (see PHP mysql_insert_id function).&lt;br /&gt;
&lt;br /&gt;
; DbAffectedRow() int&lt;br /&gt;
: Return the number of row affected by the last operation&lt;br /&gt;
&lt;br /&gt;
; escapeStringForDB(string $string) string&lt;br /&gt;
: You must use this function on every string type data in your database that contains unsafe data.&lt;br /&gt;
: (unsafe = can be modified by a player).&lt;br /&gt;
: This method makes sure that no SQL injection will be done through the string used.&lt;br /&gt;
: Note: if you using standard types in ajax actions, like AT_alphanum it is sanitized before arrival,&lt;br /&gt;
: this is only needed if you manage to get unchecked string, like in the games where user has to enter text as a response.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note: see Editing [[Game database model: dbmodel.sql]] to know how to define your database model.&lt;br /&gt;
&lt;br /&gt;
== Use globals ==&lt;br /&gt;
Sometimes, you want a single global value for your game, and you don&#039;t want to create a DB table specifically for it.&lt;br /&gt;
&lt;br /&gt;
You can do this with the BGA framework &amp;quot;globals&amp;quot;. Your value will be stored in the &amp;quot;bga_globals&amp;quot; table in the database, and you can access it with simple methods.&lt;br /&gt;
&lt;br /&gt;
The keys are strings, so you might want to store them in constants to avoid mistakes (the key must be at maximum 50 characters long).&lt;br /&gt;
&lt;br /&gt;
The variable can be of any type (number, string, array, object) and will be stored as a JSON (so functions cannot be stored, and circular references on objects will trigger an Exception when storing).&lt;br /&gt;
&lt;br /&gt;
Having a string key and a JSON serialization allows you to debug easily by looking at the bga_globals table content.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Note: this globals module doesn&#039;t use cache, so every call to one of the following methods makes a DB request.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;globals-&amp;gt;set(string $name, $mixed $obj): void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Define the value of a global variable.  &lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
const FIRST_PLAYER_ID = &amp;quot;firstPlayerId&amp;quot;;&lt;br /&gt;
$this-&amp;gt;globals-&amp;gt;set(FIRST_PLAYER_ID, array_keys($players)[0]);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;globals-&amp;gt;get(string $name, $mixed $defaultValue = null): mixed&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Get the value of a global variable. Returns `null` if not set, except specified otherwise in the optional `$defaultValue`.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$currentFirstPlayerId = $this-&amp;gt;globals-&amp;gt;get(FIRST_PLAYER_ID);&lt;br /&gt;
...&lt;br /&gt;
$selectedCardsIds = $this-&amp;gt;globals-&amp;gt;get(SELECTED_CARDS_IDS, []);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;globals-&amp;gt;getAll(...$names): array&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Get the value of all global variables, as a key=&amp;gt;value array. You can set a list of names to only get matching variables. In that case, non-existent keys will not be set in the returned array, so if you have a key with null value, it means the key has been set to null previously.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$variables = $this-&amp;gt;globals-&amp;gt;getAll();&lt;br /&gt;
...&lt;br /&gt;
$diceVariables = $this-&amp;gt;globals-&amp;gt;getAll(DIE1, DIE2);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Use with PHP&#039;s [https://www.php.net/extract extract()] function to quickly assign multiple variables:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
extract($this-&amp;gt;globals-&amp;gt;getAll(&#039;endTime&#039;, &#039;hour&#039;, &#039;vipWelcome&#039;));&lt;br /&gt;
// $endTime, $hour, and $vipWelcome (may) now exist&lt;br /&gt;
&lt;br /&gt;
if (!empty($endTime)) {&lt;br /&gt;
   ...&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;globals-&amp;gt;delete(...$names): void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Delete a global variable or a list of global variables stored in database.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$this-&amp;gt;globals-&amp;gt;delete(SELECTED_CARDS_IDS);&lt;br /&gt;
...&lt;br /&gt;
$this-&amp;gt;globals-&amp;gt;delete(SELECTED_CARDS_IDS, UNDO, AFTER_DISCARD_RETURN_STATE);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;globals-&amp;gt;has(string $name): bool&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Indicates if a global variable is stored in database.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$cardSelectionIsStarted = $this-&amp;gt;globals-&amp;gt;has(SELECTED_CARDS_IDS);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;globals-&amp;gt;inc(string $name, $int $inc): int&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Increments the value of a global variable, and return the incremented value. Will trigger an exception if the variable is not a numeric value.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$this-&amp;gt;globals-&amp;gt;inc(PLAYED_ACTIONS_IN_CURRENT_TURN, 1);&lt;br /&gt;
...&lt;br /&gt;
$totalSpent = $this-&amp;gt;globals-&amp;gt;inc(SPENT_COINS_IN_CURRENT_TURN, $cardCost);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Use globals (numbers only / game options) ==&lt;br /&gt;
&lt;br /&gt;
Before the `$this-&amp;gt;globals`, you could only store numeric values as globals. Theses &amp;quot;GameStateValues&amp;quot; are stored in the &amp;quot;global&amp;quot; table in the database, and you can access it with simple methods.&lt;br /&gt;
&lt;br /&gt;
All methods below are members of the game class and should be accessed via $this-&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;initGameStateLabels(array $labelsMap): void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
This method should be located at the beginning of constructor of &#039;&#039;yourgamename.game.php&#039;&#039;. This is where you define the globals used in your game logic, by assigning them IDs.&lt;br /&gt;
&lt;br /&gt;
You can define up to 80 globals, with IDs from 10 to 89 (inclusive, there can be gaps). &lt;br /&gt;
Also you must use this method to access value of game options [[Game_options_and_preferences:_gameoptions.inc.php]], in that case, IDs need to be between 100 and 199.&lt;br /&gt;
You must &#039;&#039;&#039;not&#039;&#039;&#039; use globals outside the range defined above, as those values are used by other components of the framework.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
   function __construct() {&lt;br /&gt;
        parent::__construct();&lt;br /&gt;
        $this-&amp;gt;initGameStateLabels([ &lt;br /&gt;
                &amp;quot;my_first_global_variable&amp;quot; =&amp;gt; 10,&lt;br /&gt;
                &amp;quot;my_second_global_variable&amp;quot; =&amp;gt; 11,&lt;br /&gt;
                &amp;quot;my_game_variant&amp;quot; =&amp;gt; 100&lt;br /&gt;
        ]);&lt;br /&gt;
         // other code ...&lt;br /&gt;
   }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
NOTE: The methods below WILL throw an exception if label is not defined using the call above.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;setGameStateInitialValue( string $label, int $value ): void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Initialize global value. This is not required if you ok with default value if 0. This should be called from setupNewGame function.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;getGameStateValue( string $label, int $default = 0): int&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Retrieve the value of a global. Returns $default if global is not been initialized (by setGameStateInitialValue).&lt;br /&gt;
&lt;br /&gt;
NOTE: this method use globals &amp;quot;cache&amp;quot; if you directly manipulated globals table OR call this function after undoRestorePoint() - it won&#039;t work as expected.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  $value = $this-&amp;gt;getGameStateValue(&#039;my_first_global_variable&#039;);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
For debugging purposes, you can have labels and value pairs send to client side by inserting that code in your &amp;quot;getAllDatas&amp;quot;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$labels = array_keys($this-&amp;gt;mygamestatelabels);&lt;br /&gt;
$result[&#039;myglobals&#039;] = array_combine($labels, array_map([$this,&#039;getGameStateValue&#039;],$labels));&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
That assumes you stored your label mapping in $this-&amp;gt;mygamestatelabels in constructor&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  $this-&amp;gt;mygamestatelabels=[&amp;quot;my_first_global_variable&amp;quot; =&amp;gt; 10, ...];&lt;br /&gt;
  $this-&amp;gt;initGameStateLabels($this-&amp;gt;mygamestatelabels);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;setGameStateValue( string $label, int $value ): void&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Set the current value of a global. &lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  $this-&amp;gt;setGameStateValue(&#039;my_first_global_variable&#039;, 42);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;incGameStateValue( string $label, int $increment ): int&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Increment the current value of a global. If increment is negative, decrement the value of the global.&lt;br /&gt;
&lt;br /&gt;
Return the final value of the global. If global was not initialized it will initialize it as 0.&lt;br /&gt;
&lt;br /&gt;
NOTE: this method use globals &amp;quot;cache&amp;quot; if you directly manipulated globals table OR call this function after undoRestorePoint() - it won&#039;t work as expected.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  $value = $this-&amp;gt;incGameStateValue(&#039;my_first_global_variable&#039;, 1);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== BGA predefined globals ===&lt;br /&gt;
&lt;br /&gt;
BGA already defines some globals in the &#039;&#039;global&#039;&#039; database table. You should not change them directly but it can be useful to know what they mean when debugging:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! global_id !! label !! Meaning&lt;br /&gt;
|-&lt;br /&gt;
| 1 || || Current state &lt;br /&gt;
|-&lt;br /&gt;
| 2 || || Active player id&lt;br /&gt;
|-&lt;br /&gt;
| 3 || next_move_id || Next move number&lt;br /&gt;
|-&lt;br /&gt;
| 4 ||  || Game id&lt;br /&gt;
|-&lt;br /&gt;
| 5 ||  || Table creator id&lt;br /&gt;
|-&lt;br /&gt;
| 6 || playerturn_nbr || Player turn number&lt;br /&gt;
|-&lt;br /&gt;
| 7 || gameprogression || Game progression&lt;br /&gt;
|-&lt;br /&gt;
| 8 || initial_reflexion_time || Initial reflection time&lt;br /&gt;
|-&lt;br /&gt;
| 9 || additional_reflexion_time || Additional reflection time&lt;br /&gt;
|-&lt;br /&gt;
| 200 || reflexion_time_profile ||  Game speed&lt;br /&gt;
Real-time games:&lt;br /&gt;
* 0 = Real-time • Fast paced&lt;br /&gt;
* 1 = Real-time • Normal speed&lt;br /&gt;
* 2 = Real-time • Slow speed&lt;br /&gt;
* 9 = No time limit • with friends only&lt;br /&gt;
&lt;br /&gt;
Turn-based games:&lt;br /&gt;
* 10 = Fast Turn-based • 24 moves per day&lt;br /&gt;
* 11 = Fast Turn-based • 12 moves per day&lt;br /&gt;
* 12 = Fast Turn-based • 8 moves per day&lt;br /&gt;
* 13 = Turn-based • 4 moves per day&lt;br /&gt;
* 14 = Turn-based • 3 moves per day&lt;br /&gt;
* 15 = Turn-based • 2 moves per day&lt;br /&gt;
* 17 = Turn-based • 1 move per day&lt;br /&gt;
* 19 = Turn-based • 1 move per 2 days&lt;br /&gt;
* 20 = No time limit • with friends only&lt;br /&gt;
|-&lt;br /&gt;
| 201 || bgaranking_mode || Game mode&lt;br /&gt;
* 0 = Normal mode&lt;br /&gt;
* 1 = Friendly mode (no ELO)&lt;br /&gt;
* 2 = Arena mode&lt;br /&gt;
|-&lt;br /&gt;
| 207 || game_language ||GAMESTATE_GAME_LANG&lt;br /&gt;
|-&lt;br /&gt;
| 300 || game_db_version ||GAMESTATE_GAMEVERSION: Current version of the game (when in production)&lt;br /&gt;
|-&lt;br /&gt;
| 301 || game_result_neutralized ||GAMESTATE_GAME_RESULT_NEUTRALIZED&lt;br /&gt;
|-&lt;br /&gt;
| 302 || neutralized_player_id ||GAMESTATE_NEUTRALIZED_PLAYER_ID&lt;br /&gt;
|-&lt;br /&gt;
| 304 || undo_moves_stored ||GAMESTATE_UNDO_MOVES_STORED&lt;br /&gt;
|-&lt;br /&gt;
| 305 || undo_moves_player ||GAMESTATE_UNDO_MOVES_PLAYER&lt;br /&gt;
|-&lt;br /&gt;
| 306 || lock_screen_timestamp ||GAMESTATE_LOCK_TIMESTAMP&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Game states and active players ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Activate player handling ===&lt;br /&gt;
&lt;br /&gt;
; $this-&amp;gt;activeNextPlayer()&lt;br /&gt;
: Make the next player active in the natural player order.&lt;br /&gt;
: Note: you CANNOT use this method in a &amp;quot;activeplayer&amp;quot; or &amp;quot;multipleactiveplayer&amp;quot; state. You must use a &amp;quot;game&amp;quot; type game state for this.&lt;br /&gt;
&lt;br /&gt;
; $this-&amp;gt;activePrevPlayer()&lt;br /&gt;
: Make the previous player active (in the natural player order).&lt;br /&gt;
: Note: you CANNOT use this method in a &amp;quot;activeplayer&amp;quot; or &amp;quot;multipleactiveplayer&amp;quot; state. You must use a &amp;quot;game&amp;quot; type game state for this.&lt;br /&gt;
&lt;br /&gt;
; $this-&amp;gt;gamestate-&amp;gt;changeActivePlayer( $player_id )&lt;br /&gt;
: You can call this method to make any player active.&lt;br /&gt;
: Note: you CANNOT use this method in a &amp;quot;activeplayer&amp;quot; or &amp;quot;multipleactiveplayer&amp;quot; state. You must use a &amp;quot;game&amp;quot; type game state for this.&lt;br /&gt;
&lt;br /&gt;
; $this-&amp;gt;getActivePlayerId()&lt;br /&gt;
: Return the &amp;quot;active_player&amp;quot; id&lt;br /&gt;
: Note: it does NOT mean that this player is active right now, because state type could be &amp;quot;game&amp;quot; or &amp;quot;multipleactiveplayer&amp;quot;&lt;br /&gt;
: Note: avoid using this method in a &amp;quot;multipleactiveplayer&amp;quot; state because it does not mean anything.&lt;br /&gt;
&lt;br /&gt;
=== Multiple activate player handling ===&lt;br /&gt;
&lt;br /&gt;
; $this-&amp;gt;gamestate-&amp;gt;setAllPlayersMultiactive()&lt;br /&gt;
: All playing players are made active. Update notification is sent to all players (this will trigger &#039;&#039;&#039;onUpdateActionButtons&#039;&#039;&#039;).&lt;br /&gt;
: Usually, you use this method at the beginning of a game state (e.g., &amp;quot;stGameState&amp;quot;) which transitions to a &#039;&#039;multipleactiveplayer&#039;&#039; state in which multiple players have to perform some action. Do not use this method if you going to make some more changes in the active player list. (I.e., if you want to take away multipleactiveplayer status immediately afterwards, use setPlayersMultiactive instead.)&lt;br /&gt;
&lt;br /&gt;
Example of usage:&lt;br /&gt;
    &amp;lt;pre&amp;gt;&lt;br /&gt;
    function st_MultiPlayerInit() {&lt;br /&gt;
        $this-&amp;gt;gamestate-&amp;gt;setAllPlayersMultiactive();&lt;br /&gt;
    }&lt;br /&gt;
    &amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
; $this-&amp;gt;stMakeEveryoneActive()&lt;br /&gt;
:this method can be used in state machine to make everybody active as &amp;quot;st&amp;quot; method of multiplayeractive state, it just calls $this-&amp;gt;gamestate-&amp;gt;setAllPlayersMultiactive()&lt;br /&gt;
&lt;br /&gt;
This is to be used in state declaration:&lt;br /&gt;
    &amp;lt;pre&amp;gt;&lt;br /&gt;
    2 =&amp;gt; array(&lt;br /&gt;
    		&amp;quot;name&amp;quot; =&amp;gt; &amp;quot;playerTurnPlace&amp;quot;,&lt;br /&gt;
    		&amp;quot;description&amp;quot; =&amp;gt; clienttranslate(&#039;Other player must place ships&#039;),&lt;br /&gt;
    		&amp;quot;descriptionmyturn&amp;quot; =&amp;gt; clienttranslate(&#039;${you} must place ships (click on YOUR SHIPS board to place)&#039;),&lt;br /&gt;
    		&amp;quot;type&amp;quot; =&amp;gt; &amp;quot;multipleactiveplayer&amp;quot;,&lt;br /&gt;
                &#039;action&#039; =&amp;gt; &#039;stMakeEveryoneActive&#039;,&lt;br /&gt;
                &#039;args&#039; =&amp;gt; &#039;arg_playerTurnPlace&#039;,&lt;br /&gt;
    	     	&amp;quot;possibleactions&amp;quot; =&amp;gt; array( &amp;quot;actionBla&amp;quot; ),&lt;br /&gt;
                &amp;quot;transitions&amp;quot; =&amp;gt; array( &amp;quot;next&amp;quot; =&amp;gt; 4, &amp;quot;last&amp;quot; =&amp;gt; 99)&lt;br /&gt;
    ),&lt;br /&gt;
    &amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
; $this-&amp;gt;gamestate-&amp;gt;setAllPlayersNonMultiactive( $next_state )&lt;br /&gt;
: All playing players are made inactive. Transition to next state&lt;br /&gt;
&lt;br /&gt;
; $this-&amp;gt;gamestate-&amp;gt;setPlayersMultiactive( $players, $next_state, $bExclusive = false )&lt;br /&gt;
: Make a specific list of players active during a multiactive gamestate. Update notification is sent to all players whose state changed.&lt;br /&gt;
: &amp;quot;players&amp;quot; is the array of player id that should be made active. If &amp;quot;players&amp;quot; is not empty the value of &amp;quot;next_state&amp;quot; will be ignored (you can put whatever you want)&lt;br /&gt;
: If &amp;quot;bExclusive&amp;quot; parameter is not set or false it doesn&#039;t deactivate other previously active players. If its set to true, the players who will be multiactive at the end are only these in &amp;quot;$players&amp;quot; array&lt;br /&gt;
&lt;br /&gt;
: In case &amp;quot;players&amp;quot; is empty, the method trigger the &amp;quot;next_state&amp;quot; transition to go to the next game state.&lt;br /&gt;
: returns true if state transition happened, false otherwise&lt;br /&gt;
&lt;br /&gt;
; $this-&amp;gt;gamestate-&amp;gt;setPlayerNonMultiactive( $player_id, $next_state )&lt;br /&gt;
: During a multiactive game state, make the specified player inactive.&lt;br /&gt;
: Usually, you call this method during a multiactive game state after a player did his action. It is also possible to call it directly from multiplayer action handler.&lt;br /&gt;
: If this player was the last active player, the method trigger the &amp;quot;next_state&amp;quot; transition to go to the next game state.&lt;br /&gt;
: returns true if state transition happened, false otherwise&lt;br /&gt;
Example of usage (see state declaration of playerTurnPlace above):&lt;br /&gt;
    &amp;lt;pre&amp;gt;&lt;br /&gt;
    function actionBla($args) {&lt;br /&gt;
        $this-&amp;gt;checkAction(&#039;actionBla&#039;);&lt;br /&gt;
        // handle the action using $this-&amp;gt;getCurrentPlayerId()&lt;br /&gt;
        $this-&amp;gt;gamestate-&amp;gt;setPlayerNonMultiactive( $this-&amp;gt;getCurrentPlayerId(), &#039;next&#039;);&lt;br /&gt;
    }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
; $this-&amp;gt;gamestate-&amp;gt;getActivePlayerList()&lt;br /&gt;
: With this method you can retrieve the list of the active player at any time.&lt;br /&gt;
: During a &amp;quot;game&amp;quot; type gamestate, it will return a void array.&lt;br /&gt;
: During a &amp;quot;activeplayer&amp;quot; type gamestate, it will return an array with one value (the active player id).&lt;br /&gt;
: During a &amp;quot;multipleactiveplayer&amp;quot; type gamestate, it will return an array of the active players id.&lt;br /&gt;
: Note: you should only use this method in the latter case.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
;  $this-&amp;gt;gamestate-&amp;gt;updateMultiactiveOrNextState( $next_state_if_none )&lt;br /&gt;
: Sends update notification about multiplayer changes. All multiactive set* functions above do that, however if you want to change state manually using db queries for complex calculations, you have to call this yourself after. Do not call this if you calling one of the other setters above.&lt;br /&gt;
Example: you have player teams and you want to activate all players in one team&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        $sql = &amp;quot;UPDATE player SET player_is_multiactive=&#039;0&#039;&amp;quot;;&lt;br /&gt;
        $this-&amp;gt;DbQuery( $sql );&lt;br /&gt;
        $sql = &amp;quot;UPDATE player SET player_is_multiactive=&#039;1&#039; WHERE player_id=&#039;$player_id&#039; AND player_team=&#039;$team_no&#039;&amp;quot;;&lt;br /&gt;
        $this-&amp;gt;DbQuery( $sql );&lt;br /&gt;
        &lt;br /&gt;
        $this-&amp;gt;gamestate-&amp;gt;updateMultiactiveOrNextState( &#039;error&#039; );&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
; updating database manually&lt;br /&gt;
: Use this helper function to change multiactive state without sending notification&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    /**&lt;br /&gt;
     * Changes values of multiactivity in db, does not sent notifications.&lt;br /&gt;
     * To send notifications after use updateMultiactiveOrNextState&lt;br /&gt;
     * @param number $player_id, player id &amp;lt;=0 or null - means ALL&lt;br /&gt;
     * @param number $value - 1 multiactive, 0 non multiactive&lt;br /&gt;
     */&lt;br /&gt;
    function dbSetPlayerMultiactive($player_id = -1, $value = 1) {&lt;br /&gt;
        if (! $value)&lt;br /&gt;
            $value = 0;&lt;br /&gt;
        else&lt;br /&gt;
            $value = 1;&lt;br /&gt;
        $sql = &amp;quot;UPDATE player SET player_is_multiactive = &#039;$value&#039; WHERE player_zombie = 0 and player_eliminated = 0&amp;quot;;&lt;br /&gt;
        if ($player_id &amp;gt; 0) {&lt;br /&gt;
            $sql .= &amp;quot; AND player_id = $player_id&amp;quot;;&lt;br /&gt;
        }&lt;br /&gt;
        $this-&amp;gt;DbQuery($sql);&lt;br /&gt;
    }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
;$this-&amp;gt;gamestate-&amp;gt;isPlayerActive($player_id)&lt;br /&gt;
:Return true if specified player is active right now.&lt;br /&gt;
:This method take into account game state type, ie nobody is active if game state is &amp;quot;game&amp;quot; and several players can be active if game state is &amp;quot;multiplayer&amp;quot;&lt;br /&gt;
&lt;br /&gt;
;$this-&amp;gt;bIndependantMultiactiveTable&lt;br /&gt;
:This flag can be set to true in constructor of game.php to force creation of second table to handle multiplayer states (normally these are in player table), this is very advanced feature.&lt;br /&gt;
:ONLY use it after you deploy you game to production if you receive unusual amount of bug report with dead lock symptoms DURING multiactiveplayer states&lt;br /&gt;
    function __construct() {&lt;br /&gt;
      ...&lt;br /&gt;
      $this-&amp;gt;bIndependantMultiactiveTable=true;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
=== States functions ===&lt;br /&gt;
; $this-&amp;gt;gamestate-&amp;gt;nextState( $transition )&lt;br /&gt;
: Change current state to a new state. Important: the $transition parameter is the name of the transition, and NOT the name of the target game state, see [[Your game state machine: states.inc.php]] for more information about states.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;$this-&amp;gt;gamestate-&amp;gt;jumpToState($stateNum)&#039;&#039;&#039;&lt;br /&gt;
: Change current state to a new state. Important: the $stateNum parameter is the key of the state. See [[Your game state machine: states.inc.php]] for more information about states.&lt;br /&gt;
: Note: this is very advanced method, it should not be used in normal cases. Specific advanced cases include - jumping to specific state from &amp;quot;do_anytime&amp;quot; actions, jumping to dispatcher state or jumping to recovery state from zombie player function&lt;br /&gt;
&lt;br /&gt;
; $this-&amp;gt;checkAction( $actionName, $bThrowException=true )&lt;br /&gt;
: Check if the current player can perform a specific action in the current game state, and optionally throw an exception if they can&#039;t.&lt;br /&gt;
: The action is valid if it is listed in the &amp;quot;possibleactions&amp;quot; array for the current game state (see game state description).&lt;br /&gt;
: This method MUST be the first one called in ALL your PHP methods that handle player actions that are not using [[Main game logic: yourgamename.game.php#Actions (autowired)|Action autowiring]], in order to make sure a player doesn&#039;t perform an action not allowed by the rules at the point in the game.  It should not be called from methods where the current player is not necessarily the active player, otherwise it may fail with an &amp;quot;It is not your turn&amp;quot; exception.&lt;br /&gt;
: If &amp;quot;bThrowException&amp;quot; is set to &amp;quot;false&amp;quot;, the function returns &#039;&#039;&#039;false&#039;&#039;&#039; in case of failure instead of throwing an exception. This is useful when several actions are possible, in order to test each of them without throwing exceptions.&lt;br /&gt;
&lt;br /&gt;
; $this-&amp;gt;gamestate-&amp;gt;checkPossibleAction( $action )&lt;br /&gt;
: (rarely used)&lt;br /&gt;
: This works exactly like &amp;quot;checkAction&amp;quot; (above), except that it does NOT check if the current player is active.&lt;br /&gt;
: &#039;&#039;&#039;Note: This does NOT check either spectator or eliminated status, so those checks must be done manually.&#039;&#039;&#039;&lt;br /&gt;
: This is used specifically in certain game states when you want to authorize additional actions for players that are not active at the moment.&lt;br /&gt;
: Example: in &#039;&#039;Libertalia&#039;&#039;, you want to authorize players to change their mind about the card played. They are of course not active at the time they change their mind, so you cannot use &amp;quot;checkAction&amp;quot;; use &amp;quot;checkPossibleAction&amp;quot; instead.&lt;br /&gt;
&lt;br /&gt;
This is how PHP action looks that returns player to active state (only for multiplayeractive states). To be able to execute this on client do not call checkAction on js side for this specific action.&lt;br /&gt;
&lt;br /&gt;
   function actionUnpass() {&lt;br /&gt;
        $this-&amp;gt;gamestate-&amp;gt;checkPossibleAction(&#039;actUnpass&#039;); // player changed mind about passing while others were thinking&lt;br /&gt;
        $this-&amp;gt;gamestate-&amp;gt;setPlayersMultiactive(array ($this-&amp;gt;getCurrentPlayerId() ), &#039;error&#039;, false);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
; $this-&amp;gt;gamestate-&amp;gt;state()&lt;br /&gt;
: Get an associative array of current game state attributes, see [[Your game state machine: states.inc.php]] for state attributes.&lt;br /&gt;
&lt;br /&gt;
  $state=$this-&amp;gt;gamestate-&amp;gt;state(); if( $state[&#039;name&#039;] == &#039;myGameState&#039; ) {...}&lt;br /&gt;
&lt;br /&gt;
I suggest to define and use this function in your php class to access state name:&lt;br /&gt;
&lt;br /&gt;
    public function getStateName() {&lt;br /&gt;
        $state = $this-&amp;gt;gamestate-&amp;gt;state();&lt;br /&gt;
        return $state[&#039;name&#039;];&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
; $this-&amp;gt;gamestate-&amp;gt;state_id()&lt;br /&gt;
: Get the id of the current game state (rarely useful, its best to use name, unless you use constants for state ids)&lt;br /&gt;
&lt;br /&gt;
; $this-&amp;gt;gamestate-&amp;gt;isMutiactiveState()&lt;br /&gt;
: Return true if we are in multipleactiveplayer state, false otherwise&lt;br /&gt;
&lt;br /&gt;
=== Private parallel states ===&lt;br /&gt;
&lt;br /&gt;
See the overview of private parallel states [[Your_game_state_machine:_states.inc.php#Private_parallel_states|here]].&lt;br /&gt;
&lt;br /&gt;
; $this-&amp;gt;gamestate-&amp;gt;initializePrivateStateForAllActivePlayers()&lt;br /&gt;
: All active players in a multiactive state are entering a first private state defined in the master state&#039;s initialprivate parameter.&lt;br /&gt;
: Every time you need to start a private parallel states you need to call this or similar methods below.&lt;br /&gt;
: Note: at least one player needs to be active (see [[#Multiple_activate_player_handling|above]]) and current game state must be a multiactive state with initialprivate parameter defined&lt;br /&gt;
: Note: initialprivate parameter of master state should be set to the id of the first private state. This private state needs to be defined in states.php with the type set to &#039;private&#039;.&lt;br /&gt;
: Note: this method is usually preceded with activating some or all players&lt;br /&gt;
: Note: initializing private state can run action or args methods of the initial private state&lt;br /&gt;
&lt;br /&gt;
Example of usage:&lt;br /&gt;
    &amp;lt;pre&amp;gt;&lt;br /&gt;
    function stStartPlayerTurn() {&lt;br /&gt;
        // This is usually done in master state action method&lt;br /&gt;
        &lt;br /&gt;
        $this-&amp;gt;gamestate-&amp;gt;setAllPlayersMultiactive();&lt;br /&gt;
        $this-&amp;gt;gamestate-&amp;gt;initializePrivateStateForAllActivePlayers();&lt;br /&gt;
&lt;br /&gt;
        // in some cases you can move immediately some or all players to different private states&lt;br /&gt;
        if ($someCondition) {&lt;br /&gt;
            //move all players to different state &lt;br /&gt;
            $this-&amp;gt;gamestate-&amp;gt;nextPrivateStateForAllActivePlayers(&amp;quot;some_transition&amp;quot;);&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        if ($other condition) {&lt;br /&gt;
            //move single player to different state&lt;br /&gt;
            $this-&amp;gt;gamestate-&amp;gt;nextPrivateState($specificPlayerId, &amp;quot;some_transition&amp;quot;);&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    &amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
; $this-&amp;gt;gamestate-&amp;gt;initializePrivateStateForPlayers($playerIds)&lt;br /&gt;
: Players with specified ids are entering a first private state defined in the master state initialprivate parameter.&lt;br /&gt;
: Same considerations apply as for the method above.&lt;br /&gt;
&lt;br /&gt;
; $this-&amp;gt;gamestate-&amp;gt;initializePrivateState($playerId)&lt;br /&gt;
: Player with the specified id is entering a first private state defined in the master state initialprivate parameter.&lt;br /&gt;
: Everytime you need to start a private parallel states you need to call this or similar methods above&lt;br /&gt;
: Note: player needs to be active (see [[#Multiple_activate_player_handling|above]]) and current game state must be a multiactive state with initialprivate parameter defined&lt;br /&gt;
: Note: initialprivate parameter of master state should be set to the id of the first private state. This private state needs to be defined in states.php with the type set to &#039;private&#039;.&lt;br /&gt;
: Note: this method is usually preceded with activating that player&lt;br /&gt;
: Note: initializing private state can run action or args methods of the initial private state&lt;br /&gt;
&lt;br /&gt;
Example of usage:&lt;br /&gt;
    &amp;lt;pre&amp;gt;&lt;br /&gt;
    function st_ChangeMind() {&lt;br /&gt;
        // This player finished his move before, but now decides change something while other players are still active&lt;br /&gt;
        // We activate the player and initialize his private state&lt;br /&gt;
        $this-&amp;gt;gamestate-&amp;gt;setPlayersMultiactive([$this-&amp;gt;getCurrentPlayerId()], &amp;quot;&amp;quot;);&lt;br /&gt;
        $this-&amp;gt;gamestate-&amp;gt;initializePrivateState(this-&amp;gt;getCurrentPlayerId());&lt;br /&gt;
&lt;br /&gt;
        // It is also possible to move the player to some other specific state immediately&lt;br /&gt;
        $this-&amp;gt;gamestate-&amp;gt;nextPrivateState($this-&amp;gt;getCurrentPlayerId(), &amp;quot;some_transition&amp;quot;);&lt;br /&gt;
    }&lt;br /&gt;
    &amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
; $this-&amp;gt;gamestate-&amp;gt;nextPrivateStateForAllActivePlayers($transition)&lt;br /&gt;
: All active players will transition to next private state by specified transition&lt;br /&gt;
: Note: game needs to be in a master state which allows private parallel states&lt;br /&gt;
: Note: transition should lead to another private state (i.e. a state with type defined as &#039;private&#039;&lt;br /&gt;
: Note: transition should be defined in private state in which the players currently are. &lt;br /&gt;
: Note: this method can run action or args methods of the target state&lt;br /&gt;
: Note: this is usually used after initializing the private state to move players to specific private state according to the game logic&lt;br /&gt;
&lt;br /&gt;
Example of usage:&lt;br /&gt;
    &amp;lt;pre&amp;gt;&lt;br /&gt;
    function stStartPlayerTurn() {&lt;br /&gt;
        // This is usually done in master state action method&lt;br /&gt;
        $this-&amp;gt;gamestate-&amp;gt;setAllPlayersMultiactive();&lt;br /&gt;
        $this-&amp;gt;gamestate-&amp;gt;initializePrivateStateForAllActivePlayers();&lt;br /&gt;
&lt;br /&gt;
        if ($specificOption) {&lt;br /&gt;
            //move all players to different state &lt;br /&gt;
            $this-&amp;gt;gamestate-&amp;gt;nextPrivateStateForAllActivePlayers(&amp;quot;some_transition&amp;quot;);&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    &amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
; $this-&amp;gt;gamestate-&amp;gt;nextPrivateStateForPlayers($playerIds, $transition)&lt;br /&gt;
: Players with specified ids will transition to next private state specified by provided transition.&lt;br /&gt;
: Same considerations apply as for the method above.&lt;br /&gt;
&lt;br /&gt;
; $this-&amp;gt;gamestate-&amp;gt;nextPrivateState($playerId, $transition)&lt;br /&gt;
: Player with specified id will transition to next private state specified by provided transition&lt;br /&gt;
: Note: game needs to be in a master state which allows private parallel states&lt;br /&gt;
: Note: transition should lead to another private state (i.e. a state with type defined as &#039;private&#039;&lt;br /&gt;
: Note: transition should be defined in private state in which the players currently are. &lt;br /&gt;
: Note: this method can run action or args methods of the target state for specified player&lt;br /&gt;
: Note: this is usually used after some player actions to move to next private state&lt;br /&gt;
&lt;br /&gt;
Example of usage:&lt;br /&gt;
    &amp;lt;pre&amp;gt;&lt;br /&gt;
    function actSomeAction() {&lt;br /&gt;
        $this-&amp;gt;checkAction(&amp;quot;actSomeAction&amp;quot;); //needs to be defined in the current state&lt;br /&gt;
        $this-&amp;gt;gamestate-&amp;gt;nextPrivateState($this-&amp;gt;getCurrentPlayerId(), &amp;quot;some_transition&amp;quot;);&lt;br /&gt;
    }&lt;br /&gt;
    &amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
; $this-&amp;gt;gamestate-&amp;gt;unsetPrivateStateForAllPlayers()&lt;br /&gt;
: All players private state will be reset to null, which means they will get out of private parallel states and be in a master state like the private states are not used &lt;br /&gt;
: Note: game needs to be in a master state which allows private parallel states&lt;br /&gt;
: Note: this is usually used to clean up after leaving a master state in which private states were used, but can be used in other cases when we want to exit private parallel states and use a regular multiactive state for all players&lt;br /&gt;
: Note: After unseting private state only actions on master state are possible&lt;br /&gt;
: Note: Usually it is not necessary to unset private states as they will be initialized to first private state when private states are needed again. Nevertheless it is generally better to clean private state after exiting private parallel states to avoid bugs. &lt;br /&gt;
&lt;br /&gt;
Example of usage:&lt;br /&gt;
    &amp;lt;pre&amp;gt;&lt;br /&gt;
    function stNextRound() {&lt;br /&gt;
        $this-&amp;gt;gamestate-&amp;gt;unsetPrivateStateForAllPlayers();&lt;br /&gt;
    }&lt;br /&gt;
    &amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
; $this-&amp;gt;gamestate-&amp;gt;unsetPrivateStateForPlayers($playerIds, $transition)&lt;br /&gt;
: For players with specified ids private state will be reset to null, which means they will get out of private parallel states and be in a master state like the private states are not used.&lt;br /&gt;
: Same considerations apply as for the method above.&lt;br /&gt;
&lt;br /&gt;
; $this-&amp;gt;gamestate-&amp;gt;unsetPrivateState($playerId)&lt;br /&gt;
: For player with specified id private state will be reset to null, which means they will get out of private parallel states and be in a master state like the private states are not used &lt;br /&gt;
: Note: game needs to be in a master state which allows private parallel states&lt;br /&gt;
: Note: this is usually used when deactivating player to clean up their parallel state&lt;br /&gt;
: Note: After unseting private state only actions on master state are possible&lt;br /&gt;
: Note: Usually it is not necessary to unset private state as it will be initialized to first private state when private states are needed again. Nevertheless it is generally better to clean private state when not needed to avoid bugs. &lt;br /&gt;
&lt;br /&gt;
Example of usage:&lt;br /&gt;
    &amp;lt;pre&amp;gt;&lt;br /&gt;
    function done() {&lt;br /&gt;
        $this-&amp;gt;gamestate-&amp;gt;setPlayerNonMultiactive( $this-&amp;gt;getCurrentPlayerId(), &amp;quot;newTurn&amp;quot; );&lt;br /&gt;
        $this-&amp;gt;gamestate-&amp;gt;unsetPrivateState($this-&amp;gt;getCurrentPlayerId());&lt;br /&gt;
    }&lt;br /&gt;
    &amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
; $this-&amp;gt;gamestate-&amp;gt;setPrivateState($playerId, $newStateId)&lt;br /&gt;
: For player with specified id a new private state would be set&lt;br /&gt;
: Note: game needs to be in a master state which allows private parallel states&lt;br /&gt;
: Note: this should be rarely used as it doesn&#039;t check if the transition is allowed (it doesn&#039;t even specifies transition). This can be useful in very complex cases when standard state machine is not adequate (i.e. specific cards can lead to some micro action in various states where defining transitions back and forth can become very tedious.) &lt;br /&gt;
: Note: this method can run action or args methods of the target state for specified player&lt;br /&gt;
&lt;br /&gt;
Example of usage:&lt;br /&gt;
    &amp;lt;pre&amp;gt;&lt;br /&gt;
    function actSomeAction() {&lt;br /&gt;
        $this-&amp;gt;checkAction(&amp;quot;actSomeAction&amp;quot;); //needs to be defined in the current state&lt;br /&gt;
&lt;br /&gt;
        if ($playerHaveSpecificCard)&lt;br /&gt;
            return $this-&amp;gt;gamestate-&amp;gt;setPrivateState($this-&amp;gt;getCurrentPlayerId(), 35);&lt;br /&gt;
&lt;br /&gt;
        $this-&amp;gt;gamestate-&amp;gt;nextPrivateState($this-&amp;gt;getCurrentPlayerId(), &amp;quot;some_transition&amp;quot;);        &lt;br /&gt;
    }&lt;br /&gt;
    &amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
; $this-&amp;gt;gamestate-&amp;gt;getPrivateState($playerId) &lt;br /&gt;
: This return the private state or null if not initialized or not in private state&lt;br /&gt;
&lt;br /&gt;
==== State Arguments in Private parallel states ====&lt;br /&gt;
&lt;br /&gt;
The args method called for private states will have the player_id passed to it, allowing you to customise the arguments returned for that player.&lt;br /&gt;
&lt;br /&gt;
Example of usage:&lt;br /&gt;
    &amp;lt;pre&amp;gt;&lt;br /&gt;
    function argMyPrivateState($player_id) {&lt;br /&gt;
        return array(&lt;br /&gt;
          &#039;my_data&#039; =&amp;gt; $this-&amp;gt;getPlayerSpecificData($player_id)&lt;br /&gt;
        );&lt;br /&gt;
    }&lt;br /&gt;
    &amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Inactive Players ====&lt;br /&gt;
&lt;br /&gt;
During Private Parallel State, active players will be managed by the private state that is current assigned to them.&lt;br /&gt;
&lt;br /&gt;
Inactive players will be managed by the master multipleactiveplayer state, so your client should respond to that state in order to display any status message advising players that they are waiting for others to have their turn, or to add any buttons that allow players to potentially &amp;quot;break in&amp;quot; and become active.&lt;br /&gt;
&lt;br /&gt;
== Actions (autowired) ==&lt;br /&gt;
The action function should be prefixed by &amp;quot;act&amp;quot; and match the names specified in the &amp;quot;possibleactions&amp;quot; field on the state file.&lt;br /&gt;
&lt;br /&gt;
If your actions start with &amp;quot;act&amp;quot;, they will be autowired, that means you can declare action functions on the game.php file and call them directly from the front (with bgaPerformAction). You don&#039;t need to use action.php file anymore. The query param from the front request will be matched with the PHP variable of the same name, and it needs to be properly typed. This works for basic types: int, bool, float, string.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
public function actPlayCard(int $cardId) { ... }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
This function can be called from front-side with &lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
this.bgaPerformAction(&#039;actPlayCard&#039;, {&lt;br /&gt;
  cardId: this.selectedCardId // the &amp;quot;cardId&amp;quot; param match the PHP variable name&lt;br /&gt;
});&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
(Note: if you also declare the function in the action.php, it will be used instead of the autowiring)&lt;br /&gt;
&lt;br /&gt;
If you want more complex types like int array or JSON, you&#039;ll need to specify it using the Param attributes. Same if the PHP variable name is different from the front query param, or if you want to specify the tests that should be realized on the parameter before calling the function.&lt;br /&gt;
&lt;br /&gt;
=== Possible attributes ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;BoolParam(?string $name = null)&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
use \Bga\GameFramework\Actions\Types\BoolParam;&lt;br /&gt;
&lt;br /&gt;
...&lt;br /&gt;
&lt;br /&gt;
public function actRaiseBet(#[BoolParam(name: &#039;raise&#039;)] bool $raiseBet)&lt;br /&gt;
&lt;br /&gt;
public function actRaiseBet(#[BoolParam(name: &#039;raise&#039;)] bool $raise) // NOTE: it&#039;s the same as actRaiseBet(bool $raise) if PHP var name and param name are the same&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;IntParam(?string $name = null, public ?int $min = null, public ?int $max = null)&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
use \Bga\GameFramework\Actions\Types\IntParam;&lt;br /&gt;
&lt;br /&gt;
...&lt;br /&gt;
&lt;br /&gt;
public function actPlayCard(#[IntParam(name: &#039;id&#039;)] int $cardId)&lt;br /&gt;
&lt;br /&gt;
public function actSpendGold(#[IntParam(min: 1)] int $gold) // will trigger an exception if param is &amp;lt; 1&lt;br /&gt;
&lt;br /&gt;
public function actPlaceCardOnSpot(int $cardId, #[IntParam(min: 1, max: 5)] int $spot) // will trigger an exception if spot is not in 1 to 5 range&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;FloatParam(?string $name = null, public ?int $min = null, public ?int $max = null)&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Works the same way as IntParam, import is &amp;lt;code&amp;gt;use \Bga\GameFramework\Actions\Types\FloatParam;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;StringParam(?string $name = null, public ?bool $alphanum = false, public ?bool $alphanum_dash = false, public ?bool $base64 = false, public ?array $enum)&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
use \Bga\GameFramework\Actions\Types\StringParam;&lt;br /&gt;
&lt;br /&gt;
...&lt;br /&gt;
&lt;br /&gt;
public function actSubmitWord(#[StringParam(alphanum: true)] string $word) // will trigger an exception if the word is not alphanum&lt;br /&gt;
&lt;br /&gt;
public function actChooseAction(#[StringParam(enum: [&#039;move&#039;, &#039;attack&#039;, &#039;pass&#039;])] string $action)  // will trigger an exception if the parameter doesn&#039;t match a value in the enum&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Note: You should do one of the tests of the attribute, or test it yourself on the function, to unsure the user is not sending forbidden characters to the function.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;IntArrayParam(?string $name = null, public ?int $min = null, public ?int $max = null)&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
use \Bga\GameFramework\Actions\Types\IntArrayParam;&lt;br /&gt;
&lt;br /&gt;
...&lt;br /&gt;
&lt;br /&gt;
public function actDiscardCards(#[IntArrayParam] array $ids)&lt;br /&gt;
&lt;br /&gt;
public function actDiscardCards(#[IntArrayParam(min: 2, max 8)] array $ids)  // will trigger an exception if the array length is not in the 2 to 8 range. It doesn&#039;t check the min/max of the array values!&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This function can be called from front-side with &lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
const selectedCardIds = [8, 12, 25];&lt;br /&gt;
this.bgaPerformAction(&#039;actDiscardCards&#039;, {&lt;br /&gt;
  ids: selectedCardIds.join(&#039;,&#039;)&lt;br /&gt;
});&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;JsonParam(?string $name = null, public ?bool $associative = true, public ?bool $alphanum = true)&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
use \Bga\GameFramework\Actions\Types\JsonParam;&lt;br /&gt;
&lt;br /&gt;
...&lt;br /&gt;
&lt;br /&gt;
public function actPlanComplexStuff(#[JsonParam] array $answer) // force conversion to array during PHP json decode&lt;br /&gt;
public function actPlanComplexStuff(#[JsonParam(associative: false)] object $answer) // force conversion to object during PHP json decode&lt;br /&gt;
&lt;br /&gt;
public function actPlanComplexStuff(#[JsonParam(associative: null)] mixed $answer) // default PHP json decode&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== checkAction ===&lt;br /&gt;
The autowiring also triggers the checkAction, so you don&#039;t have to call it at the beginning of the function. If you need a function that should not trigger checkAction an action that can be played during someone else turn), you can disable it this way: &lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
use \Bga\GameFramework\Actions\CheckAction;&lt;br /&gt;
&lt;br /&gt;
...&lt;br /&gt;
&lt;br /&gt;
#[CheckAction(false)]&lt;br /&gt;
public function actSetAutopass(bool $autopass)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If you disable checkAction, you probably need to call checkPossibleAction instead at the beginning of your function.&lt;br /&gt;
&lt;br /&gt;
=== act prefix ===&lt;br /&gt;
The act prefix needed to activate the autowiring is not just to have some consistency in naming, it&#039;s also intended to protect your code. If we let autowired action to any function, a player may do a request to &#039;setPlayerScore&#039; function, even if you never intended for it to be called front side, and it would allow almost undetectable cheating for anyone reading the code of your game.&lt;br /&gt;
&lt;br /&gt;
== Players turn order ==&lt;br /&gt;
&lt;br /&gt;
When table is created the &amp;quot;natural&amp;quot; player order is assigned to player at random, and stored in &amp;quot;read-only&amp;quot; field &amp;quot;player_no&amp;quot;.&lt;br /&gt;
If you need to create a custom order you should never change natural order but have a separate data structure. &lt;br /&gt;
For example you can alter the players table to add another &amp;quot;custom_order&amp;quot; field, you can use state globals or you can use your natural board database, &lt;br /&gt;
to store meeple_color/position_location pair.&lt;br /&gt;
BGA currently does not provide any API to create/store custom player order.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;getNextPlayerTable()&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Return an associative array which associate each player with the next player around the table.&lt;br /&gt;
&lt;br /&gt;
In addition, key 0 is associated to the first player to play.&lt;br /&gt;
&lt;br /&gt;
Example: if three player with ID 1000, 2000 and 3000 are around the table, in this order, the method returns:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
   array( &lt;br /&gt;
    1000 =&amp;gt; 2000, &lt;br /&gt;
    2000 =&amp;gt; 3000, &lt;br /&gt;
    3000 =&amp;gt; 1000, &lt;br /&gt;
    0 =&amp;gt; 1000 &lt;br /&gt;
   );&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;getPrevPlayerTable()&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Same as above, but the associative array associate the previous player around the table. However there no 0 index here.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;getPlayerAfter( $player_id )&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Get player playing after given player in natural playing order.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;getPlayerBefore( $player_id )&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Get player playing before given player in natural playing order.&lt;br /&gt;
&lt;br /&gt;
Note: There is no API to modify this order, if you have custom player order you have to maintain it in your database&lt;br /&gt;
and have custom function to access it.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;createNextPlayerTable( $players, $bLoop=true )&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Using $players array creates a map of current =&amp;gt; next as in example from getNextPlayerTable(), however you can use custom order here. &lt;br /&gt;
If parmeter $bLoop is set to true then last player will points to first (creaing a loop), false otherwise.&lt;br /&gt;
In any case index 0 points to first player (first element of $players array). $players is array of player ids in desired order.&lt;br /&gt;
&lt;br /&gt;
Note: This function &#039;&#039;&#039;DOES NOT&#039;&#039;&#039; change the order in database, it only creates a map using key/values as descibed.&lt;br /&gt;
&lt;br /&gt;
Example of usage:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    function getNextPlayerTableCustom() {&lt;br /&gt;
        $starting = $this-&amp;gt;getStartingPlayer(); // custom function to get starting player&lt;br /&gt;
        $player_ids = $this-&amp;gt;getPlayerIdsInOrder($starting); // custom function to create players array starting from starting player&lt;br /&gt;
        return $this-&amp;gt;createNextPlayerTable($player_ids, false); // create next player table in custom order&lt;br /&gt;
    }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$table = $this-&amp;gt;createNextPlayerTable([3000,2000,1000], false);&lt;br /&gt;
&lt;br /&gt;
will return:&lt;br /&gt;
   [ &lt;br /&gt;
    3000 =&amp;gt; 2000, &lt;br /&gt;
    2000 =&amp;gt; 1000, &lt;br /&gt;
    1000 =&amp;gt; null,&lt;br /&gt;
    0 =&amp;gt; 3000 &lt;br /&gt;
   ]&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Notifications ==&lt;br /&gt;
&lt;br /&gt;
To understand notifications, please read [http://www.slideshare.net/boardgamearena/the-bga-framework-at-a-glance The BGA Framework at a glance] first.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;IMPORTANT&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Notifications are crutial part of BGA framework. Everything players see, all changes which happen on frontend (including setup) are done via notfications.&lt;br /&gt;
Some of the are framework notifications and some of them are custom (game specific).&lt;br /&gt;
Generally you should not send or handle stanard notifications, except exposed APIs.&lt;br /&gt;
Example of standard notifications:&lt;br /&gt;
* game setup (first time client connects to game)&lt;br /&gt;
* game state change&lt;br /&gt;
* active player change&lt;br /&gt;
Example of custom notification&lt;br /&gt;
* game piece moved&lt;br /&gt;
* player scored points&lt;br /&gt;
&lt;br /&gt;
Notifications are queued, i.e. sent at the very end of the action, when it ends normally. It means that if you throw an exception for any reason (i.e: move is not allowed), no notifications will be sent to players.&lt;br /&gt;
&lt;br /&gt;
Notification can be sent from the following  functions (and transive calls obviosly):&lt;br /&gt;
&lt;br /&gt;
* action handler (action* in game.php). It is a MUST actually. At least one notificaton must be sent (but it includes state transition which sends it)&lt;br /&gt;
* game state transition (st* in game.php)&lt;br /&gt;
* setupNewGame (after player tables setup is finished)&lt;br /&gt;
&lt;br /&gt;
Notification cannot be sent from the following:&lt;br /&gt;
* .view.php&lt;br /&gt;
* .action.php&lt;br /&gt;
* material.inc.php&lt;br /&gt;
* constructor of .game.php&lt;br /&gt;
* arg* methods of .game.php&lt;br /&gt;
&lt;br /&gt;
There are conceptually two types of notification:&lt;br /&gt;
* public - sent to all client who are listening - that includes all players in the table and spectators&lt;br /&gt;
* private - that can only be sent to a player &lt;br /&gt;
&lt;br /&gt;
The bundle of notifications is sent at the end action considered a single &amp;quot;move&amp;quot; and move counter increases.&lt;br /&gt;
If you ONLY sending private notifications during action handling - they will not have associate move_id (to avoid it add simple public notification with empty message). &lt;br /&gt;
In rare case if you want to change this behavior, you can apply some hackery described in [[BGA_Studio_Cookbook]]&lt;br /&gt;
&lt;br /&gt;
Note: total notification size is now limited to 128K. It seems a lot, but don&#039;t forget that notification are bundled and only send at the end of action which also INCLUDES all game state transitions that follow.&lt;br /&gt;
&lt;br /&gt;
The notifications are handled on JS side by subscribing to notifications (only do it for custom notifications!). See [Game_interface_logic:_yourgamename.js#Notifications]&lt;br /&gt;
&lt;br /&gt;
=== NotifyAllPlayers ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;notifyAllPlayers(string $notification_type,string $message,array $notification_args )&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Send a notification to all players of the game and spectators (public).&lt;br /&gt;
&lt;br /&gt;
* notification_type: A string that defines the type of your notification.&lt;br /&gt;
&lt;br /&gt;
Your game interface Javascript logic will use this to know what is the type of the received notification (and to trigger the corresponding method).&lt;br /&gt;
&lt;br /&gt;
* message: A string that defines what is to be displayed in the game log.&lt;br /&gt;
&lt;br /&gt;
You can use an empty string here (&#039;&#039;). In this case, nothing is displayed in the game log.&lt;br /&gt;
&lt;br /&gt;
Unless its empty, use &amp;quot;clienttranslate&amp;quot; method to make sure string is translated.&lt;br /&gt;
&lt;br /&gt;
You can use arguments in your $notification_log string, that refers to values defines in the &amp;quot;$notification_args&amp;quot; argument (see below). &lt;br /&gt;
Note: Make sure you only use single quotes (&#039;), otherwise PHP will try to interpolate the variable and will ignore the values in the args array.&lt;br /&gt;
&lt;br /&gt;
* notification_args: The arguments of your notifications, as an associative array.&lt;br /&gt;
&lt;br /&gt;
This array will be transmitted to the game interface logic, in order the game interface can be updated.&lt;br /&gt;
&lt;br /&gt;
Complete notifyAllPlayers example (from &amp;quot;Reversi&amp;quot;):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$this-&amp;gt;notifyAllPlayers( &amp;quot;playDisc&amp;quot;, clienttranslate( &#039;${player_name} plays a disc and turns over ${returned_nbr} disc(s)&#039; ),&lt;br /&gt;
 array(&lt;br /&gt;
        &#039;player_id&#039; =&amp;gt; $player_id,&lt;br /&gt;
        &#039;player_name&#039; =&amp;gt; self::getActivePlayerName(),&lt;br /&gt;
        &#039;returned_nbr&#039; =&amp;gt; count( $turnedOverDiscs ),&lt;br /&gt;
        &#039;x&#039; =&amp;gt; $x,&lt;br /&gt;
        &#039;y&#039; =&amp;gt; $y&lt;br /&gt;
     ) );&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You can see in the example above the use of the &amp;quot;clienttranslate&amp;quot; method, and the use of 2 arguments &amp;quot;player_name&amp;quot; and &amp;quot;returned_nbr&amp;quot; in the notification log.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Important&#039;&#039;&#039;: NO private data must be sent with this method, as a cheater could see it even if it is not used explicitly by the game interface logic. If you want to send private information to a player, please use notifyPlayer below.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Important&#039;&#039;&#039;: this array is serialized to be sent to the browsers, and will be saved with the notification to be able to replay the game later. If it is too big, it can make notifications slower / less reliable, and replay archives very big (to the point of failing). So as a general rule, you should send only the minimum of information necessary to update the client interface with no overhead in order to keep the notifications as light as possible.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Important&#039;&#039;&#039;: When the game page is reloaded (i.e. F5 or when loading turn based game) all previous notifications are replayed as history notifications. These notifications do not trigger notification handlers and are used basically to build the game log. Because of that most of the notification arguments (except i18n, player_id and all arguments referenced in the message), are removed from these history notifications. If you need additional arguments in history notifications you can add special field &amp;lt;b&amp;gt;preserve&amp;lt;/b&amp;gt; to notification arguments, like this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$this-&amp;gt;notifyAllPlayers( &amp;quot;playDisc&amp;quot;, clienttranslate( &#039;${player_name} plays a disc and turns over ${returned_nbr} disc(s)&#039; ),&lt;br /&gt;
 array(&lt;br /&gt;
        &#039;player_id&#039; =&amp;gt; $player_id,&lt;br /&gt;
        &#039;player_name&#039; =&amp;gt; self::getActivePlayerName(),&lt;br /&gt;
        &#039;returned_nbr&#039; =&amp;gt; count( $turnedOverDiscs ),&lt;br /&gt;
        &#039;x&#039; =&amp;gt; $x,&lt;br /&gt;
        &#039;y&#039; =&amp;gt; $y,&lt;br /&gt;
        &#039;preserve&#039; =&amp;gt; [ &#039;x&#039;, &#039;y&#039; ]&lt;br /&gt;
     ) );&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
In this example, fields x and y will be preserved when replaying history notification at the game load.&lt;br /&gt;
&lt;br /&gt;
NOTE: The ONLY reason &#039;preserve&#039; is useful if you have custom method to render notifications in game log which changes some text arguments into html (i.e. to insert the images instead of plain text). Do not use preserve &amp;quot;just in case&amp;quot; - it will only bloat the logs and make game load VERY slow.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Important&#039;&#039;&#039;: If both public and private notifications are sent to the same player in the same action (AJAX call), they will initially appear in the log in the order in which they were called, but they are placed into the game log in the following order: All private notifications first, then all public notifications. This means that when the page is refreshed, or when a player loads an asynchronous game, if you have called any public notifications &#039;&#039;before&#039;&#039; the last private notification, they will appear out of order in the log.&lt;br /&gt;
&lt;br /&gt;
==== HTML in Notifications ====&lt;br /&gt;
&lt;br /&gt;
You CAN use some HTML inside your notification log, however it not recommended for many reasons:&lt;br /&gt;
* Its bad architecture, ui elements leak into server now you have to manage ui in many places&lt;br /&gt;
* If you decided to change something in ui in a future version, old games replay and tutorials may not work, since they use stored notifications (for example if the change occured during the game and later this game is used for tutorial)&lt;br /&gt;
* When you read log preview for old games its unreadable (this is log before you enter the game replay, useful for troubleshooting or game analysis)&lt;br /&gt;
* Its more data to transfer and store in db&lt;br /&gt;
* Its nightmare for translators, at least don&#039;t put HTML tags inside the &amp;quot;clienttranslate&amp;quot; method. You can use a notification argument instead, and provide your HTML through this argument.&lt;br /&gt;
&lt;br /&gt;
If you still want to have pretty pictures in the log check this [[BGA_Studio_Cookbook#Inject_images_and_styled_html_in_the_log]].&lt;br /&gt;
&lt;br /&gt;
==== Recursive Notifications ====&lt;br /&gt;
&lt;br /&gt;
If your notification contains some phrases that build programmatically you may need to use recursive notifications. In this case the argument can be not only the string but&lt;br /&gt;
an array itself, which contains &#039;log&#039; and &#039;args&#039;, i.e.&lt;br /&gt;
&lt;br /&gt;
  $this-&amp;gt;notifyAllPlayers(&#039;message&#039;,clienttranslate(&#039;Game moves ${token_name_rec}&#039;),&lt;br /&gt;
                   [&#039;token_name_rec&#039;=&amp;gt;[&#039;log&#039;=&amp;gt;&#039;${token_name} #${token_number}&#039;,&lt;br /&gt;
                                       &#039;args&#039;=&amp;gt; [&#039;token_name&#039;=&amp;gt;clienttranslate(&#039;Boo&#039;), &#039;token_number&#039;=&amp;gt;$number, &#039;i18n&#039;=&amp;gt;[&#039;token_name&#039;] ]&lt;br /&gt;
                                      ]&lt;br /&gt;
                   ]);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Excluding some players ====&lt;br /&gt;
&lt;br /&gt;
Sometimes you want to notify all players of a message but not have it appear in the log of specific players (for example, have every player see &amp;quot;Player X draws a card&amp;quot; but have Player X  will get a private notification &amp;quot;You draw the Ace of Spades&amp;quot;, so you want them not to see the public one).&lt;br /&gt;
&lt;br /&gt;
To send a notification to all players but have some clients ignore it, send it as normal from the server, but implement &#039;&#039;&#039;setIgnoreNotificationCheck&#039;&#039;&#039; on the client to ignore the message under given conditions. See the [[Game_interface_logic:_yourgamename.js#Ignoring_notifications]] documentation for more details. Note: do not sent private info with such notification, hiding something on client side is not a hacker safe.&lt;br /&gt;
&lt;br /&gt;
==== Using player names  ====&lt;br /&gt;
&lt;br /&gt;
The variable for player name must be ${player_name} in order to be highlighted with the player color in the game log, it has to have matching &#039;player_id&#039; argument in $notification_args. If you want a second player name in the log, name the variable ${player_name2} and $player_id2, etc.  For the multiple player case, usage of player_id and player_name is not mandatory i.e. skipping to player_id1 and player_name1 is fine.&lt;br /&gt;
&lt;br /&gt;
Special handling of arguments:&lt;br /&gt;
* ${player_name}  - this will be wrapped in html and text shown using color of the corresponding player, some colors also have reserved background. This will apply recursively as well.&lt;br /&gt;
* ${player_name1}, ${player_name2}, ${player_name3}, etc. work the same as above&lt;br /&gt;
In order for this to work you must pass corresponding player_idX AND player_nameX in args i.e.&lt;br /&gt;
&lt;br /&gt;
    $this-&amp;gt;notifyAllPlayers(&lt;br /&gt;
      &#039;buyAndPassCard&#039;,&lt;br /&gt;
      clienttranslate(&#039;${player_name} buys ${card_name} and passes it to ${player_name2}&#039;),&lt;br /&gt;
      [&lt;br /&gt;
        &#039;player_id&#039; =&amp;gt; $player1[&#039;id&#039;],&lt;br /&gt;
        &#039;player_name&#039; =&amp;gt; $player1[&#039;name&#039;],&lt;br /&gt;
        &#039;player_id2&#039; =&amp;gt; $player2[&#039;id&#039;],&lt;br /&gt;
        &#039;player_name2&#039; =&amp;gt; $player2[&#039;name&#039;],&lt;br /&gt;
        ...&lt;br /&gt;
      ]&lt;br /&gt;
    );&lt;br /&gt;
&lt;br /&gt;
Note: player_name is not translatable, never add it to i18n array&lt;br /&gt;
&lt;br /&gt;
=== NotifyPlayer ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;notifyPlayer(int $player_id, string $notification_type, string $message, $notification_args )&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Same as above, except that the notification is sent to one player only. The player must be the player at the game table.&lt;br /&gt;
&lt;br /&gt;
This method must be used each time some private information must be transmitted to a player.&lt;br /&gt;
&lt;br /&gt;
Important: the variable for player name must be ${player_name} in order to be highlighted with the player color in the game log. Since its a private notification it may be more appropriate to use &amp;quot;you&amp;quot; insted&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
  $this-&amp;gt;notifyPlayer($player_id,&#039;message&#039;,clienttranslate(&#039;You draw ${card_name}&#039;), [ ... ]);&lt;br /&gt;
or&lt;br /&gt;
  $this-&amp;gt;notifyPlayer($player_id,&#039;message&#039;,clienttranslate(&#039;${player_name} draws ${card_name}&#039;), [ &#039;player_name&#039; =&amp;gt; $this-&amp;gt;getPlayerNameById($player_id), ... ]);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Note: Spectators cannot be notified using this method, because their player ID is not available via loadPlayersBasicInfos() or otherwise. You must use notifyAllPlayers() for any notification that spectators should get.&lt;br /&gt;
&lt;br /&gt;
== Randomization ==&lt;br /&gt;
&lt;br /&gt;
A large number of board games rely on random, most often based on dice, cards shuffling, picking some item in a bag, and so on. This is very important to ensure a high level of randomness for each of these situations.&lt;br /&gt;
&lt;br /&gt;
Here&#039;s are a list of techniques you should use in these situations, from the best to the worst.&lt;br /&gt;
&lt;br /&gt;
=== Dice and bga_rand ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;bga_rand( min, max )&#039;&#039;&#039; &lt;br /&gt;
This is a BGA framework function that provides you a random number between &amp;quot;min&amp;quot; and &amp;quot;max&amp;quot; (inclusive), using the best available random method available on the system.&lt;br /&gt;
&lt;br /&gt;
This is the preferred function you should use, because we are updating it when a better method is introduced.&lt;br /&gt;
&lt;br /&gt;
As of now, bga_rand is based on the PHP function &amp;quot;random_int&amp;quot;, which ensures a cryptographic level of randomness.&lt;br /&gt;
&lt;br /&gt;
In particular, it is &#039;&#039;&#039;mandatory&#039;&#039;&#039; to use it for all &#039;&#039;&#039;dice throw&#039;&#039;&#039; (ie: games using other methods for dice throwing will be rejected by BGA during review).&lt;br /&gt;
&lt;br /&gt;
Note: rand() and mt_rand() are deprecated on BGA and should not be used anymore, as their randomness is not as good as &amp;quot;bga_rand&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
=== Arrays ===&lt;br /&gt;
&lt;br /&gt;
PHP&#039;s [https://www.php.net/array_rand array_rand()] and [https://www.php.net/shuffle shuffle()] functions are not cryptographically secure. Instead, the following code based on PHP&#039;s [https://www.php.net/random_int random_int()] provides a better method to choose a random key, value, or slice of an array. (the slice preserves keys)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    private function getRandomKey(array $array)&lt;br /&gt;
    {&lt;br /&gt;
        $size = count($array);&lt;br /&gt;
        if ($size == 0) {&lt;br /&gt;
            trigger_error(&amp;quot;getRandomKey(): Array is empty&amp;quot;, E_USER_WARNING);&lt;br /&gt;
            return null;&lt;br /&gt;
        }&lt;br /&gt;
        $rand = random_int(0, $size - 1);&lt;br /&gt;
        $slice = array_slice($array, $rand, 1, true);&lt;br /&gt;
        foreach ($slice as $key =&amp;gt; $value) {&lt;br /&gt;
            return $key;&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    private function getRandomValue(array $array)&lt;br /&gt;
    {&lt;br /&gt;
        $size = count($array);&lt;br /&gt;
        if ($size == 0) {&lt;br /&gt;
            trigger_error(&amp;quot;getRandomValue(): Array is empty&amp;quot;, E_USER_WARNING);&lt;br /&gt;
            return null;&lt;br /&gt;
        }&lt;br /&gt;
        $rand = random_int(0, $size - 1);&lt;br /&gt;
        $slice = array_slice($array, $rand, 1, true);&lt;br /&gt;
        foreach ($slice as $key =&amp;gt; $value) {&lt;br /&gt;
            return $value;&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    private function getRandomSlice(array $array, int $count)&lt;br /&gt;
    {&lt;br /&gt;
        $size = count($array);&lt;br /&gt;
        if ($size == 0) {&lt;br /&gt;
            trigger_error(&amp;quot;getRandomSlice(): Array is empty&amp;quot;, E_USER_WARNING);&lt;br /&gt;
            return null;&lt;br /&gt;
        }&lt;br /&gt;
        if ($count &amp;lt; 1 || $count &amp;gt; $size) {&lt;br /&gt;
            trigger_error(&amp;quot;getRandomSlice(): Invalid count $count for array with size $size&amp;quot;, E_USER_WARNING);&lt;br /&gt;
            return null;&lt;br /&gt;
        }&lt;br /&gt;
        $slice = [];&lt;br /&gt;
        $randUnique = [];&lt;br /&gt;
        while (count($randUnique) &amp;lt; $count) {&lt;br /&gt;
            $rand = random_int(0, $size - 1);&lt;br /&gt;
            if (array_key_exists($rand, $randUnique)) {&lt;br /&gt;
                continue;&lt;br /&gt;
            }&lt;br /&gt;
            $randUnique[$rand] = true;&lt;br /&gt;
            $slice += array_slice($array, $rand, 1, true);&lt;br /&gt;
        }&lt;br /&gt;
        return $slice;&lt;br /&gt;
    }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== shuffle and cards shuffling ===&lt;br /&gt;
&lt;br /&gt;
To shuffle items, like a pile of cards, the best way is to use the BGA PHP [[Deck]] component and to use &amp;quot;shuffle&amp;quot; method. This ensures that the best available shuffling method is used, and that if in the future we improve it your game will be up to date.&lt;br /&gt;
&lt;br /&gt;
As of now, the Deck component shuffle method is based on PHP &amp;quot;shuffle&amp;quot; method, which has quite good randomness (even if not as good as bga_rand). In consequence, we accept other shuffling methods during reviews, as long as they are based on PHP &amp;quot;shuffle&amp;quot; function (or similar, like &amp;quot;array_rand&amp;quot;).&lt;br /&gt;
&lt;br /&gt;
=== Other methods ===&lt;br /&gt;
&lt;br /&gt;
Mysql &amp;quot;RAND()&amp;quot; function has not enough randomness to be a valid method to get a random element on BGA. This function has been used in some existing games and has given acceptable results, but now it should be avoided and you should use other methods instead.&lt;br /&gt;
&lt;br /&gt;
== Game statistics ==&lt;br /&gt;
&lt;br /&gt;
There are 2 types of statistics:&lt;br /&gt;
* a &amp;quot;player&amp;quot; statistic is a statistic associated to a player&lt;br /&gt;
* a &amp;quot;table&amp;quot; statistic is a statistic not associated to a player (global statistic for this game).&lt;br /&gt;
&lt;br /&gt;
See [[Game statistics: stats.inc.php]] to see how you define statistics for your game.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;initStat( $table_or_player, $name, $value, $player_id = null )&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Create a statistic entry with a default value.&lt;br /&gt;
&lt;br /&gt;
This method must be called for each statistic of your game, in your setupNewGame method.&lt;br /&gt;
If you neglect to call this for a statistic, and also do not update the value during the course of a certain game using setStat or incStat, the value of the stat will be undefined rather than 0. This will result in it being ignored at the end of the game, as if it didn&#039;t apply to that particular game, and excluded from cumulative statistics. As a consequence - if do not want statistic to be applied, do not init it, or call set or inc on it.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;$table_or_player&#039; must be set to &amp;quot;table&amp;quot; if this is a table statistic, or &amp;quot;player&amp;quot; if this is a player statistic.&lt;br /&gt;
&lt;br /&gt;
&#039;$name&#039; is the name of your statistic, as it has been defined in your stats.inc.php file.&lt;br /&gt;
&lt;br /&gt;
&#039;$value&#039; is the initial value of the statistic. If this is a player statistic and if the player is not specified by &amp;quot;$player_id&amp;quot; argument, the value is set for ALL players.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;setStat( $value, $name, $player_id = null )&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Set a statistic $name to $value.&lt;br /&gt;
&lt;br /&gt;
If &amp;quot;$player_id&amp;quot; is not specified, setStat consider it is a TABLE statistic.&lt;br /&gt;
&lt;br /&gt;
If &amp;quot;$player_id&amp;quot; is specified, setStat consider it is a PLAYER statistic.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;incStat( $delta, $name, $player_id = null )&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Increment (or decrement) specified statistic value by $delta value. Same behavior as setStat function.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;getStat( $name, $player_id = null )&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Return the value of statistic specified by $name. Useful when creating derivative statistics such as average.&lt;br /&gt;
&lt;br /&gt;
== Translations ==&lt;br /&gt;
&lt;br /&gt;
See [[Translations]]&lt;br /&gt;
&lt;br /&gt;
== Manage player scores and Tie breaker ==&lt;br /&gt;
&lt;br /&gt;
=== Normal scoring ===&lt;br /&gt;
&lt;br /&gt;
At the end of the game, players automatically get a rank depending on their score: the player with the biggest score is #1, the player with the second biggest score is #2, and so on...&lt;br /&gt;
&lt;br /&gt;
During the game, you update player&#039;s score directly by updating &amp;quot;player_score&amp;quot; field of &amp;quot;player&amp;quot; table in database.&lt;br /&gt;
&lt;br /&gt;
Examples:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
  // +2 points to active player&lt;br /&gt;
  $this-&amp;gt;DbQuery( &amp;quot;UPDATE player SET player_score=player_score+2 WHERE player_id=&#039;&amp;quot;.self::getActivePlayerId().&amp;quot;&#039;&amp;quot; );&lt;br /&gt;
&lt;br /&gt;
  // Set score of active player to 5&lt;br /&gt;
  $this-&amp;gt;DbQuery( &amp;quot;UPDATE player SET player_score=5 WHERE player_id=&#039;&amp;quot;.self::getActivePlayerId().&amp;quot;&#039;&amp;quot; );&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note: don&#039;t forget to notify the client side in order the score control can be updated accordingly.&lt;br /&gt;
&lt;br /&gt;
=== Tie breaker ===&lt;br /&gt;
&lt;br /&gt;
Tie breaker is used when two players get the same score at the end of a game.&lt;br /&gt;
&lt;br /&gt;
Tie breaker is using &amp;quot;player_score_aux&amp;quot; field of &amp;quot;player&amp;quot; table. It is updated exactly like the &amp;quot;player_score&amp;quot; field.&lt;br /&gt;
&lt;br /&gt;
Tie breaker score is displayed only for players who are tied at the end of the game. Most of the time, it is not supposed to be displayed explicitly during the game.&lt;br /&gt;
&lt;br /&gt;
When you are using &amp;quot;player_score_aux&amp;quot; functionality, you must describe the formula to use in your gameinfos.inc.php file like this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
         &#039;tie_breaker_description&#039; =&amp;gt; totranslate(&amp;quot;Describe here your tie breaker formula&amp;quot;),&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This description will be used as a tooltip to explain to players how this auxiliary score has been calculated.&lt;br /&gt;
&lt;br /&gt;
See also [https://en.doc.boardgamearena.com/Game_meta-information:_gameinfos.inc.php#Multiple_tie_breaker_management Multiple Tie Breaker Management].&lt;br /&gt;
&lt;br /&gt;
=== Co-operative game ===&lt;br /&gt;
&lt;br /&gt;
To make everyone win/lose together in a full-coop game:&lt;br /&gt;
&lt;br /&gt;
Add the following in gameinfos.inc.php :&lt;br /&gt;
&#039;is_coop&#039; =&amp;gt; 1, // full cooperative&lt;br /&gt;
&lt;br /&gt;
Assign a score of zero to everyone if it&#039;s a loss.&lt;br /&gt;
Assign the same score &amp;gt; 0 to everyone if it&#039;s a win.&lt;br /&gt;
&lt;br /&gt;
=== Semi-coop ===&lt;br /&gt;
&lt;br /&gt;
If the game is not full-coop, then everyone loses = everyone is tied. I.e. set score to 0 to everybody.&lt;br /&gt;
&lt;br /&gt;
=== Only &amp;quot;winners&amp;quot; and &amp;quot;losers&amp;quot; ===&lt;br /&gt;
&lt;br /&gt;
For some games, there is only a group (or a single) &amp;quot;winner&amp;quot;, and everyone else is a &amp;quot;loser&amp;quot;, with no &amp;quot;end of game rank&amp;quot; (1st, 2nd, 3rd...).&lt;br /&gt;
&lt;br /&gt;
Examples:&lt;br /&gt;
* Coup&lt;br /&gt;
* Not Alone&lt;br /&gt;
* Werewolves&lt;br /&gt;
* Quantum&lt;br /&gt;
&lt;br /&gt;
In this case:&lt;br /&gt;
* Set the scores so that the winner has the best score, and the other players have the same (lower) score.&lt;br /&gt;
* Add the following lines to gameinfos.inc.php:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
// If in the game, all losers are equal (no score to rank them or explicit in the rules that losers are not ranked between them), set this to true &lt;br /&gt;
// The game end result will display &amp;quot;Winner&amp;quot; for the 1st player and &amp;quot;Loser&amp;quot; for all other players&lt;br /&gt;
&#039;losers_not_ranked&#039; =&amp;gt; true,&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Werewolves and Coup are implemented like this, as you can see here:&lt;br /&gt;
* https://boardgamearena.com/#!gamepanel?game=werewolves&amp;amp;section=lastresults&lt;br /&gt;
* https://boardgamearena.com/#!gamepanel?game=coupcitystate&amp;amp;section=lastresults&lt;br /&gt;
&lt;br /&gt;
Adding this has the following effects:&lt;br /&gt;
* On game results for this game, &amp;quot;Winner&amp;quot; or &amp;quot;Loser&amp;quot; is going to appear instead of the usual &amp;quot;1st, 2nd, 3rd, ...&amp;quot;.&lt;br /&gt;
* When a game is over, the result of the game will be &amp;quot;End of game: Victory&amp;quot; or &amp;quot;End of game: Defeat&amp;quot; depending on the result of the CURRENT player (instead of the usual &amp;quot;Victory of XXX&amp;quot;).&lt;br /&gt;
* When calculating ELO points, if there is at least one &amp;quot;Loser&amp;quot;, no &amp;quot;victorious&amp;quot; player can lose ELO points, and no &amp;quot;losing&amp;quot; player can win ELO point. Usually it may happened because being tie with many players with a low rank is considered as a tie and may cost you points. If losers_not_ranked is set, we prevent this behavior and make sure you only gain/loss ELO when you get the corresponding results.&lt;br /&gt;
&lt;br /&gt;
Important: this SHOULD NOT be used for cooperative games (see is_coop parameter), or for 2 players games (it makes no sense in this case).&lt;br /&gt;
&lt;br /&gt;
=== Solo ===&lt;br /&gt;
&lt;br /&gt;
If game supports solo variant, a negative or zero score means defeat, a positive score means victory.&lt;br /&gt;
&lt;br /&gt;
=== Player elimination ===&lt;br /&gt;
&lt;br /&gt;
In some games, this is useful to eliminate a player from the game in order he/she can start another game without waiting for the current game end.&lt;br /&gt;
&lt;br /&gt;
This case should be rare. Please don&#039;t use player elimination feature if some player just has to wait the last 10% of the game for game end. This feature should be used only in games where players are eliminated all along the game (typical examples: &amp;quot;Perudo&amp;quot; or &amp;quot;The Werewolves of Miller&#039;s Hollow&amp;quot;).&lt;br /&gt;
&lt;br /&gt;
Usage:&lt;br /&gt;
&lt;br /&gt;
* Player to eliminate should NOT be active anymore (preferably use the feature in a &amp;quot;game&amp;quot; type game state).&lt;br /&gt;
* In your PHP code:&lt;br /&gt;
  $this-&amp;gt;eliminatePlayer( &amp;lt;player_to_eliminate_id&amp;gt; );&lt;br /&gt;
* the player is informed in a dialog box that he no longer have to play and can start another game if he/she wants too (with buttons &amp;quot;stay at this table&amp;quot; &amp;quot;quit table and back to main site&amp;quot;). In any case, the player is free to start &amp;amp; join another table from now.&lt;br /&gt;
* When your game is over, all players who have been eliminated before receive a &amp;quot;notification&amp;quot; (the small &amp;quot;!&amp;quot; icon on the top right of the BGA interface) that indicate them that &amp;quot;the game has ended&amp;quot; and invite them to review the game results.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Important:&#039;&#039;&#039; this should not be used on a player who has already left the game (&amp;quot;zombie&amp;quot;) as leaving/being kicked of the game (outside of the scope of the rules) is not the same as being eliminated from the game (according to the rules), except if in the course of the game, the zombie player is eliminated according to the rules.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Important:&#039;&#039;&#039; When all surviving players are eliminated at the same time BGA framework causes the game to be abandoned automatically.&lt;br /&gt;
To circumvent this, the game should leave 1 player not eliminated but change final scores accordingly and end the game.&lt;br /&gt;
&lt;br /&gt;
=== Scoring Helper functions ===&lt;br /&gt;
&lt;br /&gt;
These functions should have been API but they are not, just add them to your php game and use for every game.&lt;br /&gt;
&lt;br /&gt;
    // get score&lt;br /&gt;
    function dbGetScore($player_id) {&lt;br /&gt;
        return $this-&amp;gt;getUniqueValueFromDB(&amp;quot;SELECT player_score FROM player WHERE player_id=&#039;$player_id&#039;&amp;quot;);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // set score&lt;br /&gt;
    function dbSetScore($player_id, $count) {&lt;br /&gt;
        $this-&amp;gt;DbQuery(&amp;quot;UPDATE player SET player_score=&#039;$count&#039; WHERE player_id=&#039;$player_id&#039;&amp;quot;);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // set aux score (tie breaker)&lt;br /&gt;
    function dbSetAuxScore($player_id, $score) {&lt;br /&gt;
        $this-&amp;gt;DbQuery(&amp;quot;UPDATE player SET player_score_aux=$score WHERE player_id=&#039;$player_id&#039;&amp;quot;);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // increment score (can be negative too)&lt;br /&gt;
    function dbIncScore($player_id, $inc) {&lt;br /&gt;
        $count = $this-&amp;gt;dbGetScore($player_id);&lt;br /&gt;
        if ($inc != 0) {&lt;br /&gt;
            $count += $inc;&lt;br /&gt;
            $this-&amp;gt;dbSetScore($player_id, $count);&lt;br /&gt;
        }&lt;br /&gt;
        return $count;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
== Reflexion time ==&lt;br /&gt;
&lt;br /&gt;
; function giveExtraTime( $player_id, $specific_time=null )&lt;br /&gt;
: Give standard extra time to this player.&lt;br /&gt;
: Standard extra time depends on the speed of the game (small with &amp;quot;slow&amp;quot; game option, bigger with other options).&lt;br /&gt;
: You can also specify an exact time to add, in seconds, with the &amp;quot;specified_time&amp;quot; argument (rarely used).&lt;br /&gt;
&lt;br /&gt;
; function isAsync()&lt;br /&gt;
: Returns true if game is turn based, false if it is realtime&lt;br /&gt;
&lt;br /&gt;
== Undo moves ==&lt;br /&gt;
&lt;br /&gt;
Please read our [[BGA Undo policy]] before.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Important&#039;&#039;&#039;: Before using these methods, you must also add the following to your &amp;quot;gameinfos.inc.php&amp;quot; file, otherwise these methods are ineffective:&lt;br /&gt;
  &#039;db_undo_support&#039; =&amp;gt; true&lt;br /&gt;
&lt;br /&gt;
Note: if you deploy undo support after game is in production this will take into effect for new games only, old games will give user an error if user choses Undo action, but otherwise it should not affect them.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
; function undoSavepoint( )&lt;br /&gt;
: Save the whole game situation inside an &amp;quot;Undo save point&amp;quot;.&lt;br /&gt;
: There is only ONE undo save point available (see [[BGA Undo policy]]). Cannot use in multiactivate state or in game state where next state is multiactive.&lt;br /&gt;
: Note: this function does not actually do anything when it is called, it only raises the flag to store the database AFTER transaction is over. So the actual state will be saved when you exit the function  calling it (technically before first queued notification is sent, which matters if you transition to game state not to user state after), this may affect what you end up saving.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
; function undoRestorePoint()&lt;br /&gt;
: Restore the situation previously saved as an &amp;quot;Undo save point&amp;quot;.&lt;br /&gt;
: You must make sure that the active player is the same after and before the undoRestorePoint (ie: this is your responsibility to ensure that the player that is active when this method is called is exactly the same than the player that was active when the undoSavePoint method has been called).&lt;br /&gt;
&lt;br /&gt;
    function actionUndo() {&lt;br /&gt;
        $this-&amp;gt;checkAction(&#039;actionUndo&#039;);&lt;br /&gt;
        $this-&amp;gt;undoRestorePoint();&lt;br /&gt;
        $this-&amp;gt;gamestate-&amp;gt;nextState(&#039;next&#039;); // transition to single player state (i.e. beginning of player actions for this turn)&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Important note&#039;&#039;&#039;: if you are reading game state variable right after restore (without changing state first) it won&#039;t work properly as the global table cache is not automatically refreshed after undoRestorePoint(). So you should either change state immediately to refresh game state values, or use $this-&amp;gt;gamestate-&amp;gt;reloadState() to refresh the state. If you choose to do the latest, be aware that this will bring the state machine back to the state during which the save point snapshot has been taken using undoSavepoint() (which means your transition you do after has to declared in the state which was saved, not in the state which was active for your actionUndo())&lt;br /&gt;
&lt;br /&gt;
== Managing errors and exceptions ==&lt;br /&gt;
&lt;br /&gt;
Note: when you throw an exception, all database changes and all notifications are cancelled immediately. This way, the game situation that existed before the request is completely restored.&lt;br /&gt;
&lt;br /&gt;
; throw new BgaUserException ( $error_message)&lt;br /&gt;
: Base class to notify a user error&lt;br /&gt;
: You must throw this exception when a player wants to do something that they are not allowed to do.&lt;br /&gt;
: The error message will be shown to the player as a &amp;quot;red message&amp;quot;.&lt;br /&gt;
: The error message must be translated, make sure you use self::_() or $this-&amp;gt;_() here and NOT clientranslate()&lt;br /&gt;
: Throwing such an exception is NOT considered a bug, so it is not traced in BGA error logs.&lt;br /&gt;
&lt;br /&gt;
Example from Gomoku:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
     throw new BgaUserException( $this-&amp;gt;_(&amp;quot;There is already a stone on this intersection, you can&#039;t play there&amp;quot;) );&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
; throw new BgaVisibleSystemException ( $error_message)&lt;br /&gt;
: You must throw this exception when you detect something that is not supposed to happened in your code.&lt;br /&gt;
: The error message is shown to the user as an &amp;quot;Unexpected error&amp;quot;, in order that he can report it in the forum.&lt;br /&gt;
: The error message is logged in BGA error logs. If it happens regularly, we will report it to you.&lt;br /&gt;
&lt;br /&gt;
; throw new BgaSystemException ( $error_message)&lt;br /&gt;
: Base class to notify a system exception. The message will be hidden from the user, but show in the logs. Use this if the message contains technical information.&lt;br /&gt;
: You shouldn&#039;t use this type of exception except if you think the information shown could be critical. Indeed: a generic error message will be shown to the user, so it&#039;s going to be difficult for you to see what happened.&lt;br /&gt;
&lt;br /&gt;
== Zombie mode ==&lt;br /&gt;
&lt;br /&gt;
When a player leaves a game for any reason (expelled, quit), he becomes a &amp;quot;zombie player&amp;quot;. In this case, the results of the game won&#039;t count for statistics, but this is cool if the other players can finish the game anyway. That&#039;s why zombie mode exists: allow the other player to finish the game, even if the situation is not ideal.&lt;br /&gt;
&lt;br /&gt;
While developing your zombie mode, keep in mind that:&lt;br /&gt;
* Do not refer to the rules, because this situation is not planned by the rules.&lt;br /&gt;
* Try to figure that you are playing with your friends and one of them has to leave: how can we finish the game without killing the spirit of the game?&lt;br /&gt;
* The idea is NOT to develop an artificial intelligence for the game.&lt;br /&gt;
* Do not try to end the game early, even in a two-player game. The zombie is there to allow the game to continue, not to end it. Trying to end the game is not supported by the framework and will likely cause unexpected errors.&lt;br /&gt;
&lt;br /&gt;
Most of the time, the best thing to do when it is zombie player turn is to jump immediately to a state where he is not active anymore. For example, if he is in a game state where he has a choice between playing A and playing B, the best thing to do is NOT to choose A or B, but to pass. So, even if there&#039;s no &amp;quot;pass&amp;quot; action in the rules, add a &amp;quot;zombiepass&amp;quot; transitition in your game state and use it.&lt;br /&gt;
&lt;br /&gt;
Each time a zombie player must play, your &amp;quot;zombieTurn&amp;quot; method is called.&lt;br /&gt;
&lt;br /&gt;
Parameters:&lt;br /&gt;
* $state: the name of the current game state.&lt;br /&gt;
* $active_player: the id of the active player.&lt;br /&gt;
&lt;br /&gt;
Most of the time, your zombieTurn method looks like this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    function zombieTurn( $state, $active_player )&lt;br /&gt;
    {&lt;br /&gt;
    	$statename = $state[&#039;name&#039;];&lt;br /&gt;
&lt;br /&gt;
        if( $statename == &#039;myFirstGameState&#039;&lt;br /&gt;
             ||  $statename == &#039;my2ndGameState&#039;&lt;br /&gt;
             ||  $statename == &#039;my3rdGameState&#039;&lt;br /&gt;
               ....&lt;br /&gt;
           )&lt;br /&gt;
        {&lt;br /&gt;
            $this-&amp;gt;gamestate-&amp;gt;nextState( &amp;quot;zombiePass&amp;quot; );&lt;br /&gt;
        }&lt;br /&gt;
        else&lt;br /&gt;
            throw new BgaVisibleSystemException( &amp;quot;Zombie mode not supported at this game state: &amp;quot;.$statename );&lt;br /&gt;
    }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note that in the example above, all corresponding game state should implement &amp;quot;zombiePass&amp;quot; as a transition.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Very important&#039;&#039;&#039;: your zombie code will be called when the player leaves the game. This action is triggered from the main site and propagated to the gameserver from a server, not from a browser. As a consequence, there is no current player associated to this action. In your zombieTurn function, you must &#039;&#039;&#039;never&#039;&#039;&#039; use getCurrentPlayerId() or getCurrentPlayerName(), otherwise it will fail with a &amp;quot;Not logged&amp;quot; error message.&lt;br /&gt;
&lt;br /&gt;
== User preferences ==&lt;br /&gt;
&#039;&#039;&#039;getGameUserPreference(int $playerId, int $prefId): ?int&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Return the value of a user preference for a player. It will return the value currently selected in the select combo box, in the top-right menu.&lt;br /&gt;
&lt;br /&gt;
== Player color preferences ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
BGA premium users may choose their preferred color for playing. For example, if they are used to play green for every board game, they can select &amp;quot;green&amp;quot; in their BGA preferences page.&lt;br /&gt;
&lt;br /&gt;
Making your game compatible with colors preferences is very easy and requires only 1 line of configuration change:&lt;br /&gt;
&lt;br /&gt;
On your gameinfos.inc.php file, add the following lines :&lt;br /&gt;
&lt;br /&gt;
  // Favorite colors support: if set to &amp;quot;true&amp;quot;, support attribution of favorite colors based on player&#039;s preferences (see reattributeColorsBasedOnPreferences PHP method)&lt;br /&gt;
  // NB: this parameter is used only to flag games supporting this feature; you must use (or not use) reattributeColorsBasedOnPreferences PHP method to actually enable or disable the feature.&lt;br /&gt;
  &#039;favorite_colors_support&#039; =&amp;gt; true,&lt;br /&gt;
&lt;br /&gt;
Then, on your main &amp;lt;your_game&amp;gt;.game.php file check the code of &amp;quot;setupNewGame&amp;quot;. New template already have correct code, but if you editing very old game and it may be absent.&lt;br /&gt;
&lt;br /&gt;
        $gameinfos = $this-&amp;gt;getGameinfos();&lt;br /&gt;
        ...&lt;br /&gt;
        if ($gameinfos[&#039;favorite_colors_support&#039;])&lt;br /&gt;
            $this-&amp;gt;reattributeColorsBasedOnPreferences($players, $gameinfos[&#039;player_colors&#039;]); // this should be above reloadPlayersBasicInfos()&lt;br /&gt;
        $this-&amp;gt;reloadPlayersBasicInfos();&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The &amp;quot;reattributeColorsBasedOnPreferences&amp;quot; method reattributes all colors, taking into account players color preferences and available colors.&lt;br /&gt;
&lt;br /&gt;
Note that you must update the colors to indicate the colors available for your game.&lt;br /&gt;
&lt;br /&gt;
Some important remarks:&lt;br /&gt;
* for some games (i.e. Chess), the color has an influence on a mechanism of the game, most of the time by giving a special advantage to a player (i.e. Starting the game). Color preference mechanism must NOT be used in such a case.&lt;br /&gt;
* your logic should NEVER consider that the first player has the color X, that the second player has the color Y, and so on. If this is the case, your game will NOT be compatible with reattributeColorsBasedOnPreferences as this method attribute colors to players based on their preferences and not based as their order at the table.&lt;br /&gt;
&lt;br /&gt;
=== Custom color assignments ===&lt;br /&gt;
Some colors don&#039;t play nicely with BGA&#039;s color difference algorithm. If you receive feedback that colors are not well chosen, you can bypass the BGA algorithm by specifying a map from user preference colors to game colors.&lt;br /&gt;
&lt;br /&gt;
For example, you may wish to assign BGA&#039;s blue to your game&#039;s baby blue: &amp;lt;code&amp;gt;&amp;quot;0000ff&amp;quot; /* Blue */ =&amp;gt; &amp;quot;89CFF0&amp;quot;,&amp;lt;/code&amp;gt; whereas otherwise, a deep purple might be chosen instead. Just be sure that the assigned colors are also present in the &amp;lt;code&amp;gt;player_colors&amp;lt;/code&amp;gt; array passed to &amp;lt;code&amp;gt;reattributeColorsBasedOnPreferences&amp;lt;/code&amp;gt;, otherwise the assignment will be ignored.&lt;br /&gt;
&lt;br /&gt;
To do this, implement this method in your &amp;lt;code&amp;gt;X.game.php&amp;lt;/code&amp;gt; class.&lt;br /&gt;
&lt;br /&gt;
Note: the user preference colors (the keys in the returned array) should not be modified, or the code may not work as expected. These are the colors players can choose between in their profile.&lt;br /&gt;
     /**&lt;br /&gt;
      * Returns an array of user preference colors to game colors.&lt;br /&gt;
      * Game colors must be among those which are passed to reattributeColorsBasedOnPreferences()&lt;br /&gt;
      * Each game color can be an array of suitable colors, or a single color:&lt;br /&gt;
      * [&lt;br /&gt;
      *    // The first available color chosen:&lt;br /&gt;
      *    &#039;ff0000&#039; =&amp;gt; [&#039;990000&#039;, &#039;aa1122&#039;],&lt;br /&gt;
      *    // This color is chosen, if available&lt;br /&gt;
      *    &#039;0000ff&#039; =&amp;gt; &#039;000099&#039;,&lt;br /&gt;
      * ]&lt;br /&gt;
      * If no color can be matched from this array, then the default implementation is used.&lt;br /&gt;
      */&lt;br /&gt;
     function getSpecificColorPairings(): array {&lt;br /&gt;
         return array(&lt;br /&gt;
             &amp;quot;ff0000&amp;quot; /* Red */         =&amp;gt; null,&lt;br /&gt;
             &amp;quot;008000&amp;quot; /* Green */       =&amp;gt; null,&lt;br /&gt;
             &amp;quot;0000ff&amp;quot; /* Blue */        =&amp;gt; null,&lt;br /&gt;
             &amp;quot;ffa500&amp;quot; /* Yellow */      =&amp;gt; null,&lt;br /&gt;
             &amp;quot;000000&amp;quot; /* Black */       =&amp;gt; null,&lt;br /&gt;
             &amp;quot;ffffff&amp;quot; /* White */       =&amp;gt; null,&lt;br /&gt;
             &amp;quot;e94190&amp;quot; /* Pink */        =&amp;gt; null,&lt;br /&gt;
             &amp;quot;982fff&amp;quot; /* Purple */      =&amp;gt; null,&lt;br /&gt;
             &amp;quot;72c3b1&amp;quot; /* Cyan */        =&amp;gt; null,&lt;br /&gt;
             &amp;quot;f07f16&amp;quot; /* Orange */      =&amp;gt; null,&lt;br /&gt;
             &amp;quot;bdd002&amp;quot; /* Khaki green */ =&amp;gt; null,&lt;br /&gt;
             &amp;quot;7b7b7b&amp;quot; /* Gray */        =&amp;gt; null,&lt;br /&gt;
         );&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
== Legacy games API ==&lt;br /&gt;
&lt;br /&gt;
For some very specific games (&amp;quot;legacy&amp;quot;, &amp;quot;campaign&amp;quot;), you need to keep some informations from a game to another.&lt;br /&gt;
&lt;br /&gt;
This should be an exceptional situation: the legacy API is costing resources on Board Game Arena databases, and is slowing down the game setup process + game end of game process. Please do not use it for things like:&lt;br /&gt;
* keeping a player preference/settings (=&amp;gt; player preferences and game options should be used instead)&lt;br /&gt;
* keeping a statistics, a score, or a ranking, while it is not planned in the physical board game, or while there is no added value compared to BGA statistics / rankings.&lt;br /&gt;
&lt;br /&gt;
You should use it for:&lt;br /&gt;
* legacy games: when some components of the game has been altered in a previous game and should be kept as it is.&lt;br /&gt;
* &amp;quot;campaign style&amp;quot; games: when a player is getting a &amp;quot;reward&amp;quot; at the end of a game, and should be able to use it in further games.&lt;br /&gt;
&lt;br /&gt;
Important: you cannot store more than 64k of data (serialized as JSON) per player per game. If you go over 64k, storeLegacyData function is going to FAIL, and there is a risk to create a major bug (= players blocked) in your game. You MUST make sure that no more than 64k of data is used for each player for your game. For example, if you are implementing a &amp;quot;campaign style&amp;quot; game and if you allow a player to start multiple campaign, you must LIMIT the number of different campaign so that the total data size to not go over the limit. We strongly recommend you to use this:&lt;br /&gt;
&lt;br /&gt;
  try &lt;br /&gt;
  {&lt;br /&gt;
  	$this-&amp;gt;storeLegacyTeamData( $my_data );&lt;br /&gt;
  }&lt;br /&gt;
  catch( feException $e ) // feException is a base class of BgaSystemException and others...&lt;br /&gt;
  {&lt;br /&gt;
  	if( $e-&amp;gt;getCode() == FEX_legacy_size_exceeded )&lt;br /&gt;
  	{&lt;br /&gt;
  		// Do something here to free some space in Legacy data (ex: by removing some variables)&lt;br /&gt;
  	}&lt;br /&gt;
  	else&lt;br /&gt;
  		throw $e;&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
The keys may only contain letters and numbers, underscore seems not to be allowed.&lt;br /&gt;
&lt;br /&gt;
; function storeLegacyData( $player_id, $key, $data, $ttl = 365 )&lt;br /&gt;
: Store some data associated with $key for the given user / current game&lt;br /&gt;
: In the opposite of all other game data, this data will PERSIST after the end of this table, and can be re-used&lt;br /&gt;
: in a future table with the same game.&lt;br /&gt;
: IMPORTANT: The only possible place where you can use this method is when the game is over at your table (last game action). Otherwise, there is a risk of conflicts between ongoing games.    &lt;br /&gt;
: TTL is a time-to-live: the maximum, and default, is 365 days.&lt;br /&gt;
: In any way, the total data (= all keys) you can store for a given user+game is 64k (note: data is store serialized as JSON data)&lt;br /&gt;
: NOTICE: You can store some persistant data across all tables from your game using the specific player_id 0 which is unused. In such case, it&#039;s even more important to manage correctly the size of your data to avoid any exception or issue while storing updated data (ie. you can use this for some kind of leaderbord for solo game or contest)&lt;br /&gt;
: Note: This function cannot be called during game setup (will throw an error).&lt;br /&gt;
&lt;br /&gt;
; function retrieveLegacyData( $player_id, $key )&lt;br /&gt;
: Get data associated with $key for the current game&lt;br /&gt;
: This data is common to ALL tables from the same game for this player, and persist from one table to another.&lt;br /&gt;
: Note: calling this function has an important cost =&amp;gt; please call it few times (possibly: only ONCE) for each player for 1 game if possible&lt;br /&gt;
: Note: you can use &#039;%&#039; in $key to retrieve all keys matching the given patterns&lt;br /&gt;
&lt;br /&gt;
; function removeLegacyData( $player_id, $key )&lt;br /&gt;
: Remove some legacy data with the given key&lt;br /&gt;
: (useful to free some data to avoid going over 64k)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
; function storeLegacyTeamData( $data, $ttl = 365 )&lt;br /&gt;
: Same as storeLegacyData, except that it stores some data for the whole team within the current table and does not use a key&lt;br /&gt;
: Ie: if players A, B and C are at a table, the legacy data will be saved for future table with (exactly) A, B and C on the table.&lt;br /&gt;
: This is useful for games which are intended to be played several time by the same team.&lt;br /&gt;
: Note: the data total size is still limited, so you must implement catch the FEX_legacy_size_exceeded exception if it happens&lt;br /&gt;
&lt;br /&gt;
; function retrieveLegacyTeamData()&lt;br /&gt;
: Same as retrieveLegacyData, except that it retrieves some data for the whole team within the current table (set by storeLegacyTeamData)&lt;br /&gt;
&lt;br /&gt;
; function removeLegacyTeamData()&lt;br /&gt;
: Same as removeLegacyData, except that it retrieves some data for the whole team within the current table (set by storeLegacyTeamData)&lt;br /&gt;
&lt;br /&gt;
== Players text input and moderation ==&lt;br /&gt;
This section concerns only games where the players have to write some words to play: games based on words, like &amp;quot;Just one&amp;quot; or &amp;quot;Codenames&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
Some players will use your game to write insults or profanities. As this is part of the game and not in the game chat, these words cannot be reported by players and moderated.&lt;br /&gt;
&lt;br /&gt;
If you met the following situation:&lt;br /&gt;
&lt;br /&gt;
* You are asking a player to type a text (word(s) or sentence)&lt;br /&gt;
* The player can enter any text (this is not a pre-selection or anything you can control)&lt;br /&gt;
* This text is visible by at least one other player&lt;br /&gt;
&lt;br /&gt;
Then, you must use the following method:&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;function logTextForModeration( $player_id, $text )&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
player_id = player who write the text&lt;br /&gt;
&lt;br /&gt;
text = text that has been written&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
This function will have no visible consequence for your game, but will allow players to report the text to moderators if something happens.&lt;br /&gt;
&lt;br /&gt;
== Language dependent games API ==&lt;br /&gt;
&lt;br /&gt;
This API is used for games that are heavily language dependent. Two most common use cases are:&lt;br /&gt;
* Games that have a language dependent component that are not necessarily translatable, typically a list of words. (Think of games like Codenames, Decrypto, Just One...)&lt;br /&gt;
* Games with massive communication where players would like to ensure that all participants speak the same language. (Think of games like Werewolf, The Resistance, maybe even dixit...)&lt;br /&gt;
&lt;br /&gt;
If this option is used, the table created will be limited only to users that have specific language in their profile. Player starting the game would be able to chose one of the languages they speak.&lt;br /&gt;
&lt;br /&gt;
There is a new property language_dependency in gameinfos.inc.php which can be set like this:&lt;br /&gt;
  &#039;language_dependency&#039; =&amp;gt; false,  //or if the property is missing, the game is not language dependent&lt;br /&gt;
  &#039;language_dependency&#039; =&amp;gt; true, //all players at the table must speak the same language&lt;br /&gt;
  &#039;language_dependency&#039; =&amp;gt; array( 1 =&amp;gt; &#039;en&#039;, 2 =&amp;gt; &#039;fr&#039;, 3 =&amp;gt; &#039;it&#039; ), //1-based list of supported languages&lt;br /&gt;
&lt;br /&gt;
In the gamename.game.php file, you can get the id of selected language with the method &#039;&#039;&#039;getGameLanguage&#039;&#039;&#039;.&lt;br /&gt;
; function getGameLanguage()&lt;br /&gt;
: Returns an index of the selected language as defined in gameinfos.inc.php.&lt;br /&gt;
&lt;br /&gt;
Languages currently available on BGA are:&lt;br /&gt;
  &#039;ar&#039; =&amp;gt; array( &#039;name&#039; =&amp;gt; &amp;quot;العربية&amp;quot;, &#039;code&#039; =&amp;gt; &#039;ar_AE&#039; ),             // Arabic&lt;br /&gt;
  &#039;be&#039; =&amp;gt; array( &#039;name&#039; =&amp;gt; &amp;quot;беларуская мова&amp;quot;, &#039;code&#039; =&amp;gt; &#039;be_BY&#039; ),     // Belarusian&lt;br /&gt;
  &#039;bn&#039; =&amp;gt; array( &#039;name&#039; =&amp;gt; &amp;quot;বাংলা&amp;quot;, &#039;code&#039; =&amp;gt; &#039;bn_BD&#039; ),                // Bengali&lt;br /&gt;
  &#039;bg&#039; =&amp;gt; array( &#039;name&#039; =&amp;gt; &amp;quot;български език&amp;quot;, &#039;code&#039; =&amp;gt; &#039;bg_BG&#039; ),      // Bulgarian&lt;br /&gt;
  &#039;ca&#039; =&amp;gt; array( &#039;name&#039; =&amp;gt; &amp;quot;català&amp;quot;, &#039;code&#039; =&amp;gt; &#039;ca_ES&#039; ),              // Catalan&lt;br /&gt;
  &#039;cs&#039; =&amp;gt; array( &#039;name&#039; =&amp;gt; &amp;quot;čeština&amp;quot;, &#039;code&#039; =&amp;gt; &#039;cs_CZ&#039; ),             // Czech&lt;br /&gt;
  &#039;da&#039; =&amp;gt; array( &#039;name&#039; =&amp;gt; &amp;quot;dansk&amp;quot;, &#039;code&#039; =&amp;gt; &#039;da_DK&#039; ),               // Danish&lt;br /&gt;
  &#039;de&#039; =&amp;gt; array( &#039;name&#039; =&amp;gt; &amp;quot;deutsch&amp;quot;, &#039;code&#039; =&amp;gt; &#039;de_DE&#039; ),             // German&lt;br /&gt;
  &#039;el&#039; =&amp;gt; array( &#039;name&#039; =&amp;gt; &amp;quot;Ελληνικά&amp;quot;, &#039;code&#039; =&amp;gt; &#039;el_GR&#039; ),            // Greek&lt;br /&gt;
  &#039;en&#039; =&amp;gt; array( &#039;name&#039; =&amp;gt; &amp;quot;English&amp;quot;, &#039;code&#039; =&amp;gt; &#039;en_US&#039; ),             // English&lt;br /&gt;
  &#039;es&#039; =&amp;gt; array( &#039;name&#039; =&amp;gt; &amp;quot;español&amp;quot;, &#039;code&#039; =&amp;gt; &#039;es_ES&#039; ),             // Spanish&lt;br /&gt;
  &#039;et&#039; =&amp;gt; array( &#039;name&#039; =&amp;gt; &amp;quot;eesti keel&amp;quot;, &#039;code&#039; =&amp;gt; &#039;et_EE&#039; ),          // Estonian       &lt;br /&gt;
  &#039;fi&#039; =&amp;gt; array( &#039;name&#039; =&amp;gt; &amp;quot;suomi&amp;quot;, &#039;code&#039; =&amp;gt; &#039;fi_FI&#039; ),               // Finnish&lt;br /&gt;
  &#039;fr&#039; =&amp;gt; array( &#039;name&#039; =&amp;gt; &amp;quot;français&amp;quot;, &#039;code&#039; =&amp;gt; &#039;fr_FR&#039; ),            // French&lt;br /&gt;
  &#039;he&#039; =&amp;gt; array( &#039;name&#039; =&amp;gt; &amp;quot;עברית&amp;quot;, &#039;code&#039; =&amp;gt; &#039;he_IL&#039; ),               // Hebrew       &lt;br /&gt;
  &#039;hi&#039; =&amp;gt; array( &#039;name&#039; =&amp;gt; &amp;quot;हिन्दी&amp;quot;, &#039;code&#039; =&amp;gt; &#039;hi_IN&#039; ),                 // Hindi&lt;br /&gt;
  &#039;hr&#039; =&amp;gt; array( &#039;name&#039; =&amp;gt; &amp;quot;Hrvatski&amp;quot;, &#039;code&#039; =&amp;gt; &#039;hr_HR&#039; ),            // Croatian&lt;br /&gt;
  &#039;hu&#039; =&amp;gt; array( &#039;name&#039; =&amp;gt; &amp;quot;magyar&amp;quot;, &#039;code&#039; =&amp;gt; &#039;hu_HU&#039; ),              // Hungarian&lt;br /&gt;
  &#039;id&#039; =&amp;gt; array( &#039;name&#039; =&amp;gt; &amp;quot;Bahasa Indonesia&amp;quot;, &#039;code&#039; =&amp;gt; &#039;id_ID&#039; ),    // Indonesian&lt;br /&gt;
  &#039;ms&#039; =&amp;gt; array( &#039;name&#039; =&amp;gt; &amp;quot;Bahasa Malaysia&amp;quot;, &#039;code&#039; =&amp;gt; &#039;ms_MY&#039; ),     // Malaysian&lt;br /&gt;
  &#039;it&#039; =&amp;gt; array( &#039;name&#039; =&amp;gt; &amp;quot;italiano&amp;quot;, &#039;code&#039; =&amp;gt; &#039;it_IT&#039; ),            // Italian&lt;br /&gt;
  &#039;ja&#039; =&amp;gt; array( &#039;name&#039; =&amp;gt; &amp;quot;日本語&amp;quot;, &#039;code&#039; =&amp;gt; &#039;ja_JP&#039; ),               // Japanese&lt;br /&gt;
  &#039;jv&#039; =&amp;gt; array( &#039;name&#039; =&amp;gt; &amp;quot;Basa Jawa&amp;quot;, &#039;code&#039; =&amp;gt; &#039;jv_JV&#039; ),           // Javanese                       &lt;br /&gt;
  &#039;ko&#039; =&amp;gt; array( &#039;name&#039; =&amp;gt; &amp;quot;한국어&amp;quot;, &#039;code&#039; =&amp;gt; &#039;ko_KR&#039; ),               // Korean&lt;br /&gt;
  &#039;lt&#039; =&amp;gt; array( &#039;name&#039; =&amp;gt; &amp;quot;lietuvių&amp;quot;, &#039;code&#039; =&amp;gt; &#039;lt_LT&#039; ),            // Lithuanian&lt;br /&gt;
  &#039;lv&#039; =&amp;gt; array( &#039;name&#039; =&amp;gt; &amp;quot;latviešu&amp;quot;, &#039;code&#039; =&amp;gt; &#039;lv_LV&#039; ),            // Latvian&lt;br /&gt;
  &#039;nl&#039; =&amp;gt; array( &#039;name&#039; =&amp;gt; &amp;quot;nederlands&amp;quot;, &#039;code&#039; =&amp;gt; &#039;nl_NL&#039; ),          // Dutch&lt;br /&gt;
  &#039;no&#039; =&amp;gt; array( &#039;name&#039; =&amp;gt; &amp;quot;norsk&amp;quot;, &#039;code&#039; =&amp;gt; &#039;nb_NO&#039; ),               // Norwegian&lt;br /&gt;
  &#039;oc&#039; =&amp;gt; array( &#039;name&#039; =&amp;gt; &amp;quot;occitan&amp;quot;, &#039;code&#039; =&amp;gt; &#039;oc_FR&#039; ),             // Occitan&lt;br /&gt;
  &#039;pl&#039; =&amp;gt; array( &#039;name&#039; =&amp;gt; &amp;quot;polski&amp;quot;, &#039;code&#039; =&amp;gt; &#039;pl_PL&#039; ),              // Polish&lt;br /&gt;
  &#039;pt&#039; =&amp;gt; array( &#039;name&#039; =&amp;gt; &amp;quot;português&amp;quot;,  &#039;code&#039; =&amp;gt; &#039;pt_PT&#039; ),          // Portuguese&lt;br /&gt;
  &#039;ro&#039; =&amp;gt; array( &#039;name&#039; =&amp;gt; &amp;quot;română&amp;quot;,  &#039;code&#039; =&amp;gt; &#039;ro_RO&#039;  ),            // Romanian&lt;br /&gt;
  &#039;ru&#039; =&amp;gt; array( &#039;name&#039; =&amp;gt; &amp;quot;Русский язык&amp;quot;, &#039;code&#039; =&amp;gt; &#039;ru_RU&#039; ),        // Russian&lt;br /&gt;
  &#039;sk&#039; =&amp;gt; array( &#039;name&#039; =&amp;gt; &amp;quot;slovenčina&amp;quot;, &#039;code&#039; =&amp;gt; &#039;sk_SK&#039; ),          // Slovak&lt;br /&gt;
  &#039;sl&#039; =&amp;gt; array( &#039;name&#039; =&amp;gt; &amp;quot;slovenščina&amp;quot;, &#039;code&#039; =&amp;gt; &#039;sl_SI&#039; ),         // Slovenian       &lt;br /&gt;
  &#039;sr&#039; =&amp;gt; array( &#039;name&#039; =&amp;gt; &amp;quot;Српски&amp;quot;, &#039;code&#039; =&amp;gt; &#039;sr_RS&#039; ),              // Serbian       &lt;br /&gt;
  &#039;sv&#039; =&amp;gt; array( &#039;name&#039; =&amp;gt; &amp;quot;svenska&amp;quot;, &#039;code&#039; =&amp;gt; &#039;sv_SE&#039; ),             // Swedish&lt;br /&gt;
  &#039;tr&#039; =&amp;gt; array( &#039;name&#039; =&amp;gt; &amp;quot;Türkçe&amp;quot;, &#039;code&#039; =&amp;gt; &#039;tr_TR&#039; ),              // Turkish       &lt;br /&gt;
  &#039;uk&#039; =&amp;gt; array( &#039;name&#039; =&amp;gt; &amp;quot;Українська мова&amp;quot;, &#039;code&#039; =&amp;gt; &#039;uk_UA&#039; ),     // Ukrainian&lt;br /&gt;
  &#039;zh&#039; =&amp;gt; array( &#039;name&#039; =&amp;gt; &amp;quot;中文 (漢)&amp;quot;,  &#039;code&#039; =&amp;gt; &#039;zh_TW&#039; ),           // Traditional Chinese (Hong Kong, Macau, Taiwan)&lt;br /&gt;
  &#039;zh-cn&#039; =&amp;gt; array( &#039;name&#039; =&amp;gt; &amp;quot;中文 (汉)&amp;quot;, &#039;code&#039; =&amp;gt; &#039;zh_CN&#039; ),         // Simplified Chinese (Mainland China, Singapore)&lt;br /&gt;
&lt;br /&gt;
== Debugging and Tracing ==&lt;br /&gt;
&lt;br /&gt;
To debug php code you can use some tracing functions available from the parent class such as debug, trace, error, warn, dump.&lt;br /&gt;
  &lt;br /&gt;
  $this-&amp;gt;debug(&amp;quot;Ahh!&amp;quot;);&lt;br /&gt;
  $this-&amp;gt;dump(&#039;my_var&#039;,$my_var);&lt;br /&gt;
&lt;br /&gt;
See [[Practical_debugging]] section for complete information about debugging interfaces and where to find logs.&lt;br /&gt;
&lt;br /&gt;
== PHP 8 upgrade ==&lt;br /&gt;
&lt;br /&gt;
See [[PHP 8 upgrade]]&lt;br /&gt;
&lt;br /&gt;
[[Category:Studio]]&lt;/div&gt;</summary>
		<author><name>Sguzzer Gunayer</name></author>
	</entry>
	<entry>
		<id>https://en.doc.boardgamearena.com/index.php?title=Studio&amp;diff=22619</id>
		<title>Studio</title>
		<link rel="alternate" type="text/html" href="https://en.doc.boardgamearena.com/index.php?title=Studio&amp;diff=22619"/>
		<updated>2024-09-17T20:46:03Z</updated>

		<summary type="html">&lt;p&gt;Sguzzer Gunayer: /* BGA Studio game components reference */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Studio_Framework_Navigation}}&lt;br /&gt;
&lt;br /&gt;
[[File:Bga_studio_small.jpg|frameless|300px]]&lt;br /&gt;
&lt;br /&gt;
Note: Please DO NOT translate Studio Documentation, so that there can be one place where you can find the latest information available.&lt;br /&gt;
&lt;br /&gt;
__TOC__&lt;br /&gt;
&lt;br /&gt;
== What is Board Game Arena Studio? ==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Board Game Arena Studio&#039;&#039;&#039; is a platform to build online board game adaptations using the Board Game Arena platform.&lt;br /&gt;
&lt;br /&gt;
It is open to any gamer with software development skills :)&lt;br /&gt;
&lt;br /&gt;
BGA Studio website: https://studio.boardgamearena.com&lt;br /&gt;
&lt;br /&gt;
Original announcement on BGA forum: https://forum.boardgamearena.com/viewtopic.php?f=10&amp;amp;t=1973&lt;br /&gt;
&lt;br /&gt;
== Discover BGA Studio in 5 presentations ==&lt;br /&gt;
&lt;br /&gt;
Why, how, what... to start discovering BGA Studio, we prepared 5 &amp;quot;powerpoint&amp;quot; presentations for you:&lt;br /&gt;
&lt;br /&gt;
* [http://www.slideshare.net/boardgamearena/5-reasons-why-you-should-use-bga-studio-for-your-online-board-game 5 reasons why you should use BGA Studio for your online board game] (or [http://en.doc.boardgamearena.com/images/5/58/1-why-developing.pdf ‎Download as PDF])&lt;br /&gt;
* [http://www.slideshare.net/boardgamearena/the-8-steps-to-create-a-board-game-on-board-game-arena The 8 steps to create a board game on Board Game Arena] (or [http://en.doc.boardgamearena.com/images/1/1e/2-8-steps-to-realize.pdf Download as PDF])&lt;br /&gt;
* [http://www.slideshare.net/boardgamearena/the-bga-framework-at-a-glance The BGA Framework at a glance] (or [http://en.doc.boardgamearena.com/images/7/79/3-thebgaframework.pdf Download as PDF])&lt;br /&gt;
* [http://www.slideshare.net/boardgamearena/bga-studio-focus-on-bga-game-state-machine Focus on BGA game state machine] (or [http://en.doc.boardgamearena.com/images/9/98/4-gamestates.pdf Download as PDF])&lt;br /&gt;
* [http://www.slideshare.net/boardgamearena/bga-studio-guidelines BGA developers guidelines] (or [http://en.doc.boardgamearena.com/images/7/76/5-guidelines.pdf ‎Download as PDF])&lt;br /&gt;
&lt;br /&gt;
== How to join the BGA developer team? ==&lt;br /&gt;
&lt;br /&gt;
Please see this page: [[How to join BGA developer team?]]&lt;br /&gt;
&lt;br /&gt;
== Great, I&#039;m in! ... How should I start? ==&lt;br /&gt;
&lt;br /&gt;
If you didn&#039;t already, check the presentations at the top of this page to get the basics.&lt;br /&gt;
&lt;br /&gt;
Then, you should checkout the [[First steps with BGA Studio]] to make sure that runs fine.&lt;br /&gt;
&lt;br /&gt;
After that, we strongly advise you to take one of these game creation tutorials:&lt;br /&gt;
* [[Tutorial reversi]] (&#039;&#039;&#039;recommended&#039;&#039;&#039;, closest to the actual BGA implementation and maintained by the BGA team) - an abstract strategy game played on an 8×8 uncheckered board for 2 players&lt;br /&gt;
* [[Tutorial gomoku]] - an abstract strategy game tic-tac-toe style for 2 players&lt;br /&gt;
* [[Tutorial hearts]] - a card game for 4 players&lt;br /&gt;
&lt;br /&gt;
Then start editing files and see what happens! ;)&lt;br /&gt;
&lt;br /&gt;
Once you&#039;re done with tutorials, you can start a real game (or join existing project)&lt;br /&gt;
* [[Create a game in BGA Studio: Complete Walkthrough]] &lt;br /&gt;
&lt;br /&gt;
If you have any questions, please check out the [[Studio FAQ]] or [[Contact BGA Studio]].&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
To search wiki pages on studio enter this text in search bar: &lt;br /&gt;
  &amp;quot;Category:Studio&amp;quot; white rabbit &lt;br /&gt;
That is if you want to search for white rabbit&lt;br /&gt;
&lt;br /&gt;
== BGA Studio documentation ==&lt;br /&gt;
&lt;br /&gt;
=== BGA Studio Framework reference ===&lt;br /&gt;
&lt;br /&gt;
This part of the documentation focuses on the development framework itself: functions and methods available to build your game.&lt;br /&gt;
&lt;br /&gt;
[[Studio file reference|File structure of a BGA game]]&lt;br /&gt;
&lt;br /&gt;
==== Game logic (Server side) ====&lt;br /&gt;
&lt;br /&gt;
* [[Main game logic: yourgamename.game.php]]&lt;br /&gt;
* [[Your game state machine: states.inc.php]]&lt;br /&gt;
* [[Game database model: dbmodel.sql]]&lt;br /&gt;
* [[Players actions: yourgamename.action.php]]&lt;br /&gt;
* [[Game material description: material.inc.php]]&lt;br /&gt;
* [[Game statistics: stats.inc.php]]&lt;br /&gt;
&lt;br /&gt;
==== Game interface (Client side) ====&lt;br /&gt;
&lt;br /&gt;
* [[Game interface logic: yourgamename.js]]&lt;br /&gt;
* [[Game art: img directory]]&lt;br /&gt;
* [[Game interface stylesheet: yourgamename.css]]&lt;br /&gt;
* [[Game layout: view and template: yourgamename.view.php and yourgamename_yourgamename.tpl]]&lt;br /&gt;
* [[Your game mobile version]]&lt;br /&gt;
&lt;br /&gt;
==== Other components ====&lt;br /&gt;
&lt;br /&gt;
* [[Translations]] (how to make your game translatable)&lt;br /&gt;
* [[Options_and_preferences:_gameoptions.json,_gamepreferences.json|Game Options and Preferences]]&lt;br /&gt;
* [[Game meta-information: gameinfos.inc.php]]&lt;br /&gt;
* [[Game replay]]&lt;br /&gt;
* [[3D]]&lt;br /&gt;
&lt;br /&gt;
=== BGA Studio game components reference ===&lt;br /&gt;
&lt;br /&gt;
Game components are useful tools you can use in your game adaptations.&lt;br /&gt;
&lt;br /&gt;
JS:&lt;br /&gt;
&lt;br /&gt;
* [[Counter]]: a JS component to manage a counter that can increase/decrease (ex: player&#039;s score).&lt;br /&gt;
* [[Scrollmap]]: a JS component to manage a scrollable game area (useful when the game area can be infinite. Examples:  Saboteur or Takenoko games).&lt;br /&gt;
* [[Stock]]: a JS component to manage and display a set of game elements displayed at a position.&lt;br /&gt;
* [[Zone]]: a JS component to manage a zone of the board where several game elements can come and leave, but should be well displayed together (See for example: token&#039;s places at Can&#039;t Stop).&lt;br /&gt;
* [[Draggable]]: a JS component to manage drag&#039;n&#039;drop actions.&lt;br /&gt;
* [[ExpandableSection]]: a JS component to manage a rectangular block of HTML than can be displayed/hidden.&lt;br /&gt;
* [[Anti-Stock]]: Code snippets in vanilla JS/HTML5 to do what stock does (that is if you cannot beat Stock into submission)&lt;br /&gt;
&lt;br /&gt;
PHP:&lt;br /&gt;
* [[Deck]]: a PHP component to manage cards (deck, hands, picking cards, moving cards, shuffle deck, ...).&lt;br /&gt;
&lt;br /&gt;
Reference for classes in game class hierarchy&lt;br /&gt;
&lt;br /&gt;
* [[Table]]: a PHP class that you inherit from for the game php&lt;br /&gt;
&lt;br /&gt;
=== BGA Studio user guide ===&lt;br /&gt;
&lt;br /&gt;
This part of the documentation is a user guide for the BGA Studio online development environment.&lt;br /&gt;
&lt;br /&gt;
Lifecycle&lt;br /&gt;
&lt;br /&gt;
* [[BGA game Lifecycle]]&lt;br /&gt;
* [[Create a game in BGA Studio: Complete Walkthrough]]&lt;br /&gt;
* [[Pre-release checklist]] - Go throught this list if you think you done development&lt;br /&gt;
* [[Post-release phase]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Tools and Advice&lt;br /&gt;
* [[BGA Studio Guidelines]]&lt;br /&gt;
* [[Tutorials checklist]]&lt;br /&gt;
* [[I wish I knew this when I started]] - one liners on most common missed features, mistakes, etc with further doc references&lt;br /&gt;
* [[Tools and tips of BGA Studio]] - Tips and instructions on setting up development environment&lt;br /&gt;
** [[Setting up BGA Development environment using VSCode]]&lt;br /&gt;
** [[Practical debugging]] - Tips focused on debugging&lt;br /&gt;
** [[Testing by developer]]&lt;br /&gt;
** [[Studio logs]] - Instructions for log access&lt;br /&gt;
** [[Troubleshooting]] - Most common &amp;quot;I am really stuck&amp;quot; situations&lt;br /&gt;
* [[BGA Studio Cookbook]] - Tips and instructions on using API&#039;s, libraries and frameworks&lt;br /&gt;
** [[Using Vue]] - work-in-progress guide on using the modern framework Vue.js to create a game&lt;br /&gt;
** [[Using Typescript and Scss]] - How to auto-build Typescript and SCSS files to make your code cleaner&lt;br /&gt;
** [[BGA Type Safe Template]] - Setting up a fully typed project using typescript and more!&lt;br /&gt;
** [[Bots and Artificial Intelligence]] - How to add AI/Bots to the game&lt;br /&gt;
* [[Studio FAQ]]&lt;br /&gt;
&lt;br /&gt;
Sharing&lt;br /&gt;
* [[Common board game elements image resources]] - Dice, meeples, cubes, etc&lt;br /&gt;
* [[BGA Code Sharing]] - Shared resources, projects on git hub, common code, other links&lt;br /&gt;
&lt;br /&gt;
== Software Versions ==&lt;br /&gt;
&lt;br /&gt;
Versions currently used by BGA framework:&lt;br /&gt;
&lt;br /&gt;
* Dojo Toolkit 1.15&lt;br /&gt;
* PHP: 8.2&lt;br /&gt;
* SQL: MySQL 5.7&lt;br /&gt;
* JS/CSS/HTML: limited by what minimization tools support: [[Game_interface_logic:_yourgamename.js#Javascript_minimization_.28after_July_2020.29|JS minimization]]&lt;br /&gt;
* Font Awesome: 4.7 https://fontawesome.com/v4.7/icons/ (available as &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;&amp;lt;i class=&amp;quot;fa fa-clock&amp;quot; /&amp;gt;&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt;)&lt;br /&gt;
* Font Awesome: 6.4.0 https://fontawesome.com/v6/search?o=r&amp;amp;m=free (available as &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;&amp;lt;i class=&amp;quot;fa6 fa6-clock&amp;quot; /&amp;gt;&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
=== PHP Extensions Used ===&lt;br /&gt;
&lt;br /&gt;
The following PHP extensions are - as of May 8th, 2022 - in use in BGA Studio and available:&lt;br /&gt;
&lt;br /&gt;
date, libxml, openssl, pcre, zlib, filter, hash, Reflection, SPL, session, standard, sodium, apache2handler, mysqlnd, PDO, xml, apcu, bz2, calendar, ctype, curl, dom, mbstring, FFI, fileinfo, ftp, gd, gettext, gmp, iconv, igbinary, json, exif, msgpack, mysqli, pdo_mysql, apc, posix, readline, shmop, SimpleXML, sockets, sysvmsg, sysvsem, sysvshm, tokenizer, v8js, xmlreader, xmlwriter, xsl, zip, Phar, memcached, Zend OPcache&lt;br /&gt;
&lt;br /&gt;
== Other resources ==&lt;br /&gt;
&lt;br /&gt;
[http://forum.boardgamearena.com/viewforum.php?f=12 Development forum]&lt;br /&gt;
&lt;br /&gt;
[https://studio.boardgamearena.com/bugs Bug tracking system FOR STUDIO issues and APIs]&lt;br /&gt;
&lt;br /&gt;
DISCORD chat server/room invite link https://discord.gg/YxEUacY if it does not work check this topic https://forum.boardgamearena.com/viewtopic.php?f=12&amp;amp;t=17403&amp;amp;hilit=discord&lt;br /&gt;
&lt;br /&gt;
Developer BLOGS https://bga-devs.github.io/blog/&lt;br /&gt;
&lt;br /&gt;
[[Contact BGA Studio]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Category:Studio]]&lt;/div&gt;</summary>
		<author><name>Sguzzer Gunayer</name></author>
	</entry>
	<entry>
		<id>https://en.doc.boardgamearena.com/index.php?title=Deck&amp;diff=22605</id>
		<title>Deck</title>
		<link rel="alternate" type="text/html" href="https://en.doc.boardgamearena.com/index.php?title=Deck&amp;diff=22605"/>
		<updated>2024-09-17T13:19:11Z</updated>

		<summary type="html">&lt;p&gt;Sguzzer Gunayer: /* Auto-reshuffle */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Studio_Framework_Navigation}}&lt;br /&gt;
&lt;br /&gt;
&amp;quot;Deck&amp;quot; is one of the most useful component on the PHP side. With &amp;quot;Deck&amp;quot;, you can manage the cards in your game on the server side.&lt;br /&gt;
&lt;br /&gt;
Using &amp;quot;deck&amp;quot;, you will be able to use the following features without writing a single SQL database request:&lt;br /&gt;
* Place cards in a pile, shuffle cards, draw cards one by one or many at a time.&lt;br /&gt;
* &amp;quot;Auto-reshuffle&amp;quot; the discard pile into the deck when the deck is empty.&lt;br /&gt;
* Move cards between different locations: hands of players, the table, etc.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Using Deck: Hearts example ==&lt;br /&gt;
&lt;br /&gt;
The Deck component is extensively used in the sample &#039;&#039;Hearts&#039;&#039; card game. You will find in &amp;quot;hearts.game.php&amp;quot; that the object &amp;quot;$this-&amp;gt;cards&amp;quot; is used many times.&lt;br /&gt;
&lt;br /&gt;
== Deck overview ==&lt;br /&gt;
&lt;br /&gt;
With Deck component, you manage all cards of your game.&lt;br /&gt;
&lt;br /&gt;
=== The 5 properties of each card ===&lt;br /&gt;
&lt;br /&gt;
Using the Deck component, each card will have 5 properties:&lt;br /&gt;
* &#039;&#039;&#039;id&#039;&#039;&#039;: This is the unique ID of each card.&lt;br /&gt;
* &#039;&#039;&#039;type&#039;&#039;&#039; and &#039;&#039;&#039;type_arg&#039;&#039;&#039;: These two values define the type of your card (i.e., what sort of card is this?).&lt;br /&gt;
* &#039;&#039;&#039;location&#039;&#039;&#039; and &#039;&#039;&#039;location_arg&#039;&#039;&#039;: These two values define where the card is at now.&lt;br /&gt;
&lt;br /&gt;
The id, type, and type_arg properties are constants throughout the game. location and location_arg change when your cards move from one place to another in the game area.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;id&#039;&#039;&#039; is the unique ID of each card. Two cards cannot have the same ID. IDs are generated automatically by the Deck component when you create cards during the Setup phase of your game.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;type&#039;&#039;&#039; and &#039;&#039;&#039;type_arg&#039;&#039;&#039; defines the type of your card.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;type&#039;&#039;&#039; is a short string, and &#039;&#039;&#039;type_arg&#039;&#039;&#039; is an integer.&lt;br /&gt;
&lt;br /&gt;
You can use these two values as you like to make sure you will be able to identify the different cards in the game. See usage of &amp;quot;type&amp;quot; and &amp;quot;type_arg&amp;quot; below.&lt;br /&gt;
&lt;br /&gt;
Examples of usage of &amp;quot;type&amp;quot; and &amp;quot;type_arg&amp;quot;:&lt;br /&gt;
* In &#039;&#039;Hearts&#039;&#039;, &amp;quot;type&amp;quot; represents the color (suite) of the card (1 to 4) and &amp;quot;type_arg&amp;quot; is the value of the card (1, 2, ... 10, J, Q, K).&lt;br /&gt;
* In &#039;&#039;Seasons&#039;&#039;, &amp;quot;type&amp;quot; represents the type of the card (e.g., 1 is Amulet of Air, 2 is Amulet of Fire, etc...). type_arg is not used.&lt;br /&gt;
* In &#039;&#039;Takenoko&#039;&#039;, a Deck component is used for objective cards. &amp;quot;type&amp;quot; is the kind of objective (irrigation/panda/plot) and &amp;quot;type_arg&amp;quot; is the ID of the specific objective to realize (e.g., &amp;quot;green bamboo x4&amp;quot;). Note that a second Deck component is used in &#039;&#039;Takenoko&#039;&#039; to manage the &amp;quot;garden plot&amp;quot; pile.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;location&#039;&#039;&#039; and &#039;&#039;&#039;location_arg&#039;&#039;&#039; define where a card is at now. &#039;&#039;&#039;location&#039;&#039;&#039; is a short string, and &#039;&#039;&#039;location_arg&#039;&#039;&#039; is an integer.&lt;br /&gt;
&lt;br /&gt;
You can use &#039;location&#039; and &#039;location_arg&#039; as you like, to move your card within the game area.&lt;br /&gt;
&lt;br /&gt;
There are 3 special &#039;location&#039; values that Deck manages automatically. You can choose to use these locations or not, depending on your needs:&lt;br /&gt;
* &#039;deck&#039;: the &#039;deck&#039; location is a standard draw deck. Cards are placed face down in a stack and are drawn in sequential order during the game. &#039;location_arg&#039; is used to specify where the card is located within the stack (the card with the highest location_arg value is the next to be drawn).&lt;br /&gt;
* &#039;hand&#039;: the &#039;hand&#039; location represents cards in a player&#039;s hand. &#039;location_arg&#039; is set to the ID of each player.&lt;br /&gt;
* &#039;discard&#039;: the &#039;discard&#039; location is used for discard piles. Card in &#039;discard&#039; may be reshuffled into the deck if needed (see &amp;quot;autoreshuffle&amp;quot;).&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Tips: using the Deck component, you will use generic properties (&amp;quot;location&amp;quot;, &amp;quot;type_arg&amp;quot;,...) for specific purposes in your game. Thus, during the design step before realizing your game, take a few minutes to write down the exact meaning of each of these generic properties in the context of your game.&lt;br /&gt;
&lt;br /&gt;
=== Create a new Deck component ===&lt;br /&gt;
&lt;br /&gt;
For each Deck component in your game, you need to create a dedicated table in the SQL database. This table has a standard format. In practice, if you just want to have a Deck component named &amp;quot;card&amp;quot;, you can copy/paste the following into your &amp;quot;dbmodel.sql&amp;quot; file:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
CREATE TABLE IF NOT EXISTS `card` (&lt;br /&gt;
  `card_id` int(10) unsigned NOT NULL AUTO_INCREMENT,&lt;br /&gt;
  `card_type` varchar(16) NOT NULL,&lt;br /&gt;
  `card_type_arg` int(11) NOT NULL,&lt;br /&gt;
  `card_location` varchar(16) NOT NULL,&lt;br /&gt;
  `card_location_arg` int(11) NOT NULL,&lt;br /&gt;
  PRIMARY KEY (`card_id`)&lt;br /&gt;
) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=1 ;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note: the database schema of this table does not have to be exactly what is listed above. You can increase the size of the fields or add more fields. For additional fields&lt;br /&gt;
you just have to do manual queries.&lt;br /&gt;
&lt;br /&gt;
In particular, if you are going to have deck locations specific to individual players, you may wish to use their player IDs in the card_location field. Those IDs can be 8+ characters long, leaving only 8 characters for the rest of the name if you use the varchar(16). If you exceed the size of the field, it will get silently truncated, which can be very difficult to troubleshoot!&lt;br /&gt;
&lt;br /&gt;
Once you have done this (and restarted your game), you can declare the Deck component in your PHP code in your class constructor. For &#039;&#039;Hearts&#039;&#039; for example, I added to the &amp;quot;Hearts()&amp;quot; method:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        $this-&amp;gt;cards = $this-&amp;gt;getNew( &amp;quot;module.common.deck&amp;quot; );&lt;br /&gt;
        $this-&amp;gt;cards-&amp;gt;init( &amp;quot;card&amp;quot; );&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note that we specify &amp;quot;card&amp;quot; here: the name of our previously created table. This means you can create several &amp;quot;Deck&amp;quot; components with multiple tables:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        $this-&amp;gt;firstKindCards = $this-&amp;gt;getNew( &amp;quot;module.common.deck&amp;quot; );&lt;br /&gt;
        $this-&amp;gt;firstKindCards -&amp;gt;init( &amp;quot;first_kind_card&amp;quot; );&lt;br /&gt;
        $this-&amp;gt;secondKindCards = $this-&amp;gt;getNew( &amp;quot;module.common.deck&amp;quot; );&lt;br /&gt;
        $this-&amp;gt;secondKindCards -&amp;gt;init( &amp;quot;second_kind_card&amp;quot; );&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Most of the time this is not useful; a Deck component should manage all objects of the same kind (i.e., all cards in the game).&lt;br /&gt;
Note that you need to create a table for each &amp;quot;Deck&amp;quot;, table name should be &amp;quot;first_kind_card&amp;quot; but the fields must remain &amp;quot;card_id&amp;quot;, &amp;quot;card_type&amp;quot; and so on.&lt;br /&gt;
&lt;br /&gt;
Afterwards, we can initialize your &amp;quot;Deck&amp;quot; by creating all the cards of the game. Generally, this is done only once during the game, in the &amp;quot;setupNewGame&amp;quot; method. &lt;br /&gt;
&lt;br /&gt;
The &amp;quot;Deck&amp;quot; component provides a fast way to initialize all your cards at once: createCards. Here is how it is used for &amp;quot;Hearts&amp;quot;:&amp;lt;pre&amp;gt;&lt;br /&gt;
        // Create cards&lt;br /&gt;
        $cards = array();&lt;br /&gt;
        foreach( $this-&amp;gt;colors as  $color_id =&amp;gt; $color ) // spade, heart, diamond, club&lt;br /&gt;
        {&lt;br /&gt;
            for( $value=2; $value&amp;lt;=14; $value++ )   //  2, 3, 4, ... K, A&lt;br /&gt;
            {&lt;br /&gt;
                $cards[] = array( &#039;type&#039; =&amp;gt; $color_id, &#039;type_arg&#039; =&amp;gt; $value, &#039;nbr&#039; =&amp;gt; 1);&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        $this-&amp;gt;cards-&amp;gt;createCards( $cards, &#039;deck&#039; );&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
As you can see, &amp;quot;createCards&amp;quot; takes a description of all cards of the game. For each type of card, you have to specify its &amp;quot;type&amp;quot;, &amp;quot;type_arg&amp;quot; and the number of cards to create (&amp;quot;nbr&amp;quot;). &amp;quot;createCards&amp;quot; create all cards and place them into the &amp;quot;deck&amp;quot; location (as specified in the second argument).&lt;br /&gt;
&lt;br /&gt;
Now, you are ready to use &amp;quot;Deck&amp;quot;!&lt;br /&gt;
&lt;br /&gt;
=== Simple examples using Deck ===&lt;br /&gt;
&lt;br /&gt;
(Most examples are from &amp;quot;Hearts&amp;quot; game)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
     // In &amp;quot;getAllDatas&#039;, we need to send to the current player all the cards he has in hand:&lt;br /&gt;
     $result[&#039;hand&#039;] = $this-&amp;gt;cards-&amp;gt;getCardsInLocation( &#039;hand&#039;, $player_id );&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
     // At some time we want to check if all the cards (52) are in player&#039;s hands:&lt;br /&gt;
     if( $this-&amp;gt;cards-&amp;gt;countCardInLocation( &#039;hand&#039; ) == 52 )&lt;br /&gt;
           // do something&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
     // When a player plays a card in front of him on the table:&lt;br /&gt;
     $this-&amp;gt;cards-&amp;gt;moveCard( $card_id, &#039;cardsontable&#039;, $player_id );&lt;br /&gt;
&lt;br /&gt;
     // Note the use of the custom location &#039;cardsontable&#039; here to keep track of cards on the table.&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
     // This is a new hand: let&#039;s gather all cards from everywhere in the deck:&lt;br /&gt;
     $this-&amp;gt;cards-&amp;gt;moveAllCardsInLocation( null, &amp;quot;deck&amp;quot; );&lt;br /&gt;
&lt;br /&gt;
     // And then shuffle the deck&lt;br /&gt;
     $this-&amp;gt;cards-&amp;gt;shuffle( &#039;deck&#039; );&lt;br /&gt;
&lt;br /&gt;
     // And then deal 13 cards to each player&lt;br /&gt;
     // Deal 13 cards to each players&lt;br /&gt;
     // Create deck, shuffle it and give 13 initial cards&lt;br /&gt;
     $players = $this-&amp;gt;loadPlayersBasicInfos();&lt;br /&gt;
     foreach( $players as $player_id =&amp;gt; $player )&lt;br /&gt;
     {&lt;br /&gt;
        $cards = $this-&amp;gt;cards-&amp;gt;pickCards( 13, &#039;deck&#039;, $player_id );&lt;br /&gt;
           &lt;br /&gt;
        // Notify player about his cards&lt;br /&gt;
        $this-&amp;gt;notifyPlayer( $player_id, &#039;newHand&#039;, &#039;&#039;, array( &lt;br /&gt;
            &#039;cards&#039; =&amp;gt; $cards&lt;br /&gt;
         ) );&lt;br /&gt;
     }  &lt;br /&gt;
&lt;br /&gt;
     // Note the use of &amp;quot;notifyPlayer&amp;quot; instead of &amp;quot;notifyAllPlayers&amp;quot;: new cards is a private information ;)  &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Deck component reference ==&lt;br /&gt;
&lt;br /&gt;
=== Initializing Deck component ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;init( $table_name )&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Initialize the Deck component.&lt;br /&gt;
&lt;br /&gt;
Argument:&lt;br /&gt;
* table_name: name of the DB table used by this Deck component.&lt;br /&gt;
&lt;br /&gt;
Must be called before any other Deck method.&lt;br /&gt;
&lt;br /&gt;
Usually, init is called in your game constructor.&lt;br /&gt;
&lt;br /&gt;
HINT: Create the deck object $this-&amp;gt;getNew and do the init call in the constructor or you will get &amp;quot;$this-&amp;gt;cards&amp;quot; as an invalid reference later. &lt;br /&gt;
&lt;br /&gt;
Example with Hearts:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
	function Hearts( )&lt;br /&gt;
	{&lt;br /&gt;
        (...)&lt;br /&gt;
        &lt;br /&gt;
        $this-&amp;gt;cards = $this-&amp;gt;getNew( &amp;quot;module.common.deck&amp;quot; );&lt;br /&gt;
        $this-&amp;gt;cards-&amp;gt;init( &amp;quot;card&amp;quot; );&lt;br /&gt;
	}&lt;br /&gt;
&amp;lt;/pre&amp;gt; &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;createCards( $cards, $location=&#039;deck&#039;, $location_arg=null )&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Create card items in your deck component. Usually, all card items are created once, during the setup phase of the game.&lt;br /&gt;
&lt;br /&gt;
&amp;quot;cards&amp;quot; describe all cards that need to be created. &amp;quot;cards&amp;quot; is an array with the following format:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
   // Create 1 card of type &amp;quot;1&amp;quot; with type_arg=99,&lt;br /&gt;
   //  and 4 cards of type &amp;quot;2&amp;quot; with type_arg=12,&lt;br /&gt;
   //  and 2 cards of type &amp;quot;3&amp;quot; with type_arg=33&lt;br /&gt;
&lt;br /&gt;
   $cards = array(&lt;br /&gt;
        array( &#039;type&#039; =&amp;gt; 1, &#039;type_arg&#039; =&amp;gt; 99, &#039;nbr&#039; =&amp;gt; 1 ),&lt;br /&gt;
        array( &#039;type&#039; =&amp;gt; 2, &#039;type_arg&#039; =&amp;gt; 12, &#039;nbr&#039; =&amp;gt; 4 ),&lt;br /&gt;
        array( &#039;type&#039; =&amp;gt; 3, &#039;type_arg&#039; =&amp;gt; 33, &#039;nbr&#039; =&amp;gt; 2 )&lt;br /&gt;
        ...&lt;br /&gt;
   );&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note: During the &amp;quot;createCards&amp;quot; process, Deck generates unique IDs for all card items.&lt;br /&gt;
&lt;br /&gt;
Note: createCards is optimized to create a lot of cards at once. Do not use it to create cards one by one.&lt;br /&gt;
&lt;br /&gt;
If &amp;quot;$location&amp;quot; and &amp;quot;$location_arg&amp;quot; arguments are not set, newly created cards are placed in the &amp;quot;deck&amp;quot; location. If &amp;quot;location&amp;quot; (and optionally location_arg) is specified, cards are created for this specific location.&lt;br /&gt;
&lt;br /&gt;
Note: &#039;location&#039; and &#039;location_arg&#039; can not be set individually, it does not read these values from the passed array of cards.&lt;br /&gt;
&lt;br /&gt;
HINT: Be sure to do the createCards in setupNewGame. Doing createCards in the constructor will throw database errors.&lt;br /&gt;
&lt;br /&gt;
=== Card standard format ===&lt;br /&gt;
&lt;br /&gt;
When Deck component methods are returning one or several cards, the following format is used:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
array(&lt;br /&gt;
   &#039;id&#039; =&amp;gt; ..,          // the card ID&lt;br /&gt;
   &#039;type&#039; =&amp;gt; ..,        // the card type&lt;br /&gt;
   &#039;type_arg&#039; =&amp;gt; ..,    // the card type argument&lt;br /&gt;
   &#039;location&#039; =&amp;gt; ..,    // the card location&lt;br /&gt;
   &#039;location_arg&#039; =&amp;gt; .. // the card location argument&lt;br /&gt;
);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Picking cards ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;pickCard( $location, $player_id )&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Pick a card from a &amp;quot;pile&amp;quot; location (ex: &amp;quot;deck&amp;quot;) and place it in the &amp;quot;hand&amp;quot; of specified player.&lt;br /&gt;
&lt;br /&gt;
Return the card picked or &amp;quot;null&amp;quot; if there are no more card in given location.&lt;br /&gt;
&lt;br /&gt;
The return value is an array of the card data elements (id, type, type_arg...) for that card.&lt;br /&gt;
&lt;br /&gt;
This method supports auto-reshuffle (see &amp;quot;auto-reshuffle&amp;quot; below).&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;pickCards( $nbr, $location, $player_id )&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Pick &amp;quot;$nbr&amp;quot; cards from a &amp;quot;pile&amp;quot; location (ex: &amp;quot;deck&amp;quot;) and place them in the &amp;quot;hand&amp;quot; of specified player.&lt;br /&gt;
&lt;br /&gt;
Return an array with the cards picked (indexed by the card ID), or &amp;quot;null&amp;quot; if there are no more card in given location.&lt;br /&gt;
&lt;br /&gt;
Note that the number of cards picked can be less than &amp;quot;$nbr&amp;quot; in case there are not enough cards in the pile location.&lt;br /&gt;
&lt;br /&gt;
This method supports auto-reshuffle (see &amp;quot;auto-reshuffle&amp;quot; below). In case there are not enough cards in the pile, all remaining cards are picked first, then the auto-reshuffle is triggered, then the other cards are picked.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;pickCardForLocation( $from_location, $to_location, $location_arg=0 )&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
This method is similar to &#039;pickCard&#039;, except that you can pick a card for any sort of location and not only the &amp;quot;hand&amp;quot; location.&lt;br /&gt;
&lt;br /&gt;
* from_location is the &amp;quot;pile&amp;quot; style location from where you are picking a card.&lt;br /&gt;
* to_location is the location where you will place the card picked.&lt;br /&gt;
* if &amp;quot;location_arg&amp;quot; is specified, the card picked will be set with this &amp;quot;location_arg&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
This method supports auto-reshuffle (see &amp;quot;auto-reshuffle&amp;quot; below).&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;pickCardsForLocation( $nbr, $from_location, $to_location, $location_arg=0, $no_deck_reform=false )&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
This method is similar to &#039;pickCards&#039;, except that you can pick cards for any sort of location and not only the &amp;quot;hand&amp;quot; location.&lt;br /&gt;
&lt;br /&gt;
* from_location is the &amp;quot;pile&amp;quot; style location from where you are picking some cards.&lt;br /&gt;
* to_location is the location where you will place the cards picked.&lt;br /&gt;
* if &amp;quot;location_arg&amp;quot; is specified, the cards picked will be set with this &amp;quot;location_arg&amp;quot;.&lt;br /&gt;
* if &amp;quot;no_deck_reform&amp;quot; is set to &amp;quot;true&amp;quot;, the auto-reshuffle feature is disabled during this method call.&lt;br /&gt;
&lt;br /&gt;
This method supports auto-reshuffle (see &amp;quot;auto-reshuffle&amp;quot; below).&lt;br /&gt;
&lt;br /&gt;
=== Moving cards ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;moveCard( $card_id, $location, $location_arg=0 )&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Move the specific card to given location.&lt;br /&gt;
&lt;br /&gt;
* card_id: ID of the card to move.&lt;br /&gt;
* location: location where to move the card.&lt;br /&gt;
* location_arg: if specified, location_arg where to move the card. If not specified &amp;quot;location_arg&amp;quot; will be set to 0.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;moveCards( $cards, $location, $location_arg=0 )&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Move the specific cards to given location.&lt;br /&gt;
&lt;br /&gt;
* cards: an array of IDs of cards to move.&lt;br /&gt;
* location: location where to move the cards.&lt;br /&gt;
* location_arg: if specified, location_arg where to move the cards. If not specified &amp;quot;location_arg&amp;quot; will be set to 0.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;insertCard( $card_id, $location, $location_arg )&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Move a card to a specific &amp;quot;pile&amp;quot; location where card are ordered.&lt;br /&gt;
&lt;br /&gt;
If location_arg place is already taken, increment all cards after location_arg in order to insert new card at this precise location.&lt;br /&gt;
&lt;br /&gt;
(note: insertCardOnExtremePosition method below is more useful in most of the case)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;insertCardOnExtremePosition( $card_id, $location, $bOnTop )&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Move a card on top or at bottom of given &amp;quot;pile&amp;quot; type location. (Lower numbers: bottom of the deck. Higher numbers: top of the deck.)&lt;br /&gt;
&lt;br /&gt;
(note: Filling an empty location this way with N cards creates &amp;quot;location_arg&amp;quot;s from 1 to N if &amp;quot;$bOnTop&amp;quot; is true and -1 to -N if &amp;quot;$bOnTop&amp;quot; is false. This can cause off-by-one errors for code intended to run on a deck generated by &amp;quot;shuffle( $location )&amp;quot; which generates &amp;quot;location_arg&amp;quot;s from 0 to N - 1.)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;moveAllCardsInLocation(  $from_location, $to_location, $from_location_arg=null, $to_location_arg=0 )&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Move all cards in specified &amp;quot;from&amp;quot; location to given location.&lt;br /&gt;
&lt;br /&gt;
* from_location: where to take the cards. If null, cards from all locations will be move.&lt;br /&gt;
* to_location: where to put the cards&lt;br /&gt;
* from_location_arg (optional): if specified, only cards with given &amp;quot;location_arg&amp;quot; are moved.&lt;br /&gt;
* to_location_arg (optional): if specified, cards moved &amp;quot;location_arg&amp;quot; is set to given value. Otherwise &amp;quot;location_arg&amp;quot; is set to 0.&lt;br /&gt;
&lt;br /&gt;
Note: if you want to keep &amp;quot;location_arg&amp;quot; untouched, you should use &amp;quot;moveAllCardsInLocationKeepOrder&amp;quot; below.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;moveAllCardsInLocationKeepOrder( $from_location, $to_location )&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Move all cards in specified &amp;quot;from&amp;quot; location to given &amp;quot;to&amp;quot; location. This method does not modify the &amp;quot;location_arg&amp;quot; of cards.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;playCard( $card_id )&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Move specified card at the top of the &amp;quot;discard&amp;quot; location.&lt;br /&gt;
&lt;br /&gt;
Note: this is an alias for: insertCardOnExtremePosition( $card_id, &amp;quot;discard&amp;quot;, true )&lt;br /&gt;
&lt;br /&gt;
=== Get cards informations ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;getCard( $card_id )&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Get specific card information.&lt;br /&gt;
&lt;br /&gt;
Return null if this card is not found.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;getCards( $cards_array )&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Get specific cards information.&lt;br /&gt;
&lt;br /&gt;
$cards_array is an array of card IDs.&lt;br /&gt;
&lt;br /&gt;
If some cards are not found or if some card IDs are specified multiple times, the method throws an (unexpected) Exception.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;getCardsInLocation( $location, $location_arg = null, $order_by = null )&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Get all cards in specific location, as an array. Return an empty array if the location is empty.&lt;br /&gt;
&lt;br /&gt;
* location (string): the location where to get the cards.&lt;br /&gt;
* location_arg (optional): if specified, return only cards with the specified &amp;quot;location_arg&amp;quot;.&lt;br /&gt;
* order_by (optional): if specified, returned cards are ordered by the given database field. Example: &amp;quot;card_id&amp;quot; or &amp;quot;card_type&amp;quot;. &lt;br /&gt;
Using the &amp;quot;order_by&amp;quot; parameter changes the resulting array. Without parameter you get an associative array with the &amp;quot;card_id&amp;quot;, with the paramter you get a simple indexed array.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;countCardInLocation( $location, $location_arg=null )&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Return the number of cards in specified location.&lt;br /&gt;
&lt;br /&gt;
* location (string): the location where to count the cards.&lt;br /&gt;
* location_arg (optional): if specified, count only cards with the specified &amp;quot;location_arg&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;countCardsInLocations()&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Return the number of cards in each location of the game.&lt;br /&gt;
&lt;br /&gt;
The method returns an associative array with the format &amp;quot;location&amp;quot; =&amp;gt; &amp;quot;number of cards&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  array(&lt;br /&gt;
    &#039;deck&#039; =&amp;gt; 12,&lt;br /&gt;
    &#039;hand&#039; =&amp;gt; 21,&lt;br /&gt;
    &#039;discard&#039; =&amp;gt; 54,&lt;br /&gt;
    &#039;ontable&#039; =&amp;gt; 3&lt;br /&gt;
  );&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;countCardsByLocationArgs( $location )&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Return the number of cards in each &amp;quot;location_arg&amp;quot; for the given location.&lt;br /&gt;
&lt;br /&gt;
The method returns an associative array with the format &amp;quot;location_arg&amp;quot; =&amp;gt; &amp;quot;number of cards&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
Example: count the number of cards in each player&#039;s hand:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    countCardsByLocationArgs( &#039;hand&#039; );&lt;br /&gt;
    &lt;br /&gt;
    // Result:&lt;br /&gt;
    array(&lt;br /&gt;
        122345 =&amp;gt; 5,    // player 122345 has 5 cards in hand&lt;br /&gt;
        123456 =&amp;gt; 4     // and player 123456 has 4 cards in hand&lt;br /&gt;
    );&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;getPlayerHand( $player_id )&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Get all cards in given player hand.&lt;br /&gt;
&lt;br /&gt;
Note: This is an alias for:&lt;br /&gt;
getCardsInLocation( &amp;quot;hand&amp;quot;, $player_id )&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;getCardOnTop( $location )&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Get the card on top of the given (&amp;quot;pile&amp;quot; style) location, or null if the location is empty.&lt;br /&gt;
&lt;br /&gt;
Note that the card pile won&#039;t be &amp;quot;auto-reshuffled&amp;quot; if there is no more card available.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;getCardsOnTop( $nbr, $location )&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Get the &amp;quot;$nbr&amp;quot; cards on top of the given (&amp;quot;pile&amp;quot; style) location.&lt;br /&gt;
&lt;br /&gt;
The method return an array with at most &amp;quot;$nbr&amp;quot; elements (or a void array if there is no card in this location).&lt;br /&gt;
&lt;br /&gt;
Note that the card pile won&#039;t be &amp;quot;auto-reshuffled&amp;quot; if there is not enough cards available.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;getExtremePosition( $bGetMax ,$location )&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
(rarely used)&lt;br /&gt;
&lt;br /&gt;
Get the position of cards at the top of the given location / at the bottom of the given location.&lt;br /&gt;
&lt;br /&gt;
Of course this method works only on location in &amp;quot;pile&amp;quot; where you are using &amp;quot;location_arg&amp;quot; to specify the position of each card (example: &amp;quot;deck&amp;quot; location).&lt;br /&gt;
&lt;br /&gt;
If bGetMax=true, return the location of the top card of the pile.&lt;br /&gt;
&lt;br /&gt;
If bGetMax=false, return the location of the bottom card of the pile.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;getCardsOfType( $type, $type_arg=null )&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Get all cards of a specific type (rarely used).&lt;br /&gt;
&lt;br /&gt;
Return an array of cards, or an empty array if there is no cards of the specified type.&lt;br /&gt;
&lt;br /&gt;
* type: the type of cards&lt;br /&gt;
* type_arg: if specified, return only cards with the specified &amp;quot;type_arg&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;getCardsOfTypeInLocation( $type, $type_arg=null, $location, $location_arg = null )&lt;br /&gt;
&lt;br /&gt;
Get all cards of a specific type in a specific location (rarely used).&lt;br /&gt;
&lt;br /&gt;
Return an array of cards, or an empty array if there is no cards of the specified type.&lt;br /&gt;
&lt;br /&gt;
* type: the type of cards&lt;br /&gt;
* type_arg: if specified, return only cards with the specified &amp;quot;type_arg&amp;quot;.&lt;br /&gt;
* location (string): the location where to get the cards.&lt;br /&gt;
* location_arg (optional): if specified, return only cards with the specified &amp;quot;location_arg&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
=== Shuffling ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;shuffle( $location )&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Shuffle all cards in specific location.&lt;br /&gt;
&lt;br /&gt;
Shuffle only works on locations where cards are on a &amp;quot;pile&amp;quot; (ex: &amp;quot;deck&amp;quot;).&lt;br /&gt;
&lt;br /&gt;
Please note that all &amp;quot;location_arg&amp;quot; will be reset to reflect the new order of the cards in the pile.&lt;br /&gt;
&lt;br /&gt;
=== Auto-reshuffle ===&lt;br /&gt;
&lt;br /&gt;
To enable auto-reshuffle you must do &amp;quot;&amp;lt;code&amp;gt;$this-&amp;gt;cards-&amp;gt;autoreshuffle = true&amp;lt;/code&amp;gt;&amp;quot; during the setup of the component (often in the &#039;&#039;_construct&#039;&#039; function when you &#039;&#039;init()&#039;&#039; the Deck object).&lt;br /&gt;
&lt;br /&gt;
Every time a card must be retrieved from the &amp;quot;deck&amp;quot; location, if it is empty the &amp;quot;discard&amp;quot; location will be automatically reshuffled into the &amp;quot;deck&amp;quot; location.&lt;br /&gt;
&lt;br /&gt;
If you need to notify players when the deck is shuffled, you can setup a callback method using this feature: &amp;lt;pre&amp;gt;$this-&amp;gt;cards-&amp;gt;autoreshuffle_trigger = array(&#039;obj&#039; =&amp;gt; $this, &#039;method&#039; =&amp;gt; &#039;deckAutoReshuffle&#039;);&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If you need to use other locations than &amp;quot;deck&amp;quot; and &amp;quot;discard&amp;quot; for auto-reshuffle feature, you can configure it this way: &amp;lt;pre&amp;gt;$this-&amp;gt;cards-&amp;gt;autoreshuffle_custom = array(&#039;deck&#039; =&amp;gt; &#039;discard&#039;);&amp;lt;/pre&amp;gt; (replace &#039;deck&#039; and &#039;discard&#039; with your custom locations).&lt;br /&gt;
&lt;br /&gt;
[[Category:Studio]]&lt;/div&gt;</summary>
		<author><name>Sguzzer Gunayer</name></author>
	</entry>
	<entry>
		<id>https://en.doc.boardgamearena.com/index.php?title=Your_game_state_machine:_states.inc.php&amp;diff=22600</id>
		<title>Your game state machine: states.inc.php</title>
		<link rel="alternate" type="text/html" href="https://en.doc.boardgamearena.com/index.php?title=Your_game_state_machine:_states.inc.php&amp;diff=22600"/>
		<updated>2024-09-16T18:31:03Z</updated>

		<summary type="html">&lt;p&gt;Sguzzer Gunayer: /* Designing states */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Studio_Framework_Navigation}}&lt;br /&gt;
&lt;br /&gt;
This file describes the state machine of your game (all the game states properties, and the transitions to get from one state to another).&lt;br /&gt;
&lt;br /&gt;
Important: to understand the game state machine, it&#039;s recommended that you read this presentation first:&lt;br /&gt;
&lt;br /&gt;
[http://www.slideshare.net/boardgamearena/bga-studio-focus-on-bga-game-state-machine Focus on BGA game state machine]&lt;br /&gt;
&lt;br /&gt;
== Overall structure ==&lt;br /&gt;
&lt;br /&gt;
The machine states are described by a PHP associative array.&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$machinestates = array(&lt;br /&gt;
&lt;br /&gt;
    // The initial state. Please do not modify.&lt;br /&gt;
    1 =&amp;gt; array(&lt;br /&gt;
        &amp;quot;name&amp;quot; =&amp;gt; &amp;quot;gameSetup&amp;quot;,&lt;br /&gt;
        &amp;quot;description&amp;quot; =&amp;gt; clienttranslate(&amp;quot;Game setup&amp;quot;),&lt;br /&gt;
        &amp;quot;type&amp;quot; =&amp;gt; &amp;quot;manager&amp;quot;,&lt;br /&gt;
        &amp;quot;action&amp;quot; =&amp;gt; &amp;quot;stGameSetup&amp;quot;,&lt;br /&gt;
        &amp;quot;transitions&amp;quot; =&amp;gt; array( &amp;quot;&amp;quot; =&amp;gt; 2 )&lt;br /&gt;
    ),&lt;br /&gt;
    &lt;br /&gt;
    // Note: ID=2 =&amp;gt; your first state&lt;br /&gt;
&lt;br /&gt;
    2 =&amp;gt; array(&lt;br /&gt;
    		&amp;quot;name&amp;quot; =&amp;gt; &amp;quot;playerTurn&amp;quot;,&lt;br /&gt;
    		&amp;quot;description&amp;quot; =&amp;gt; clienttranslate(&#039;${actplayer} must play a card or pass&#039;),&lt;br /&gt;
    		&amp;quot;descriptionmyturn&amp;quot; =&amp;gt; clienttranslate(&#039;${you} must play a card or pass&#039;),&lt;br /&gt;
    		&amp;quot;type&amp;quot; =&amp;gt; &amp;quot;activeplayer&amp;quot;,&lt;br /&gt;
    		&amp;quot;possibleactions&amp;quot; =&amp;gt; array( &amp;quot;actPlayCard&amp;quot;, &amp;quot;actPass&amp;quot; ),&lt;br /&gt;
    		&amp;quot;transitions&amp;quot; =&amp;gt; array( &amp;quot;playCard&amp;quot; =&amp;gt; 2, &amp;quot;pass&amp;quot; =&amp;gt; 2 )&lt;br /&gt;
    ),&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Syntax ==&lt;br /&gt;
&lt;br /&gt;
=== id ===&lt;br /&gt;
&lt;br /&gt;
The keys determine game state IDs (in the example above: 1 and 2).&lt;br /&gt;
&lt;br /&gt;
IDs must be positive integers.&lt;br /&gt;
&lt;br /&gt;
ID=1 is reserved for the first game state and should not be used (and you must not modify it).&lt;br /&gt;
&lt;br /&gt;
ID=99 is reserved for the last game state (end of the game) (and you must not modify it).&lt;br /&gt;
&lt;br /&gt;
Note: you may use any ID, even an ID greater than 100. But you cannot use 1 or 99.&lt;br /&gt;
&lt;br /&gt;
Note²: You must not use the same ID twice.&lt;br /&gt;
&lt;br /&gt;
Note³: When a game is in prod and you change the ID of a state, all active games (including many turn based) will behave unpredictably.&lt;br /&gt;
&lt;br /&gt;
=== name ===&lt;br /&gt;
&lt;br /&gt;
(&#039;&#039;&#039;Mandatory&#039;&#039;&#039;)&lt;br /&gt;
&lt;br /&gt;
The name of a game state is used to identify it in your game logic.&lt;br /&gt;
&lt;br /&gt;
Several game states can share the same name; however, this is not recommended.&lt;br /&gt;
&lt;br /&gt;
Warning! Do not put spaces in the name. This could cause unexpected problems in some cases.&lt;br /&gt;
&lt;br /&gt;
PHP example:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
// Get current game state&lt;br /&gt;
$state = $this-&amp;gt;gamestate-&amp;gt;state();&lt;br /&gt;
if( $state[&#039;name&#039;] == &#039;myGameState&#039; )&lt;br /&gt;
{&lt;br /&gt;
...&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
JS example:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        onEnteringState: function( stateName, args )&lt;br /&gt;
        {&lt;br /&gt;
            console.log( &#039;Entering state: &#039;+stateName );&lt;br /&gt;
            &lt;br /&gt;
            switch( stateName )&lt;br /&gt;
            case &#039;myGameState&#039;:&lt;br /&gt;
            &lt;br /&gt;
                // Do some stuff at the beginning at this game state&lt;br /&gt;
                ....&lt;br /&gt;
                &lt;br /&gt;
                break;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== type ===&lt;br /&gt;
&lt;br /&gt;
(&#039;&#039;&#039;Mandatory&#039;&#039;&#039;)&lt;br /&gt;
&lt;br /&gt;
You can use 3 types of game states:&lt;br /&gt;
* activeplayer (1 player is active and must play.)&lt;br /&gt;
* multipleactiveplayer (1..N players can be active and must play.)&lt;br /&gt;
* private (during multiactive states players can independently move to different private parallel states. See more details [[#Private_parallel_states|here]].&lt;br /&gt;
* game (No player is active. This is a transitional state to do something automatic specified by the game rules.)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note:&#039;&#039;&#039; Make sure you don&#039;t mistype the value of this attribute. If you do (e.g. &#039;multiactiveplayer&#039; instead of &#039;multipleactiveplayer&#039;), things won&#039;t work, and you might have a hard time figuring out why.&lt;br /&gt;
&lt;br /&gt;
=== description ===&lt;br /&gt;
&lt;br /&gt;
(&#039;&#039;&#039;Mandatory&#039;&#039;&#039;)&lt;br /&gt;
&lt;br /&gt;
The description is the string that is displayed in the main action bar (top of the screen) when the state is active.&lt;br /&gt;
&lt;br /&gt;
When a string is specified as a description, you must use &amp;quot;clienttranslate&amp;quot; in order for the string to be translated on the client side:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 		&amp;quot;description&amp;quot; =&amp;gt; clienttranslate(&#039;${actplayer} must play a card or pass&#039;),&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In the description string, you can use ${actplayer} to refer to the active player.&lt;br /&gt;
&lt;br /&gt;
You can also use custom arguments in your description. These custom arguments correspond to values returned by your &amp;quot;args&amp;quot; PHP method (see below &amp;quot;args&amp;quot; field).&lt;br /&gt;
&lt;br /&gt;
Example of custom field:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In states.inc.php:&lt;br /&gt;
        &amp;quot;description&amp;quot; =&amp;gt; clienttranslate(&#039;${actplayer} must choose ${nbr} identical energies&#039;),&lt;br /&gt;
        &amp;quot;args&amp;quot; =&amp;gt; &amp;quot;argMyArgumentMethod&amp;quot;&lt;br /&gt;
&lt;br /&gt;
In mygame.game.php:&lt;br /&gt;
    function argMyArgumentMethod()&lt;br /&gt;
    {&lt;br /&gt;
        return array(&lt;br /&gt;
            &#039;nbr&#039; =&amp;gt; 2  // In this case ${nbr} in the description will be replaced by &amp;quot;2&amp;quot;&lt;br /&gt;
        );    &lt;br /&gt;
    }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note: You may specify an empty string (&amp;quot;&amp;quot;) here if it never happens that the game remains in this state (i.e., if this state immediately jumps to another state when activated).&lt;br /&gt;
&lt;br /&gt;
Note²: Usually, you specify a string for &amp;quot;activeplayer&amp;quot; and &amp;quot;multipleactiveplayer&amp;quot; game states, and you specify an empty string for &amp;quot;game&amp;quot; game states. BUT, if you are using synchronous notifications, the client can remain on a &amp;quot;game&amp;quot; type game state for a few seconds, and in this case it may be useful to display a description in the status bar while in this state.&lt;br /&gt;
&lt;br /&gt;
=== descriptionmyturn ===&lt;br /&gt;
&lt;br /&gt;
(&#039;&#039;&#039;Mandatory&#039;&#039;&#039; when the state type is &amp;quot;activeplayer&amp;quot; or &amp;quot;multipleactiveplayer&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
&amp;quot;descriptionmyturn&amp;quot; has exactly the same role and properties as &amp;quot;description&amp;quot;, except that this value is displayed to the current active player - or to all active players in case of a multipleactiveplayer game state.&lt;br /&gt;
&lt;br /&gt;
In general, we have this situation:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        &amp;quot;description&amp;quot; =&amp;gt; clienttranslate(&#039;${actplayer} can take some actions&#039;),&lt;br /&gt;
        &amp;quot;descriptionmyturn&amp;quot; =&amp;gt; clienttranslate(&#039;${you} can take some actions&#039;),&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note: you can use ${you} in descriptionmyturn so the description will display &amp;quot;You&amp;quot; instead of the name of the player.&lt;br /&gt;
&lt;br /&gt;
Note 2: you can use ${otherplayer} to refer to some other player if you want this to be shown in player&#039;s color, but you must provide otherplayer_id as argument (along with otherplayer) to specify this player&#039;s id in this case or game won&#039;t load.&lt;br /&gt;
&lt;br /&gt;
I.e.&lt;br /&gt;
&lt;br /&gt;
 &amp;quot;descriptionmyturn&amp;quot; =&amp;gt; clienttranslate(&#039;${you} can follow action of ${otherplayer}&#039;),&lt;br /&gt;
&lt;br /&gt;
And this will have to be state arguments for this&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    function arg_playerTurnFollow(){&lt;br /&gt;
        return [&#039;otherplayer&#039;=&amp;gt; $this-&amp;gt;getLeaderPlayerName(),&lt;br /&gt;
                &#039;otherplayer_id&#039;=&amp;gt; $this-&amp;gt;getLeaderPlayerId()&lt;br /&gt;
        ];&lt;br /&gt;
    }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== action ===&lt;br /&gt;
&lt;br /&gt;
(&#039;&#039;&#039;Mandatory&#039;&#039;&#039; when the state type is &amp;quot;game.&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
&amp;quot;action&amp;quot; specifies a PHP method to call when entering this game state.&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
In states.inc.php:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    28 =&amp;gt; array(&lt;br /&gt;
        &amp;quot;name&amp;quot; =&amp;gt; &amp;quot;gameTurnNextPlayer&amp;quot;,&lt;br /&gt;
        &amp;quot;description&amp;quot; =&amp;gt; clienttranslate(&#039;Updating some stuff...&#039;),&lt;br /&gt;
        &amp;quot;type&amp;quot; =&amp;gt; &amp;quot;game&amp;quot;,&lt;br /&gt;
        &amp;quot;action&amp;quot; =&amp;gt; &amp;quot;st_gameTurnNextPlayer&amp;quot;,&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
In mygame.game.php:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    function st_gameTurnNextPlayer() {&lt;br /&gt;
        $player_id = $this-&amp;gt;getActivePlayerId();&lt;br /&gt;
        $next_player_id = $this-&amp;gt;getPlayerAfter($player_id);&lt;br /&gt;
        $this-&amp;gt;giveExtraTime($next_player_id);&lt;br /&gt;
        $this-&amp;gt;incStat(1, &#039;turns_number&#039;, $next_player_id);&lt;br /&gt;
        $this-&amp;gt;incStat(1, &#039;turns_number&#039;);&lt;br /&gt;
        $this-&amp;gt;gamestate-&amp;gt;changeActivePlayer($next_player_id);&lt;br /&gt;
        $this-&amp;gt;gamestate-&amp;gt;nextState(&#039;next&#039;);&lt;br /&gt;
    }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Usually, for a &amp;quot;game&amp;quot; state type, the action method is used to perform automatic functions specified by the rules (for example: check victory conditions, deal cards for a new round, go to the next player, etc.) and then jump to another game state.&lt;br /&gt;
&lt;br /&gt;
Note: a BGA convention specifies that PHP methods called with &amp;quot;action&amp;quot; are prefixed by &amp;quot;st&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
Note: this field CAN be used for player states to set something up; e.g., for multiplayer states, it can make all players active.&lt;br /&gt;
&lt;br /&gt;
Example for action in player state:&lt;br /&gt;
in states.inc.php:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    2 =&amp;gt; array(&lt;br /&gt;
    		&amp;quot;name&amp;quot; =&amp;gt; &amp;quot;playerTurnPlace&amp;quot;,&lt;br /&gt;
    		&amp;quot;description&amp;quot; =&amp;gt; clienttranslate(&#039;Other player must place ships&#039;),&lt;br /&gt;
    		&amp;quot;descriptionmyturn&amp;quot; =&amp;gt; clienttranslate(&#039;${you} must place ships (click on YOUR SHIPS board to place)&#039;),&lt;br /&gt;
    		&amp;quot;type&amp;quot; =&amp;gt; &amp;quot;multipleactiveplayer&amp;quot;,&lt;br /&gt;
            &#039;action&#039; =&amp;gt; &#039;st_MultiPlayerInit&#039;,&lt;br /&gt;
            &#039;args&#039; =&amp;gt; &#039;arg_playerTurnPlace&#039;,&lt;br /&gt;
    		&amp;quot;possibleactions&amp;quot; =&amp;gt; array( &amp;quot;playPlace&amp;quot; ),&lt;br /&gt;
            &amp;quot;transitions&amp;quot; =&amp;gt; array( &amp;quot;next&amp;quot; =&amp;gt; 4, &amp;quot;last&amp;quot; =&amp;gt; 99)&lt;br /&gt;
    ),&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
in mygame.game.php:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    function st_MultiPlayerInit() {&lt;br /&gt;
        $this-&amp;gt;gamestate-&amp;gt;setAllPlayersMultiactive();&lt;br /&gt;
    }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&#039;&#039;&#039;Warning&#039;&#039;&#039;: Prevent to do anything on stGameEnd() and argGameEnd() in mygame.game.php. It may cause game never end and always stuck in &amp;quot;Recording game results + computing statistics in progress...&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
=== transitions ===&lt;br /&gt;
&lt;br /&gt;
(&#039;&#039;&#039;Mandatory&#039;&#039;&#039;)&lt;br /&gt;
&lt;br /&gt;
With &amp;quot;transitions&amp;quot; you specify which game state(s) you can jump to from a given game state.&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    25 =&amp;gt; array(&lt;br /&gt;
        &amp;quot;name&amp;quot; =&amp;gt; &amp;quot;myGameState&amp;quot;,&lt;br /&gt;
        &amp;quot;transitions&amp;quot; =&amp;gt; array( &amp;quot;nextPlayer&amp;quot; =&amp;gt; 27, &amp;quot;endRound&amp;quot; =&amp;gt; 39 ),&lt;br /&gt;
        ....&lt;br /&gt;
    }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In the example above, if &amp;quot;myGameState&amp;quot; is the current active game state, I can jump to the game state with ID 27 or the game state with ID 39.&lt;br /&gt;
&lt;br /&gt;
Example to jump to ID 27:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
In mygame.game.php:&lt;br /&gt;
    $this-&amp;gt;gamestate-&amp;gt;nextState( &amp;quot;nextPlayer&amp;quot; );&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Important: &amp;quot;nextPlayer&amp;quot; is the name of the transition, and NOT the name of the target game state. Multiple transitions can lead to the same game state.&lt;br /&gt;
&lt;br /&gt;
Note: If there is only 1 transition, you may give it an empty name.&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
In states.inc.php:&lt;br /&gt;
    &amp;quot;transitions&amp;quot; =&amp;gt; array( &amp;quot;&amp;quot; =&amp;gt; 27 ),&lt;br /&gt;
&lt;br /&gt;
In mygame.game.php:&lt;br /&gt;
    $this-&amp;gt;gamestate-&amp;gt;nextState(  );     // We don&#039;t need to specify a transition as there is only one here&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== possibleactions ===&lt;br /&gt;
&lt;br /&gt;
(&#039;&#039;&#039;Mandatory&#039;&#039;&#039; when the game state is &amp;quot;activeplayer&amp;quot; or &amp;quot;multipleactiveplayer&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
&amp;quot;possibleactions&amp;quot; defines the actions possible by the players in this game state, and ensures they cannot perform actions that are not allowed in this state.&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
In states.game.php:&lt;br /&gt;
       	&amp;quot;possibleactions&amp;quot; =&amp;gt; array( &amp;quot;actPlayCard&amp;quot;, &amp;quot;actPass&amp;quot; ),&lt;br /&gt;
&lt;br /&gt;
In mygame.game.php:&lt;br /&gt;
        function actPlayCard( ...)&lt;br /&gt;
        {&lt;br /&gt;
             $this-&amp;gt;checkAction( &amp;quot;actPlayCard&amp;quot; );    // Will fail if &amp;quot;actPlayCard&amp;quot; is not specified in &amp;quot;possibleactions&amp;quot; in the current game state.&lt;br /&gt;
&lt;br /&gt;
            ....&lt;br /&gt;
&lt;br /&gt;
In mygame.js:&lt;br /&gt;
        playCard: function( ... )&lt;br /&gt;
        {&lt;br /&gt;
            if( this.checkAction( &amp;quot;actPlayCard&amp;quot; ) ) // Will fail if &amp;quot;actPlayCard&amp;quot; is not specified in &amp;quot;possibleactions&amp;quot; in the current game state.&lt;br /&gt;
            {  return ;   }&lt;br /&gt;
// or &lt;br /&gt;
        playCard: function( ... )&lt;br /&gt;
        {&lt;br /&gt;
            if( this.bgaPerformAction( &amp;quot;actPlayCard&amp;quot;, { id} ) ) // Will not trigger if &amp;quot;actPlayCard&amp;quot; is not specified in &amp;quot;possibleactions&amp;quot; in the current game state.&lt;br /&gt;
            {  return ;   }&lt;br /&gt;
&lt;br /&gt;
            ....&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== args ===&lt;br /&gt;
&lt;br /&gt;
(optional)&lt;br /&gt;
&lt;br /&gt;
Sometimes it happens that you need some information on the client side (i.e., for your game interface) only for a specific game state.&lt;br /&gt;
&lt;br /&gt;
Example 1: in &#039;&#039;Reversi&#039;&#039;, the list of possible moves during the playerTurn state.&lt;br /&gt;
&lt;br /&gt;
Example 2: in &#039;&#039;Caylus&#039;&#039;, the number of remaining king&#039;s favors to choose in the state where the player is choosing a favor.&lt;br /&gt;
&lt;br /&gt;
Example 3: in &#039;&#039;Can&#039;t Stop&#039;&#039;, the list of possible die combinations to be displayed to the active player so that he can choose from among them.&lt;br /&gt;
&lt;br /&gt;
In such a situation, you can specify a method name as the « args » argument for your game state. This method must retrieve some piece of information about the game (example: for &#039;&#039;Reversi&#039;&#039;, the list of possible moves) and return it.&lt;br /&gt;
&lt;br /&gt;
Thus, this data can be transmitted to the clients and used by the clients to display it. It should always be an associative array.&lt;br /&gt;
&lt;br /&gt;
Let&#039;s see a complete example using args with &#039;&#039;Reversi&#039;&#039; game:&lt;br /&gt;
&lt;br /&gt;
In states.inc.php, we specify an &#039;&#039;&#039;args&#039;&#039;&#039; argument for gamestate &#039;&#039;&#039;playerTurn&#039;&#039;&#039;:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    10 =&amp;gt; array(&lt;br /&gt;
        &amp;quot;name&amp;quot; =&amp;gt; &amp;quot;playerTurn&amp;quot;,&lt;br /&gt;
		&amp;quot;description&amp;quot; =&amp;gt; clienttranslate(&#039;${actplayer} must play a disc&#039;),&lt;br /&gt;
		&amp;quot;descriptionmyturn&amp;quot; =&amp;gt; clienttranslate(&#039;${you} must play a disc&#039;),&lt;br /&gt;
        &amp;quot;type&amp;quot; =&amp;gt; &amp;quot;activeplayer&amp;quot;,&lt;br /&gt;
        &amp;quot;args&amp;quot; =&amp;gt; &amp;quot;argPlayerTurn&amp;quot;,    // &amp;lt;==== HERE&lt;br /&gt;
        &amp;quot;possibleactions&amp;quot; =&amp;gt; array( &#039;actPlayDisc&#039; ),&lt;br /&gt;
        &amp;quot;transitions&amp;quot; =&amp;gt; array( &amp;quot;playDisc&amp;quot; =&amp;gt; 11, &amp;quot;zombiePass&amp;quot; =&amp;gt; 11 )&lt;br /&gt;
    ),&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
It corresponds to a &#039;&#039;&#039;argPlayerTurn&#039;&#039;&#039; method in our PHP code (reversi.game.php):&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    function argPlayerTurn() {&lt;br /&gt;
        return array(&lt;br /&gt;
            &#039;possibleMoves&#039; =&amp;gt; $this-&amp;gt;getPossibleMoves()&lt;br /&gt;
        );&lt;br /&gt;
    }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Then, when we enter into the &#039;&#039;&#039;playerTurn&#039;&#039;&#039; game state on the client side, we can highlight the possible moves on the board using information returned by &#039;&#039;&#039;argPlayerTurn&#039;&#039;&#039;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        onEnteringState: function( stateName, args )  {&lt;br /&gt;
           console.log( &#039;Entering state: &#039;+stateName );&lt;br /&gt;
            &lt;br /&gt;
            switch( stateName )  {&lt;br /&gt;
            case &#039;playerTurn&#039;:&lt;br /&gt;
                this.updatePossibleMoves( args.args.possibleMoves );&lt;br /&gt;
                break;&lt;br /&gt;
            }&lt;br /&gt;
        },&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Naming and API conventions ====&lt;br /&gt;
&lt;br /&gt;
As a BGA convention, PHP methods called with &amp;quot;args&amp;quot; are prefixed by &amp;quot;arg&amp;quot; followed by state name (example: &#039;&#039;&#039;argPlayerTurn&#039;&#039;&#039;).&lt;br /&gt;
&lt;br /&gt;
All &amp;quot;arg*&amp;quot; methods are put into corresponding section of .game.php file commented as&lt;br /&gt;
   //////////// Game state arguments&lt;br /&gt;
&lt;br /&gt;
Arg method MUST return array. Return integer or string will result in some undebuggable exceptions.&lt;br /&gt;
&lt;br /&gt;
Arg method MUST be defined in php if it is declared in state description, if you don&#039;t need it comment it out from the states.inc.php file (the &#039;&#039;&#039;args&#039;&#039;&#039; parameter). If you not sure if you need it or not you can keep it returning empty array until you figure it out.&lt;br /&gt;
&lt;br /&gt;
    function argPlayerTurn() {&lt;br /&gt;
        return array(); // must be an array&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Warning&#039;&#039;&#039;: the &amp;quot;args&amp;quot; method is ALWAYS called before the &amp;quot;action&amp;quot; method so don&#039;t expect data modifications by the &amp;quot;action&amp;quot; method to be available in the &amp;quot;args&amp;quot; method!&lt;br /&gt;
Also don&#039;t modify database in this method!&lt;br /&gt;
&lt;br /&gt;
You should NOT be calling getCurrentPlayer() in the context of this function, since state transitions are broadcasted to all player independent of who initiated it. Instead you should send information on per player basis (Note: if this is private info see section below). &lt;br /&gt;
&lt;br /&gt;
If you using this function in multi-player state, you should not call getActivePlayer() either, you should send per player info:&lt;br /&gt;
&lt;br /&gt;
    function arg_playerTurn() {&lt;br /&gt;
        $res = array ();&lt;br /&gt;
        $players = $this-&amp;gt;loadPlayersBasicInfos();&lt;br /&gt;
        foreach ( $players as $player_id =&amp;gt; $player_info ) {&lt;br /&gt;
            $color = $player_info [&#039;player_color&#039;];&lt;br /&gt;
            $res [$player_id] = array(&amp;quot;color&amp;quot;=&amp;gt;$color);&lt;br /&gt;
        }&lt;br /&gt;
        return $res;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
Note: you never need to send player color like this, this is just an example.&lt;br /&gt;
&lt;br /&gt;
Note 2: you CAN call methods that return all active players if multi-player states if its relevant.&lt;br /&gt;
&lt;br /&gt;
==== Other usages ====&lt;br /&gt;
&lt;br /&gt;
You can use values returned by your &amp;quot;args&amp;quot; method to have some custom values in your &amp;quot;description&amp;quot;/&amp;quot;descriptionmyturn&amp;quot;, i.e. in states.inc.php:&lt;br /&gt;
&lt;br /&gt;
   &amp;quot;descriptionmyturn&amp;quot; =&amp;gt; clienttranslate(&#039;${you} must play ${color} disc&#039;),&lt;br /&gt;
&lt;br /&gt;
So arg function will be something like:&lt;br /&gt;
&lt;br /&gt;
  function argPlayerTurn() {&lt;br /&gt;
        return array(&#039;color&#039;=&amp;gt;$this-&amp;gt;getActivePlayerColor()); &lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
You can use args also in &#039;&#039;&#039;onUpdateActionButtons&#039;&#039;&#039; function on js side, however two important notes:&lt;br /&gt;
* it is just &#039;&#039;&#039;args&#039;&#039;&#039; (not args.args like in &#039;&#039;&#039;onEnteringState&#039;&#039;&#039;)&lt;br /&gt;
* it is args of the current state, which may not be state you think it will be! This method is called during change of active player, which happens in some weird place especially during &amp;quot;multipleactiveplayer&amp;quot; states. If you pulling your hair thinking why its &amp;quot;undefined&amp;quot; on js side - check the current state.&lt;br /&gt;
&lt;br /&gt;
==== Private info in args ====&lt;br /&gt;
&lt;br /&gt;
By default, all data provided through this method are PUBLIC TO ALL PLAYERS. Please do not send any private data with this method, as a cheater could see it even it is not used explicitly by the game interface logic.&lt;br /&gt;
&lt;br /&gt;
However, it is possible to specify that some data should be sent to specific players only.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note: You cannot use Example 1 and Example 2 together. If you have to send private args to multiple players, use Example 2.&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Example 1: send information to active player(s) only:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    function argPlayerTurn()  {&lt;br /&gt;
        return array(&lt;br /&gt;
            &#039;_private&#039; =&amp;gt; array(          // Using &amp;quot;_private&amp;quot; keyword, all data inside this array will be made private&lt;br /&gt;
                &#039;active&#039; =&amp;gt; array(       // Using &amp;quot;active&amp;quot; keyword inside &amp;quot;_private&amp;quot;, you select active player(s)&lt;br /&gt;
                    &#039;somePrivateData&#039; =&amp;gt; $this-&amp;gt;getSomePrivateData()   // will be send only to active player(s)&lt;br /&gt;
                )&lt;br /&gt;
            ),&lt;br /&gt;
            &#039;possibleMoves&#039; =&amp;gt; $this-&amp;gt;getPossibleMoves()          // will be sent to all players&lt;br /&gt;
        );&lt;br /&gt;
    }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Inside the js file, these variables will be available through `args.args._private`. (e.g. `args.args._private.somePrivateData` -- it is not `args._private.active.somePrivateData` nor is it `args.somePrivateData`)&lt;br /&gt;
&lt;br /&gt;
Example 2: send information to a specific player (&amp;lt;specific_player_id&amp;gt;) only:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    function argPlayerTurn()  {&lt;br /&gt;
        $specific_player_id = ...; // calculate some-how&lt;br /&gt;
        return array(&lt;br /&gt;
            &#039;_private&#039; =&amp;gt; array(   // all data inside this array will be private&lt;br /&gt;
                $specific_player_id =&amp;gt; array(   // will be sent only to that player   &lt;br /&gt;
                    &#039;somePrivateData&#039; =&amp;gt; $this-&amp;gt;getSomePrivateData()   &lt;br /&gt;
                )&lt;br /&gt;
            ),&lt;br /&gt;
&lt;br /&gt;
            &#039;possibleMoves&#039; =&amp;gt; $this-&amp;gt;getPossibleMoves()   // will be sent to all players&lt;br /&gt;
        );&lt;br /&gt;
    }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
IMPORTANT: in certain situations (i.e. &amp;quot;multipleactiveplayer&amp;quot; game state) these &amp;quot;private data&amp;quot; features can have a significant impact on performance. Please do not use if not needed.&lt;br /&gt;
&lt;br /&gt;
It is also possible to use these private args in the &amp;quot;description&amp;quot; messages, like &amp;quot;${you} have to play ${_private.count} cards&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
==== Flag to indicate a skipped state ====&lt;br /&gt;
&lt;br /&gt;
By default, The front-end will be notified of entering/leaving all states. To speed up the front-end chaining of automatically passed states, you can disable this state change notification, so the front-end doesn&#039;t trigger the preparation steps for a state that you know will be automatically skipped, and it may reduce sent args. In this case, define the &#039;&#039;&#039;_no_notify&#039;&#039;&#039; flag to true in the state args.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
function argPlayerTurn()  {&lt;br /&gt;
  $playableCardsIds = ...;&lt;br /&gt;
  return [&lt;br /&gt;
    &#039;playableCardsIds&#039; =&amp;gt; $playableCardsIds,&lt;br /&gt;
    &#039;_no_notify&#039; =&amp;gt; count(playableCardsIds) === 0,&lt;br /&gt;
  ];&lt;br /&gt;
}&lt;br /&gt;
function stPlayerTurn()  {&lt;br /&gt;
  $args = $this-&amp;gt;argPlayerTurn();&lt;br /&gt;
  if ($args[&#039;_no_notify&#039;]) {&lt;br /&gt;
    $this-&amp;gt;gamestate-&amp;gt;nextState(&#039;next&#039;);&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In this example, it might avoid a blinking message &amp;quot;You must play a card&amp;quot; (quickly replaced by the next state message) when you cannot play a card and the game automatically skips this state.&lt;br /&gt;
&lt;br /&gt;
IMPORTANT: if you use _no_notify, you must handle a redirection to another state on the st function!&lt;br /&gt;
&lt;br /&gt;
Note that if you play synced notifications during a skipped state, it will display the notifications on the previous state. For example, for an endScore state width description &amp;quot;Computing end score...&amp;quot; sending a lot of animated notifications, you should NOT use this flag so the description is visible.&lt;br /&gt;
&lt;br /&gt;
==== Translations in args ====&lt;br /&gt;
You can do the same as in notification by adding i18n parameter, i.e&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
function argPlayerTurn()  {&lt;br /&gt;
 return [&lt;br /&gt;
      &#039;i18n&#039; =&amp;gt; [&#039;terrainName&#039; ],&lt;br /&gt;
      &#039;terrainName&#039; =&amp;gt; ($this-&amp;gt;token_types[$terrain][&#039;name&#039;]), // this should be defined in material.inc.php and with clienttranslate &lt;br /&gt;
      &#039;terrain&#039; =&amp;gt; $terrain,&lt;br /&gt;
   ];&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Than you can do something like this in state:&lt;br /&gt;
  &amp;quot;descriptionmyturn&amp;quot; =&amp;gt; clienttranslate(&#039;${you} must place a house on ${terrainName}&#039;),&lt;br /&gt;
&lt;br /&gt;
See more in [[Translations]]&lt;br /&gt;
&lt;br /&gt;
=== updateGameProgression ===&lt;br /&gt;
&lt;br /&gt;
(optional)&lt;br /&gt;
&lt;br /&gt;
If you specify &amp;quot;updateGameProgression =&amp;gt; true&amp;quot; in a game state, your &amp;quot;getGameProgression&amp;quot; PHP method will be called at the beginning of this game state - and thus the game progression of the game will be updated.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;At least one&#039;&#039; of your game states (any one) must specify &amp;quot;updateGameProgression=&amp;gt;true&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
=== initialprivate ===&lt;br /&gt;
&lt;br /&gt;
(optional)&lt;br /&gt;
&lt;br /&gt;
This parameter will enable private parallel states in a multiplayer state. Parameter should be set to first private parallel state a player will be transitioned to.&lt;br /&gt;
See more details about Private parallel states [[#Private_parallel_states|here]].&lt;br /&gt;
&lt;br /&gt;
== Implementation Notes ==&lt;br /&gt;
&lt;br /&gt;
=== Private parallel states ===&lt;br /&gt;
&lt;br /&gt;
Private parallel states are useful when multiple players are active and their turn is very complex. In that case it is possible with parallel states for each player to be in a independent state. &lt;br /&gt;
&lt;br /&gt;
Lets say that players need to do three complex action one after another in multiactive state. With parallel states each player can independently be in a different state (i.e. one player still need to decide about first action while some players are deciding their second action and the fastest player is already on their third action. Normally this can be handled with two simple, but limited, approaches:&lt;br /&gt;
&lt;br /&gt;
* Moving all players to different states together - this is limiting for faster players as they need to wait other players for each separate action. The more problematic thing is that it would be hard to implement an undo feature when one player wants to change their previous action. In that case all players should be moved back to previous state which will interrupt their flow.&lt;br /&gt;
* Using client states, by changing the state in which the player is in javascript - the problem with this approach is that players will lose their progress on browser refresh (F5). Furthermore the validation logic of specific actions should be implemented on both server side and client side and we cannot have specific args for each different action, but they should be calculated only at the beginning of the first action and possibly calculated on client side after each action, which again duplicates logic on client and server.&lt;br /&gt;
&lt;br /&gt;
With private parallel states, each specific action can be implemented as a parallel state. Parallel states are defined with the type &#039;private&#039; and players are moved to those private states during one master multiactive state. Lets look at the example:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    10 =&amp;gt; [&lt;br /&gt;
        &amp;quot;name&amp;quot; =&amp;gt; &amp;quot;playerTurn&amp;quot;,&lt;br /&gt;
        &amp;quot;description&amp;quot; =&amp;gt; clienttranslate(&#039;Waiting for other players to end their turn.&#039;),&lt;br /&gt;
        &amp;quot;descriptionmyturn&amp;quot; =&amp;gt; clienttranslate(&#039;${you} must do your turn&#039;), // Won&#039;t be displayed anyway since each private state has its own description&lt;br /&gt;
        &amp;quot;type&amp;quot; =&amp;gt; &amp;quot;multipleactiveplayer&amp;quot;,&lt;br /&gt;
        &amp;quot;initialprivate&amp;quot; =&amp;gt; 50, // This makes this state a master multiactive state and enables private states, this is also a first private state&lt;br /&gt;
        &amp;quot;action&amp;quot; =&amp;gt; &amp;quot;stPlayerTurn&amp;quot;,&lt;br /&gt;
        &amp;quot;args&amp;quot; =&amp;gt; &amp;quot;argPlayerTurn&amp;quot;,&lt;br /&gt;
        &amp;quot;possibleactions&amp;quot; =&amp;gt; [&amp;quot;actChangeMind&amp;quot;], //this action is possible if player is not in any private state which usually happens when they are inactive&lt;br /&gt;
        &amp;quot;transitions&amp;quot; =&amp;gt; [&amp;quot;playersDecide&amp;quot; =&amp;gt; 11] // this is normal next transition which will happen after all players finish their turns &lt;br /&gt;
    ],&lt;br /&gt;
&lt;br /&gt;
    50 =&amp;gt; [&lt;br /&gt;
        &amp;quot;name&amp;quot; =&amp;gt; &amp;quot;chooseFirst&amp;quot;,&lt;br /&gt;
        &amp;quot;descriptionmyturn&amp;quot; =&amp;gt; clienttranslate(&#039;${you} must make your first choice&#039;), // just this parameter is needed. description is not needed as no player is inactive in this state&lt;br /&gt;
        &amp;quot;type&amp;quot; =&amp;gt; &amp;quot;private&amp;quot;, // this state is reachable only as a private state&lt;br /&gt;
        &amp;quot;args&amp;quot; =&amp;gt; &amp;quot;argChooseFirst&amp;quot;, //this method will be called with playerId as a parametar and is used to calculate arguments for this action for specific player&lt;br /&gt;
        &amp;quot;action&amp;quot; =&amp;gt; &amp;quot;stChooseFirst&amp;quot;, // this method will be called with playerId as a parameter and can be used to make some changes when player enters this private state&lt;br /&gt;
        &amp;quot;possibleactions&amp;quot; =&amp;gt; [&amp;quot;actToSecond&amp;quot;],&lt;br /&gt;
        &amp;quot;transitions&amp;quot; =&amp;gt; [&lt;br /&gt;
          &#039;chooseSecond&#039; =&amp;gt; 51, // transition to another private state&lt;br /&gt;
        ]&lt;br /&gt;
      ],&lt;br /&gt;
   &lt;br /&gt;
    51 =&amp;gt; [&lt;br /&gt;
        &amp;quot;name&amp;quot; =&amp;gt; &amp;quot;chooseSecond&amp;quot;,&lt;br /&gt;
        &amp;quot;descriptionmyturn&amp;quot; =&amp;gt; clienttranslate(&#039;${you} must make your second choice&#039;),&lt;br /&gt;
        &amp;quot;type&amp;quot; =&amp;gt; &amp;quot;private&amp;quot;,&lt;br /&gt;
        &amp;quot;args&amp;quot; =&amp;gt; &amp;quot;argChooseSecond&amp;quot;,&lt;br /&gt;
        &amp;quot;possibleactions&amp;quot; =&amp;gt; [&amp;quot;actFinish&amp;quot;, &amp;quot;actBack&amp;quot;],&lt;br /&gt;
        &amp;quot;transitions&amp;quot; =&amp;gt; [&lt;br /&gt;
          &#039;back&#039; =&amp;gt; 50,&lt;br /&gt;
        ]&lt;br /&gt;
      ],&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
When entering the master state it is usually useful to set some players as multiactive and initialize their private state:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    function stPlayerTurn() {&lt;br /&gt;
        $this-&amp;gt;gamestate-&amp;gt;setAllPlayersMultiactive();&lt;br /&gt;
        &lt;br /&gt;
        //this is needed when starting private parallel states; players will be transitioned to initialprivate state defined in master state&lt;br /&gt;
        $this-&amp;gt;gamestate-&amp;gt;initializePrivateStateForAllActivePlayers(); &lt;br /&gt;
&lt;br /&gt;
        // in some cases you can move immediately some or all players to different private states&lt;br /&gt;
        if ($someCondition) {&lt;br /&gt;
            //move all players to different state &lt;br /&gt;
            $this-&amp;gt;gamestate-&amp;gt;nextPrivateStateForAllActivePlayers(&amp;quot;chooseSecond&amp;quot;);&lt;br /&gt;
            return;&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        if ($other condition) {&lt;br /&gt;
            //move single player to different state&lt;br /&gt;
            $this-&amp;gt;gamestate-&amp;gt;nextPrivateState($specificPlayerId, &amp;quot;chooseSecond&amp;quot;);&lt;br /&gt;
            return;&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
When some action is done by a player, you can move them to the next private state:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    function actToSecond() {&lt;br /&gt;
        $this-&amp;gt;checkAction(&amp;quot;actToSecond&amp;quot;);  //the action must be defined in private state; actions defined in master state are not possible&lt;br /&gt;
        $this-&amp;gt;gamestate-&amp;gt;nextPrivateState($this-&amp;gt;getCurrentPlayerId(), &amp;quot;chooseSecond&amp;quot;); //moving current player to different state&lt;br /&gt;
    }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Please check the detailed API [[Main_game_logic:_yourgamename.game.php#Private_parallel_states|here]].&lt;br /&gt;
&lt;br /&gt;
=== Client States ===&lt;br /&gt;
Client state almost have nothing to do with server states, except they can simulate same experience without actually changing server states.&lt;br /&gt;
&lt;br /&gt;
See description here: https://en.doc.boardgamearena.com/BGA_Studio_Cookbook#Multi_Step_Interactions:_Select_Worker.2FPlace_Worker_-_Using_Client_States&lt;br /&gt;
&lt;br /&gt;
In many cases you can achive similar results by using client states vs private server states. The only caveat - when using client states during multiactive server state&lt;br /&gt;
other player will trigger state changes (multiactive player set) which will call onUpdateActionButtons. Some measures have to be taken to preserve client state in this case.&lt;br /&gt;
&lt;br /&gt;
=== Using Named Constants for States ===&lt;br /&gt;
&lt;br /&gt;
Using numeric constants is prone to errors. If you want you can declare state constants as PHP named constants. This way you can&lt;br /&gt;
use them in the states file and in game.php as well&lt;br /&gt;
&lt;br /&gt;
EXAMPLE:&lt;br /&gt;
&lt;br /&gt;
states.inc.php:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
// define contants for state ids&lt;br /&gt;
if (!defined(&#039;STATE_END_GAME&#039;)) { // ensure this block is only invoked once, since it is included multiple times&lt;br /&gt;
   define(&amp;quot;STATE_PLAYER_TURN&amp;quot;, 2);&lt;br /&gt;
   define(&amp;quot;STATE_GAME_TURN&amp;quot;, 3);&lt;br /&gt;
   define(&amp;quot;STATE_PLAYER_TURN_CUBES&amp;quot;, 4);&lt;br /&gt;
   define(&amp;quot;STATE_END_GAME&amp;quot;, 99);&lt;br /&gt;
}&lt;br /&gt;
 &lt;br /&gt;
$machinestates = array(&lt;br /&gt;
&lt;br /&gt;
   ...&lt;br /&gt;
&lt;br /&gt;
    STATE_PLAYER_TURN =&amp;gt; array(&lt;br /&gt;
    		&amp;quot;name&amp;quot; =&amp;gt; &amp;quot;playerTurn&amp;quot;,&lt;br /&gt;
    		&amp;quot;description&amp;quot; =&amp;gt; clienttranslate(&#039;${actplayer} must select an Action Space or Pass&#039;),&lt;br /&gt;
    		&amp;quot;descriptionmyturn&amp;quot; =&amp;gt; clienttranslate(&#039;${you} must select an Action Space or Pass&#039;),&lt;br /&gt;
    		&amp;quot;type&amp;quot; =&amp;gt; &amp;quot;activeplayer&amp;quot;,&lt;br /&gt;
                &amp;quot;args&amp;quot; =&amp;gt; &#039;arg_playerTurn&#039;,&lt;br /&gt;
    		&amp;quot;possibleactions&amp;quot; =&amp;gt; array( &amp;quot;actSelectWorkerAction&amp;quot;, &amp;quot;actPass&amp;quot; ),&lt;br /&gt;
    		&amp;quot;transitions&amp;quot; =&amp;gt; array( &lt;br /&gt;
    		        &amp;quot;loopback&amp;quot; =&amp;gt; STATE_PLAYER_TURN,&lt;br /&gt;
    		        &amp;quot;playCubes&amp;quot; =&amp;gt; STATE_PLAYER_TURN_CUBES,&lt;br /&gt;
    		        &amp;quot;pass&amp;quot; =&amp;gt; STATE_GAME_TURN )&lt;br /&gt;
    ),&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Example of multipleactiveplayer state ===&lt;br /&gt;
&lt;br /&gt;
This is an example of a multipleactiveplayer state:&lt;br /&gt;
&lt;br /&gt;
  2 =&amp;gt;  array (&lt;br /&gt;
    &#039;name&#039; =&amp;gt; &#039;playerTurnSetup&#039;,&lt;br /&gt;
    &#039;type&#039; =&amp;gt; &#039;multipleactiveplayer&#039;,&lt;br /&gt;
    &#039;description&#039; =&amp;gt; clienttranslate(&#039;Other players must choose one Objective&#039;),&lt;br /&gt;
    &#039;descriptionmyturn&#039; =&amp;gt; clienttranslate(&#039;${you} must choose one Objective card to keep&#039;),&lt;br /&gt;
    &#039;possibleactions&#039; =&amp;gt;     array (&#039;actPlayKeep&#039; ),&lt;br /&gt;
    &#039;transitions&#039; =&amp;gt;    array (       &#039;next&#039; =&amp;gt; 5, &#039;loopback&#039; =&amp;gt; 2, ),&lt;br /&gt;
    &#039;action&#039; =&amp;gt; &#039;st_MultiPlayerInit&#039;,&lt;br /&gt;
    &#039;args&#039; =&amp;gt; &#039;arg_playerTurnSetup&#039;,&lt;br /&gt;
  ),&lt;br /&gt;
&lt;br /&gt;
In game.php:&lt;br /&gt;
    // this will make all players multiactive just before entering the state&lt;br /&gt;
    function st_MultiPlayerInit() {&lt;br /&gt;
        $this-&amp;gt;gamestate-&amp;gt;setAllPlayersMultiactive();&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
Note: if you want exact this function its already defined in table class its called &#039;stMakeEveryoneActive&#039;&lt;br /&gt;
&lt;br /&gt;
When ending the player action, instead of a state transition, deactivate player.&lt;br /&gt;
&lt;br /&gt;
    function actPlayKeep($cardId) {&lt;br /&gt;
        $this-&amp;gt;checkAction(&#039;actPlayKeep&#039;);&lt;br /&gt;
        $player_id = $this-&amp;gt;getCurrentPlayerId(); // CURRENT!!! not active&lt;br /&gt;
        ... // some logic here&lt;br /&gt;
        $this-&amp;gt;gamestate-&amp;gt;setPlayerNonMultiactive($player_id, &#039;next&#039;); // deactivate player; if none left, transition to &#039;next&#039; state&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
=== Difference between Single active and Multi active states ===&lt;br /&gt;
In a classic &amp;quot;activePlayer&amp;quot; state:&lt;br /&gt;
&lt;br /&gt;
* You cannot change the active player DURING the state. This is to ensure that during 1 activePlayer state, only ONE player is active&lt;br /&gt;
* As a consequence, you must set the active player BEFORE entering the activePlayer state&lt;br /&gt;
* In such states on JS side onUpdateActionButtons is called before onEnteringState during game play (but after during reload, i.e. F5)&lt;br /&gt;
* Finally, during onEnteringState, on JS side, the active player is signaled as active and the information is reliable and usable.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
In a &amp;quot;multiplePlayer&amp;quot; state:&lt;br /&gt;
&lt;br /&gt;
* You can (and must) change the active players DURING the state&lt;br /&gt;
* During such a state, players can be activated/desactivated anytime during the state, giving you the maximum of possibilities.&lt;br /&gt;
* You shouldn&#039;t set active player before entering the state. But you can set it in &amp;quot;state initializer&amp;quot; php function (see example above st_MultiPlayerInit)&lt;br /&gt;
* Finally, during onEnteringState, on JS side, the active players are NOT active yet so you must use onUpdateActionButtons to perform the client side operation which depends on a player active/inactive status.&lt;br /&gt;
&lt;br /&gt;
Note: in some off cases other players can perform special actions even if they are not active, see example https://en.doc.boardgamearena.com/BGA_Studio_Cookbook#Out-of-turn_actions%3A_Un-pass. Do not abuse this technique!&lt;br /&gt;
&lt;br /&gt;
=== Designing states ===&lt;br /&gt;
&lt;br /&gt;
As a general rule you state machine should resemble &amp;quot;round/turn overview&amp;quot; from the game rule-book. Normally if book say its player turn and player can do multiple things during their turn it is still only&lt;br /&gt;
one player state (plus a game to switch player), not multiple states.&lt;br /&gt;
&lt;br /&gt;
In a classic game (i.e. chess), there is only active player at any time, so it is simple playerTurn/gameTurn sequence and you only need 2 states.&lt;br /&gt;
&lt;br /&gt;
[[File:Simplestates.png]]&lt;br /&gt;
&lt;br /&gt;
In complex euro game there can be multiple rounds, and each round have phases which can be distinctly unique, i.e. in first phase everybody draws card and discard (multi-player), then player have one turn each (single-active), then another is resolution of actions from players and some of them may become active again, then there is round upkeep/reset. This would require one multi-player state for phase 1, pair of states for phase2 (single-active + game), pair of states for phase3 and finally round-end/unkeep game state.&lt;br /&gt;
&lt;br /&gt;
For pair of active player/game states you can make player state first, which transitions to game state, or the other way around, you start with game state which transition to active player state, its loop in any case but depends on how you want to do &amp;quot;phase&amp;quot; initiazations.&lt;br /&gt;
&lt;br /&gt;
[[File:Eurogamestates.png]]&lt;br /&gt;
&lt;br /&gt;
=== Complete examples ===&lt;br /&gt;
&lt;br /&gt;
Example of simple game where player take turns&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
if ( !defined(&#039;STATE_END_GAME&#039;)) { // guard since this included multiple times&lt;br /&gt;
    define(&amp;quot;STATE_PLAYER_TURN&amp;quot;, 2);&lt;br /&gt;
    define(&amp;quot;STATE_GAME_TURN_NEXT_PLAYER&amp;quot;, 3);&lt;br /&gt;
    define(&amp;quot;STATE_PLAYER_GAME_END&amp;quot;, 4);&lt;br /&gt;
    define(&amp;quot;STATE_END_GAME&amp;quot;, 99);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
$machinestates = [    &lt;br /&gt;
        1 =&amp;gt; [ // The initial state. Please do not modify.&lt;br /&gt;
               &amp;quot;name&amp;quot; =&amp;gt; &amp;quot;gameSetup&amp;quot;,&lt;br /&gt;
               &amp;quot;description&amp;quot; =&amp;gt; &amp;quot;&amp;quot;,&lt;br /&gt;
               &amp;quot;type&amp;quot; =&amp;gt; &amp;quot;manager&amp;quot;,&lt;br /&gt;
               &amp;quot;action&amp;quot; =&amp;gt; &amp;quot;stGameSetup&amp;quot;,&lt;br /&gt;
               &amp;quot;transitions&amp;quot; =&amp;gt; [ &amp;quot;&amp;quot; =&amp;gt; STATE_PLAYER_TURN ] ],&lt;br /&gt;
        // Game states &lt;br /&gt;
        STATE_PLAYER_TURN =&amp;gt; [ // main active player state &lt;br /&gt;
                &amp;quot;name&amp;quot; =&amp;gt; &amp;quot;playerTurn&amp;quot;,&lt;br /&gt;
                &amp;quot;description&amp;quot; =&amp;gt; clienttranslate(&#039;${actplayer} must do something or pass&#039;),&lt;br /&gt;
                &amp;quot;descriptionmyturn&amp;quot; =&amp;gt; clienttranslate(&#039;${you} must do something or pass&#039;),&lt;br /&gt;
                &amp;quot;type&amp;quot; =&amp;gt; &amp;quot;activeplayer&amp;quot;,&lt;br /&gt;
                &amp;quot;args&amp;quot; =&amp;gt; &amp;quot;arg_playerTurn&amp;quot;,&lt;br /&gt;
                &amp;quot;possibleactions&amp;quot; =&amp;gt; [ &amp;quot;actDSomething&amp;quot;,&amp;quot;actPass&amp;quot; ],&lt;br /&gt;
                &amp;quot;transitions&amp;quot; =&amp;gt; [ &amp;quot;next&amp;quot; =&amp;gt; STATE_GAME_TURN_NEXT_PLAYER,&amp;quot;last&amp;quot; =&amp;gt; STATE_PLAYER_GAME_END ] // &lt;br /&gt;
        ],&lt;br /&gt;
        STATE_GAME_TURN_NEXT_PLAYER =&amp;gt; [ // next player state&lt;br /&gt;
                &amp;quot;name&amp;quot; =&amp;gt; &amp;quot;gameTurnNextPlayer&amp;quot;,&lt;br /&gt;
                &amp;quot;description&amp;quot; =&amp;gt; clienttranslate(&#039;Upkeep...&#039;),&lt;br /&gt;
                &amp;quot;type&amp;quot; =&amp;gt; &amp;quot;game&amp;quot;, //&lt;br /&gt;
                &amp;quot;action&amp;quot; =&amp;gt; &amp;quot;st_gameTurnNextPlayer&amp;quot;, //&lt;br /&gt;
                &amp;quot;updateGameProgression&amp;quot; =&amp;gt; true,&lt;br /&gt;
                &amp;quot;transitions&amp;quot; =&amp;gt; [ &amp;quot;next&amp;quot; =&amp;gt; STATE_PLAYER_TURN,&amp;quot;loopback&amp;quot; =&amp;gt; STATE_GAME_TURN_NEXT_PLAYER,&lt;br /&gt;
                        &amp;quot;last&amp;quot; =&amp;gt; STATE_PLAYER_GAME_END ], // TODO replace with STATE_END_GAME, its there to use undo/restore during dev&lt;br /&gt;
        ],&lt;br /&gt;
    &lt;br /&gt;
        STATE_PLAYER_GAME_END =&amp;gt; [ // active player state for debugging end of game&lt;br /&gt;
                &amp;quot;name&amp;quot; =&amp;gt; &amp;quot;playerGameEnd&amp;quot;,&lt;br /&gt;
                &amp;quot;description&amp;quot; =&amp;gt; clienttranslate(&#039;${actplayer} Game Over&#039;),&lt;br /&gt;
                &amp;quot;descriptionmyturn&amp;quot; =&amp;gt; clienttranslate(&#039;${you} Game Over&#039;),&lt;br /&gt;
                &amp;quot;type&amp;quot; =&amp;gt; &amp;quot;activeplayer&amp;quot;,&lt;br /&gt;
                &amp;quot;args&amp;quot; =&amp;gt; &amp;quot;arg_playerTurn&amp;quot;,&lt;br /&gt;
                &amp;quot;possibleactions&amp;quot; =&amp;gt; [&amp;quot;actEndGame&amp;quot;],&lt;br /&gt;
                &amp;quot;transitions&amp;quot; =&amp;gt; [&amp;quot;next&amp;quot; =&amp;gt; STATE_END_GAME,&amp;quot;loopback&amp;quot; =&amp;gt; STATE_PLAYER_GAME_END ] // &lt;br /&gt;
        ],&lt;br /&gt;
        // End of Game states &lt;br /&gt;
        // Final state.&lt;br /&gt;
        // Please do not modify (and do not overload action/args methods).&lt;br /&gt;
        STATE_END_GAME =&amp;gt; [&lt;br /&gt;
                &amp;quot;name&amp;quot; =&amp;gt; &amp;quot;gameEnd&amp;quot;,&lt;br /&gt;
                &amp;quot;description&amp;quot; =&amp;gt; clienttranslate(&amp;quot;End of game&amp;quot;),&amp;quot;type&amp;quot; =&amp;gt; &amp;quot;manager&amp;quot;,&lt;br /&gt;
                &amp;quot;action&amp;quot; =&amp;gt; &amp;quot;stGameEnd&amp;quot;,&lt;br /&gt;
                &amp;quot;args&amp;quot; =&amp;gt; &amp;quot;argGameEnd&amp;quot; ] &lt;br /&gt;
&lt;br /&gt;
];&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Category:Studio]]&lt;/div&gt;</summary>
		<author><name>Sguzzer Gunayer</name></author>
	</entry>
	<entry>
		<id>https://en.doc.boardgamearena.com/index.php?title=Your_game_state_machine:_states.inc.php&amp;diff=22599</id>
		<title>Your game state machine: states.inc.php</title>
		<link rel="alternate" type="text/html" href="https://en.doc.boardgamearena.com/index.php?title=Your_game_state_machine:_states.inc.php&amp;diff=22599"/>
		<updated>2024-09-16T18:28:52Z</updated>

		<summary type="html">&lt;p&gt;Sguzzer Gunayer: /* Designing states */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Studio_Framework_Navigation}}&lt;br /&gt;
&lt;br /&gt;
This file describes the state machine of your game (all the game states properties, and the transitions to get from one state to another).&lt;br /&gt;
&lt;br /&gt;
Important: to understand the game state machine, it&#039;s recommended that you read this presentation first:&lt;br /&gt;
&lt;br /&gt;
[http://www.slideshare.net/boardgamearena/bga-studio-focus-on-bga-game-state-machine Focus on BGA game state machine]&lt;br /&gt;
&lt;br /&gt;
== Overall structure ==&lt;br /&gt;
&lt;br /&gt;
The machine states are described by a PHP associative array.&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$machinestates = array(&lt;br /&gt;
&lt;br /&gt;
    // The initial state. Please do not modify.&lt;br /&gt;
    1 =&amp;gt; array(&lt;br /&gt;
        &amp;quot;name&amp;quot; =&amp;gt; &amp;quot;gameSetup&amp;quot;,&lt;br /&gt;
        &amp;quot;description&amp;quot; =&amp;gt; clienttranslate(&amp;quot;Game setup&amp;quot;),&lt;br /&gt;
        &amp;quot;type&amp;quot; =&amp;gt; &amp;quot;manager&amp;quot;,&lt;br /&gt;
        &amp;quot;action&amp;quot; =&amp;gt; &amp;quot;stGameSetup&amp;quot;,&lt;br /&gt;
        &amp;quot;transitions&amp;quot; =&amp;gt; array( &amp;quot;&amp;quot; =&amp;gt; 2 )&lt;br /&gt;
    ),&lt;br /&gt;
    &lt;br /&gt;
    // Note: ID=2 =&amp;gt; your first state&lt;br /&gt;
&lt;br /&gt;
    2 =&amp;gt; array(&lt;br /&gt;
    		&amp;quot;name&amp;quot; =&amp;gt; &amp;quot;playerTurn&amp;quot;,&lt;br /&gt;
    		&amp;quot;description&amp;quot; =&amp;gt; clienttranslate(&#039;${actplayer} must play a card or pass&#039;),&lt;br /&gt;
    		&amp;quot;descriptionmyturn&amp;quot; =&amp;gt; clienttranslate(&#039;${you} must play a card or pass&#039;),&lt;br /&gt;
    		&amp;quot;type&amp;quot; =&amp;gt; &amp;quot;activeplayer&amp;quot;,&lt;br /&gt;
    		&amp;quot;possibleactions&amp;quot; =&amp;gt; array( &amp;quot;actPlayCard&amp;quot;, &amp;quot;actPass&amp;quot; ),&lt;br /&gt;
    		&amp;quot;transitions&amp;quot; =&amp;gt; array( &amp;quot;playCard&amp;quot; =&amp;gt; 2, &amp;quot;pass&amp;quot; =&amp;gt; 2 )&lt;br /&gt;
    ),&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Syntax ==&lt;br /&gt;
&lt;br /&gt;
=== id ===&lt;br /&gt;
&lt;br /&gt;
The keys determine game state IDs (in the example above: 1 and 2).&lt;br /&gt;
&lt;br /&gt;
IDs must be positive integers.&lt;br /&gt;
&lt;br /&gt;
ID=1 is reserved for the first game state and should not be used (and you must not modify it).&lt;br /&gt;
&lt;br /&gt;
ID=99 is reserved for the last game state (end of the game) (and you must not modify it).&lt;br /&gt;
&lt;br /&gt;
Note: you may use any ID, even an ID greater than 100. But you cannot use 1 or 99.&lt;br /&gt;
&lt;br /&gt;
Note²: You must not use the same ID twice.&lt;br /&gt;
&lt;br /&gt;
Note³: When a game is in prod and you change the ID of a state, all active games (including many turn based) will behave unpredictably.&lt;br /&gt;
&lt;br /&gt;
=== name ===&lt;br /&gt;
&lt;br /&gt;
(&#039;&#039;&#039;Mandatory&#039;&#039;&#039;)&lt;br /&gt;
&lt;br /&gt;
The name of a game state is used to identify it in your game logic.&lt;br /&gt;
&lt;br /&gt;
Several game states can share the same name; however, this is not recommended.&lt;br /&gt;
&lt;br /&gt;
Warning! Do not put spaces in the name. This could cause unexpected problems in some cases.&lt;br /&gt;
&lt;br /&gt;
PHP example:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
// Get current game state&lt;br /&gt;
$state = $this-&amp;gt;gamestate-&amp;gt;state();&lt;br /&gt;
if( $state[&#039;name&#039;] == &#039;myGameState&#039; )&lt;br /&gt;
{&lt;br /&gt;
...&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
JS example:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        onEnteringState: function( stateName, args )&lt;br /&gt;
        {&lt;br /&gt;
            console.log( &#039;Entering state: &#039;+stateName );&lt;br /&gt;
            &lt;br /&gt;
            switch( stateName )&lt;br /&gt;
            case &#039;myGameState&#039;:&lt;br /&gt;
            &lt;br /&gt;
                // Do some stuff at the beginning at this game state&lt;br /&gt;
                ....&lt;br /&gt;
                &lt;br /&gt;
                break;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== type ===&lt;br /&gt;
&lt;br /&gt;
(&#039;&#039;&#039;Mandatory&#039;&#039;&#039;)&lt;br /&gt;
&lt;br /&gt;
You can use 3 types of game states:&lt;br /&gt;
* activeplayer (1 player is active and must play.)&lt;br /&gt;
* multipleactiveplayer (1..N players can be active and must play.)&lt;br /&gt;
* private (during multiactive states players can independently move to different private parallel states. See more details [[#Private_parallel_states|here]].&lt;br /&gt;
* game (No player is active. This is a transitional state to do something automatic specified by the game rules.)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note:&#039;&#039;&#039; Make sure you don&#039;t mistype the value of this attribute. If you do (e.g. &#039;multiactiveplayer&#039; instead of &#039;multipleactiveplayer&#039;), things won&#039;t work, and you might have a hard time figuring out why.&lt;br /&gt;
&lt;br /&gt;
=== description ===&lt;br /&gt;
&lt;br /&gt;
(&#039;&#039;&#039;Mandatory&#039;&#039;&#039;)&lt;br /&gt;
&lt;br /&gt;
The description is the string that is displayed in the main action bar (top of the screen) when the state is active.&lt;br /&gt;
&lt;br /&gt;
When a string is specified as a description, you must use &amp;quot;clienttranslate&amp;quot; in order for the string to be translated on the client side:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 		&amp;quot;description&amp;quot; =&amp;gt; clienttranslate(&#039;${actplayer} must play a card or pass&#039;),&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In the description string, you can use ${actplayer} to refer to the active player.&lt;br /&gt;
&lt;br /&gt;
You can also use custom arguments in your description. These custom arguments correspond to values returned by your &amp;quot;args&amp;quot; PHP method (see below &amp;quot;args&amp;quot; field).&lt;br /&gt;
&lt;br /&gt;
Example of custom field:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In states.inc.php:&lt;br /&gt;
        &amp;quot;description&amp;quot; =&amp;gt; clienttranslate(&#039;${actplayer} must choose ${nbr} identical energies&#039;),&lt;br /&gt;
        &amp;quot;args&amp;quot; =&amp;gt; &amp;quot;argMyArgumentMethod&amp;quot;&lt;br /&gt;
&lt;br /&gt;
In mygame.game.php:&lt;br /&gt;
    function argMyArgumentMethod()&lt;br /&gt;
    {&lt;br /&gt;
        return array(&lt;br /&gt;
            &#039;nbr&#039; =&amp;gt; 2  // In this case ${nbr} in the description will be replaced by &amp;quot;2&amp;quot;&lt;br /&gt;
        );    &lt;br /&gt;
    }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note: You may specify an empty string (&amp;quot;&amp;quot;) here if it never happens that the game remains in this state (i.e., if this state immediately jumps to another state when activated).&lt;br /&gt;
&lt;br /&gt;
Note²: Usually, you specify a string for &amp;quot;activeplayer&amp;quot; and &amp;quot;multipleactiveplayer&amp;quot; game states, and you specify an empty string for &amp;quot;game&amp;quot; game states. BUT, if you are using synchronous notifications, the client can remain on a &amp;quot;game&amp;quot; type game state for a few seconds, and in this case it may be useful to display a description in the status bar while in this state.&lt;br /&gt;
&lt;br /&gt;
=== descriptionmyturn ===&lt;br /&gt;
&lt;br /&gt;
(&#039;&#039;&#039;Mandatory&#039;&#039;&#039; when the state type is &amp;quot;activeplayer&amp;quot; or &amp;quot;multipleactiveplayer&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
&amp;quot;descriptionmyturn&amp;quot; has exactly the same role and properties as &amp;quot;description&amp;quot;, except that this value is displayed to the current active player - or to all active players in case of a multipleactiveplayer game state.&lt;br /&gt;
&lt;br /&gt;
In general, we have this situation:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        &amp;quot;description&amp;quot; =&amp;gt; clienttranslate(&#039;${actplayer} can take some actions&#039;),&lt;br /&gt;
        &amp;quot;descriptionmyturn&amp;quot; =&amp;gt; clienttranslate(&#039;${you} can take some actions&#039;),&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note: you can use ${you} in descriptionmyturn so the description will display &amp;quot;You&amp;quot; instead of the name of the player.&lt;br /&gt;
&lt;br /&gt;
Note 2: you can use ${otherplayer} to refer to some other player if you want this to be shown in player&#039;s color, but you must provide otherplayer_id as argument (along with otherplayer) to specify this player&#039;s id in this case or game won&#039;t load.&lt;br /&gt;
&lt;br /&gt;
I.e.&lt;br /&gt;
&lt;br /&gt;
 &amp;quot;descriptionmyturn&amp;quot; =&amp;gt; clienttranslate(&#039;${you} can follow action of ${otherplayer}&#039;),&lt;br /&gt;
&lt;br /&gt;
And this will have to be state arguments for this&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    function arg_playerTurnFollow(){&lt;br /&gt;
        return [&#039;otherplayer&#039;=&amp;gt; $this-&amp;gt;getLeaderPlayerName(),&lt;br /&gt;
                &#039;otherplayer_id&#039;=&amp;gt; $this-&amp;gt;getLeaderPlayerId()&lt;br /&gt;
        ];&lt;br /&gt;
    }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== action ===&lt;br /&gt;
&lt;br /&gt;
(&#039;&#039;&#039;Mandatory&#039;&#039;&#039; when the state type is &amp;quot;game.&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
&amp;quot;action&amp;quot; specifies a PHP method to call when entering this game state.&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
In states.inc.php:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    28 =&amp;gt; array(&lt;br /&gt;
        &amp;quot;name&amp;quot; =&amp;gt; &amp;quot;gameTurnNextPlayer&amp;quot;,&lt;br /&gt;
        &amp;quot;description&amp;quot; =&amp;gt; clienttranslate(&#039;Updating some stuff...&#039;),&lt;br /&gt;
        &amp;quot;type&amp;quot; =&amp;gt; &amp;quot;game&amp;quot;,&lt;br /&gt;
        &amp;quot;action&amp;quot; =&amp;gt; &amp;quot;st_gameTurnNextPlayer&amp;quot;,&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
In mygame.game.php:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    function st_gameTurnNextPlayer() {&lt;br /&gt;
        $player_id = $this-&amp;gt;getActivePlayerId();&lt;br /&gt;
        $next_player_id = $this-&amp;gt;getPlayerAfter($player_id);&lt;br /&gt;
        $this-&amp;gt;giveExtraTime($next_player_id);&lt;br /&gt;
        $this-&amp;gt;incStat(1, &#039;turns_number&#039;, $next_player_id);&lt;br /&gt;
        $this-&amp;gt;incStat(1, &#039;turns_number&#039;);&lt;br /&gt;
        $this-&amp;gt;gamestate-&amp;gt;changeActivePlayer($next_player_id);&lt;br /&gt;
        $this-&amp;gt;gamestate-&amp;gt;nextState(&#039;next&#039;);&lt;br /&gt;
    }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Usually, for a &amp;quot;game&amp;quot; state type, the action method is used to perform automatic functions specified by the rules (for example: check victory conditions, deal cards for a new round, go to the next player, etc.) and then jump to another game state.&lt;br /&gt;
&lt;br /&gt;
Note: a BGA convention specifies that PHP methods called with &amp;quot;action&amp;quot; are prefixed by &amp;quot;st&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
Note: this field CAN be used for player states to set something up; e.g., for multiplayer states, it can make all players active.&lt;br /&gt;
&lt;br /&gt;
Example for action in player state:&lt;br /&gt;
in states.inc.php:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    2 =&amp;gt; array(&lt;br /&gt;
    		&amp;quot;name&amp;quot; =&amp;gt; &amp;quot;playerTurnPlace&amp;quot;,&lt;br /&gt;
    		&amp;quot;description&amp;quot; =&amp;gt; clienttranslate(&#039;Other player must place ships&#039;),&lt;br /&gt;
    		&amp;quot;descriptionmyturn&amp;quot; =&amp;gt; clienttranslate(&#039;${you} must place ships (click on YOUR SHIPS board to place)&#039;),&lt;br /&gt;
    		&amp;quot;type&amp;quot; =&amp;gt; &amp;quot;multipleactiveplayer&amp;quot;,&lt;br /&gt;
            &#039;action&#039; =&amp;gt; &#039;st_MultiPlayerInit&#039;,&lt;br /&gt;
            &#039;args&#039; =&amp;gt; &#039;arg_playerTurnPlace&#039;,&lt;br /&gt;
    		&amp;quot;possibleactions&amp;quot; =&amp;gt; array( &amp;quot;playPlace&amp;quot; ),&lt;br /&gt;
            &amp;quot;transitions&amp;quot; =&amp;gt; array( &amp;quot;next&amp;quot; =&amp;gt; 4, &amp;quot;last&amp;quot; =&amp;gt; 99)&lt;br /&gt;
    ),&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
in mygame.game.php:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    function st_MultiPlayerInit() {&lt;br /&gt;
        $this-&amp;gt;gamestate-&amp;gt;setAllPlayersMultiactive();&lt;br /&gt;
    }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&#039;&#039;&#039;Warning&#039;&#039;&#039;: Prevent to do anything on stGameEnd() and argGameEnd() in mygame.game.php. It may cause game never end and always stuck in &amp;quot;Recording game results + computing statistics in progress...&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
=== transitions ===&lt;br /&gt;
&lt;br /&gt;
(&#039;&#039;&#039;Mandatory&#039;&#039;&#039;)&lt;br /&gt;
&lt;br /&gt;
With &amp;quot;transitions&amp;quot; you specify which game state(s) you can jump to from a given game state.&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    25 =&amp;gt; array(&lt;br /&gt;
        &amp;quot;name&amp;quot; =&amp;gt; &amp;quot;myGameState&amp;quot;,&lt;br /&gt;
        &amp;quot;transitions&amp;quot; =&amp;gt; array( &amp;quot;nextPlayer&amp;quot; =&amp;gt; 27, &amp;quot;endRound&amp;quot; =&amp;gt; 39 ),&lt;br /&gt;
        ....&lt;br /&gt;
    }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In the example above, if &amp;quot;myGameState&amp;quot; is the current active game state, I can jump to the game state with ID 27 or the game state with ID 39.&lt;br /&gt;
&lt;br /&gt;
Example to jump to ID 27:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
In mygame.game.php:&lt;br /&gt;
    $this-&amp;gt;gamestate-&amp;gt;nextState( &amp;quot;nextPlayer&amp;quot; );&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Important: &amp;quot;nextPlayer&amp;quot; is the name of the transition, and NOT the name of the target game state. Multiple transitions can lead to the same game state.&lt;br /&gt;
&lt;br /&gt;
Note: If there is only 1 transition, you may give it an empty name.&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
In states.inc.php:&lt;br /&gt;
    &amp;quot;transitions&amp;quot; =&amp;gt; array( &amp;quot;&amp;quot; =&amp;gt; 27 ),&lt;br /&gt;
&lt;br /&gt;
In mygame.game.php:&lt;br /&gt;
    $this-&amp;gt;gamestate-&amp;gt;nextState(  );     // We don&#039;t need to specify a transition as there is only one here&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== possibleactions ===&lt;br /&gt;
&lt;br /&gt;
(&#039;&#039;&#039;Mandatory&#039;&#039;&#039; when the game state is &amp;quot;activeplayer&amp;quot; or &amp;quot;multipleactiveplayer&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
&amp;quot;possibleactions&amp;quot; defines the actions possible by the players in this game state, and ensures they cannot perform actions that are not allowed in this state.&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
In states.game.php:&lt;br /&gt;
       	&amp;quot;possibleactions&amp;quot; =&amp;gt; array( &amp;quot;actPlayCard&amp;quot;, &amp;quot;actPass&amp;quot; ),&lt;br /&gt;
&lt;br /&gt;
In mygame.game.php:&lt;br /&gt;
        function actPlayCard( ...)&lt;br /&gt;
        {&lt;br /&gt;
             $this-&amp;gt;checkAction( &amp;quot;actPlayCard&amp;quot; );    // Will fail if &amp;quot;actPlayCard&amp;quot; is not specified in &amp;quot;possibleactions&amp;quot; in the current game state.&lt;br /&gt;
&lt;br /&gt;
            ....&lt;br /&gt;
&lt;br /&gt;
In mygame.js:&lt;br /&gt;
        playCard: function( ... )&lt;br /&gt;
        {&lt;br /&gt;
            if( this.checkAction( &amp;quot;actPlayCard&amp;quot; ) ) // Will fail if &amp;quot;actPlayCard&amp;quot; is not specified in &amp;quot;possibleactions&amp;quot; in the current game state.&lt;br /&gt;
            {  return ;   }&lt;br /&gt;
// or &lt;br /&gt;
        playCard: function( ... )&lt;br /&gt;
        {&lt;br /&gt;
            if( this.bgaPerformAction( &amp;quot;actPlayCard&amp;quot;, { id} ) ) // Will not trigger if &amp;quot;actPlayCard&amp;quot; is not specified in &amp;quot;possibleactions&amp;quot; in the current game state.&lt;br /&gt;
            {  return ;   }&lt;br /&gt;
&lt;br /&gt;
            ....&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== args ===&lt;br /&gt;
&lt;br /&gt;
(optional)&lt;br /&gt;
&lt;br /&gt;
Sometimes it happens that you need some information on the client side (i.e., for your game interface) only for a specific game state.&lt;br /&gt;
&lt;br /&gt;
Example 1: in &#039;&#039;Reversi&#039;&#039;, the list of possible moves during the playerTurn state.&lt;br /&gt;
&lt;br /&gt;
Example 2: in &#039;&#039;Caylus&#039;&#039;, the number of remaining king&#039;s favors to choose in the state where the player is choosing a favor.&lt;br /&gt;
&lt;br /&gt;
Example 3: in &#039;&#039;Can&#039;t Stop&#039;&#039;, the list of possible die combinations to be displayed to the active player so that he can choose from among them.&lt;br /&gt;
&lt;br /&gt;
In such a situation, you can specify a method name as the « args » argument for your game state. This method must retrieve some piece of information about the game (example: for &#039;&#039;Reversi&#039;&#039;, the list of possible moves) and return it.&lt;br /&gt;
&lt;br /&gt;
Thus, this data can be transmitted to the clients and used by the clients to display it. It should always be an associative array.&lt;br /&gt;
&lt;br /&gt;
Let&#039;s see a complete example using args with &#039;&#039;Reversi&#039;&#039; game:&lt;br /&gt;
&lt;br /&gt;
In states.inc.php, we specify an &#039;&#039;&#039;args&#039;&#039;&#039; argument for gamestate &#039;&#039;&#039;playerTurn&#039;&#039;&#039;:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    10 =&amp;gt; array(&lt;br /&gt;
        &amp;quot;name&amp;quot; =&amp;gt; &amp;quot;playerTurn&amp;quot;,&lt;br /&gt;
		&amp;quot;description&amp;quot; =&amp;gt; clienttranslate(&#039;${actplayer} must play a disc&#039;),&lt;br /&gt;
		&amp;quot;descriptionmyturn&amp;quot; =&amp;gt; clienttranslate(&#039;${you} must play a disc&#039;),&lt;br /&gt;
        &amp;quot;type&amp;quot; =&amp;gt; &amp;quot;activeplayer&amp;quot;,&lt;br /&gt;
        &amp;quot;args&amp;quot; =&amp;gt; &amp;quot;argPlayerTurn&amp;quot;,    // &amp;lt;==== HERE&lt;br /&gt;
        &amp;quot;possibleactions&amp;quot; =&amp;gt; array( &#039;actPlayDisc&#039; ),&lt;br /&gt;
        &amp;quot;transitions&amp;quot; =&amp;gt; array( &amp;quot;playDisc&amp;quot; =&amp;gt; 11, &amp;quot;zombiePass&amp;quot; =&amp;gt; 11 )&lt;br /&gt;
    ),&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
It corresponds to a &#039;&#039;&#039;argPlayerTurn&#039;&#039;&#039; method in our PHP code (reversi.game.php):&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    function argPlayerTurn() {&lt;br /&gt;
        return array(&lt;br /&gt;
            &#039;possibleMoves&#039; =&amp;gt; $this-&amp;gt;getPossibleMoves()&lt;br /&gt;
        );&lt;br /&gt;
    }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Then, when we enter into the &#039;&#039;&#039;playerTurn&#039;&#039;&#039; game state on the client side, we can highlight the possible moves on the board using information returned by &#039;&#039;&#039;argPlayerTurn&#039;&#039;&#039;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        onEnteringState: function( stateName, args )  {&lt;br /&gt;
           console.log( &#039;Entering state: &#039;+stateName );&lt;br /&gt;
            &lt;br /&gt;
            switch( stateName )  {&lt;br /&gt;
            case &#039;playerTurn&#039;:&lt;br /&gt;
                this.updatePossibleMoves( args.args.possibleMoves );&lt;br /&gt;
                break;&lt;br /&gt;
            }&lt;br /&gt;
        },&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Naming and API conventions ====&lt;br /&gt;
&lt;br /&gt;
As a BGA convention, PHP methods called with &amp;quot;args&amp;quot; are prefixed by &amp;quot;arg&amp;quot; followed by state name (example: &#039;&#039;&#039;argPlayerTurn&#039;&#039;&#039;).&lt;br /&gt;
&lt;br /&gt;
All &amp;quot;arg*&amp;quot; methods are put into corresponding section of .game.php file commented as&lt;br /&gt;
   //////////// Game state arguments&lt;br /&gt;
&lt;br /&gt;
Arg method MUST return array. Return integer or string will result in some undebuggable exceptions.&lt;br /&gt;
&lt;br /&gt;
Arg method MUST be defined in php if it is declared in state description, if you don&#039;t need it comment it out from the states.inc.php file (the &#039;&#039;&#039;args&#039;&#039;&#039; parameter). If you not sure if you need it or not you can keep it returning empty array until you figure it out.&lt;br /&gt;
&lt;br /&gt;
    function argPlayerTurn() {&lt;br /&gt;
        return array(); // must be an array&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Warning&#039;&#039;&#039;: the &amp;quot;args&amp;quot; method is ALWAYS called before the &amp;quot;action&amp;quot; method so don&#039;t expect data modifications by the &amp;quot;action&amp;quot; method to be available in the &amp;quot;args&amp;quot; method!&lt;br /&gt;
Also don&#039;t modify database in this method!&lt;br /&gt;
&lt;br /&gt;
You should NOT be calling getCurrentPlayer() in the context of this function, since state transitions are broadcasted to all player independent of who initiated it. Instead you should send information on per player basis (Note: if this is private info see section below). &lt;br /&gt;
&lt;br /&gt;
If you using this function in multi-player state, you should not call getActivePlayer() either, you should send per player info:&lt;br /&gt;
&lt;br /&gt;
    function arg_playerTurn() {&lt;br /&gt;
        $res = array ();&lt;br /&gt;
        $players = $this-&amp;gt;loadPlayersBasicInfos();&lt;br /&gt;
        foreach ( $players as $player_id =&amp;gt; $player_info ) {&lt;br /&gt;
            $color = $player_info [&#039;player_color&#039;];&lt;br /&gt;
            $res [$player_id] = array(&amp;quot;color&amp;quot;=&amp;gt;$color);&lt;br /&gt;
        }&lt;br /&gt;
        return $res;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
Note: you never need to send player color like this, this is just an example.&lt;br /&gt;
&lt;br /&gt;
Note 2: you CAN call methods that return all active players if multi-player states if its relevant.&lt;br /&gt;
&lt;br /&gt;
==== Other usages ====&lt;br /&gt;
&lt;br /&gt;
You can use values returned by your &amp;quot;args&amp;quot; method to have some custom values in your &amp;quot;description&amp;quot;/&amp;quot;descriptionmyturn&amp;quot;, i.e. in states.inc.php:&lt;br /&gt;
&lt;br /&gt;
   &amp;quot;descriptionmyturn&amp;quot; =&amp;gt; clienttranslate(&#039;${you} must play ${color} disc&#039;),&lt;br /&gt;
&lt;br /&gt;
So arg function will be something like:&lt;br /&gt;
&lt;br /&gt;
  function argPlayerTurn() {&lt;br /&gt;
        return array(&#039;color&#039;=&amp;gt;$this-&amp;gt;getActivePlayerColor()); &lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
You can use args also in &#039;&#039;&#039;onUpdateActionButtons&#039;&#039;&#039; function on js side, however two important notes:&lt;br /&gt;
* it is just &#039;&#039;&#039;args&#039;&#039;&#039; (not args.args like in &#039;&#039;&#039;onEnteringState&#039;&#039;&#039;)&lt;br /&gt;
* it is args of the current state, which may not be state you think it will be! This method is called during change of active player, which happens in some weird place especially during &amp;quot;multipleactiveplayer&amp;quot; states. If you pulling your hair thinking why its &amp;quot;undefined&amp;quot; on js side - check the current state.&lt;br /&gt;
&lt;br /&gt;
==== Private info in args ====&lt;br /&gt;
&lt;br /&gt;
By default, all data provided through this method are PUBLIC TO ALL PLAYERS. Please do not send any private data with this method, as a cheater could see it even it is not used explicitly by the game interface logic.&lt;br /&gt;
&lt;br /&gt;
However, it is possible to specify that some data should be sent to specific players only.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note: You cannot use Example 1 and Example 2 together. If you have to send private args to multiple players, use Example 2.&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Example 1: send information to active player(s) only:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    function argPlayerTurn()  {&lt;br /&gt;
        return array(&lt;br /&gt;
            &#039;_private&#039; =&amp;gt; array(          // Using &amp;quot;_private&amp;quot; keyword, all data inside this array will be made private&lt;br /&gt;
                &#039;active&#039; =&amp;gt; array(       // Using &amp;quot;active&amp;quot; keyword inside &amp;quot;_private&amp;quot;, you select active player(s)&lt;br /&gt;
                    &#039;somePrivateData&#039; =&amp;gt; $this-&amp;gt;getSomePrivateData()   // will be send only to active player(s)&lt;br /&gt;
                )&lt;br /&gt;
            ),&lt;br /&gt;
            &#039;possibleMoves&#039; =&amp;gt; $this-&amp;gt;getPossibleMoves()          // will be sent to all players&lt;br /&gt;
        );&lt;br /&gt;
    }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Inside the js file, these variables will be available through `args.args._private`. (e.g. `args.args._private.somePrivateData` -- it is not `args._private.active.somePrivateData` nor is it `args.somePrivateData`)&lt;br /&gt;
&lt;br /&gt;
Example 2: send information to a specific player (&amp;lt;specific_player_id&amp;gt;) only:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    function argPlayerTurn()  {&lt;br /&gt;
        $specific_player_id = ...; // calculate some-how&lt;br /&gt;
        return array(&lt;br /&gt;
            &#039;_private&#039; =&amp;gt; array(   // all data inside this array will be private&lt;br /&gt;
                $specific_player_id =&amp;gt; array(   // will be sent only to that player   &lt;br /&gt;
                    &#039;somePrivateData&#039; =&amp;gt; $this-&amp;gt;getSomePrivateData()   &lt;br /&gt;
                )&lt;br /&gt;
            ),&lt;br /&gt;
&lt;br /&gt;
            &#039;possibleMoves&#039; =&amp;gt; $this-&amp;gt;getPossibleMoves()   // will be sent to all players&lt;br /&gt;
        );&lt;br /&gt;
    }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
IMPORTANT: in certain situations (i.e. &amp;quot;multipleactiveplayer&amp;quot; game state) these &amp;quot;private data&amp;quot; features can have a significant impact on performance. Please do not use if not needed.&lt;br /&gt;
&lt;br /&gt;
It is also possible to use these private args in the &amp;quot;description&amp;quot; messages, like &amp;quot;${you} have to play ${_private.count} cards&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
==== Flag to indicate a skipped state ====&lt;br /&gt;
&lt;br /&gt;
By default, The front-end will be notified of entering/leaving all states. To speed up the front-end chaining of automatically passed states, you can disable this state change notification, so the front-end doesn&#039;t trigger the preparation steps for a state that you know will be automatically skipped, and it may reduce sent args. In this case, define the &#039;&#039;&#039;_no_notify&#039;&#039;&#039; flag to true in the state args.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
function argPlayerTurn()  {&lt;br /&gt;
  $playableCardsIds = ...;&lt;br /&gt;
  return [&lt;br /&gt;
    &#039;playableCardsIds&#039; =&amp;gt; $playableCardsIds,&lt;br /&gt;
    &#039;_no_notify&#039; =&amp;gt; count(playableCardsIds) === 0,&lt;br /&gt;
  ];&lt;br /&gt;
}&lt;br /&gt;
function stPlayerTurn()  {&lt;br /&gt;
  $args = $this-&amp;gt;argPlayerTurn();&lt;br /&gt;
  if ($args[&#039;_no_notify&#039;]) {&lt;br /&gt;
    $this-&amp;gt;gamestate-&amp;gt;nextState(&#039;next&#039;);&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In this example, it might avoid a blinking message &amp;quot;You must play a card&amp;quot; (quickly replaced by the next state message) when you cannot play a card and the game automatically skips this state.&lt;br /&gt;
&lt;br /&gt;
IMPORTANT: if you use _no_notify, you must handle a redirection to another state on the st function!&lt;br /&gt;
&lt;br /&gt;
Note that if you play synced notifications during a skipped state, it will display the notifications on the previous state. For example, for an endScore state width description &amp;quot;Computing end score...&amp;quot; sending a lot of animated notifications, you should NOT use this flag so the description is visible.&lt;br /&gt;
&lt;br /&gt;
==== Translations in args ====&lt;br /&gt;
You can do the same as in notification by adding i18n parameter, i.e&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
function argPlayerTurn()  {&lt;br /&gt;
 return [&lt;br /&gt;
      &#039;i18n&#039; =&amp;gt; [&#039;terrainName&#039; ],&lt;br /&gt;
      &#039;terrainName&#039; =&amp;gt; ($this-&amp;gt;token_types[$terrain][&#039;name&#039;]), // this should be defined in material.inc.php and with clienttranslate &lt;br /&gt;
      &#039;terrain&#039; =&amp;gt; $terrain,&lt;br /&gt;
   ];&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Than you can do something like this in state:&lt;br /&gt;
  &amp;quot;descriptionmyturn&amp;quot; =&amp;gt; clienttranslate(&#039;${you} must place a house on ${terrainName}&#039;),&lt;br /&gt;
&lt;br /&gt;
See more in [[Translations]]&lt;br /&gt;
&lt;br /&gt;
=== updateGameProgression ===&lt;br /&gt;
&lt;br /&gt;
(optional)&lt;br /&gt;
&lt;br /&gt;
If you specify &amp;quot;updateGameProgression =&amp;gt; true&amp;quot; in a game state, your &amp;quot;getGameProgression&amp;quot; PHP method will be called at the beginning of this game state - and thus the game progression of the game will be updated.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;At least one&#039;&#039; of your game states (any one) must specify &amp;quot;updateGameProgression=&amp;gt;true&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
=== initialprivate ===&lt;br /&gt;
&lt;br /&gt;
(optional)&lt;br /&gt;
&lt;br /&gt;
This parameter will enable private parallel states in a multiplayer state. Parameter should be set to first private parallel state a player will be transitioned to.&lt;br /&gt;
See more details about Private parallel states [[#Private_parallel_states|here]].&lt;br /&gt;
&lt;br /&gt;
== Implementation Notes ==&lt;br /&gt;
&lt;br /&gt;
=== Private parallel states ===&lt;br /&gt;
&lt;br /&gt;
Private parallel states are useful when multiple players are active and their turn is very complex. In that case it is possible with parallel states for each player to be in a independent state. &lt;br /&gt;
&lt;br /&gt;
Lets say that players need to do three complex action one after another in multiactive state. With parallel states each player can independently be in a different state (i.e. one player still need to decide about first action while some players are deciding their second action and the fastest player is already on their third action. Normally this can be handled with two simple, but limited, approaches:&lt;br /&gt;
&lt;br /&gt;
* Moving all players to different states together - this is limiting for faster players as they need to wait other players for each separate action. The more problematic thing is that it would be hard to implement an undo feature when one player wants to change their previous action. In that case all players should be moved back to previous state which will interrupt their flow.&lt;br /&gt;
* Using client states, by changing the state in which the player is in javascript - the problem with this approach is that players will lose their progress on browser refresh (F5). Furthermore the validation logic of specific actions should be implemented on both server side and client side and we cannot have specific args for each different action, but they should be calculated only at the beginning of the first action and possibly calculated on client side after each action, which again duplicates logic on client and server.&lt;br /&gt;
&lt;br /&gt;
With private parallel states, each specific action can be implemented as a parallel state. Parallel states are defined with the type &#039;private&#039; and players are moved to those private states during one master multiactive state. Lets look at the example:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    10 =&amp;gt; [&lt;br /&gt;
        &amp;quot;name&amp;quot; =&amp;gt; &amp;quot;playerTurn&amp;quot;,&lt;br /&gt;
        &amp;quot;description&amp;quot; =&amp;gt; clienttranslate(&#039;Waiting for other players to end their turn.&#039;),&lt;br /&gt;
        &amp;quot;descriptionmyturn&amp;quot; =&amp;gt; clienttranslate(&#039;${you} must do your turn&#039;), // Won&#039;t be displayed anyway since each private state has its own description&lt;br /&gt;
        &amp;quot;type&amp;quot; =&amp;gt; &amp;quot;multipleactiveplayer&amp;quot;,&lt;br /&gt;
        &amp;quot;initialprivate&amp;quot; =&amp;gt; 50, // This makes this state a master multiactive state and enables private states, this is also a first private state&lt;br /&gt;
        &amp;quot;action&amp;quot; =&amp;gt; &amp;quot;stPlayerTurn&amp;quot;,&lt;br /&gt;
        &amp;quot;args&amp;quot; =&amp;gt; &amp;quot;argPlayerTurn&amp;quot;,&lt;br /&gt;
        &amp;quot;possibleactions&amp;quot; =&amp;gt; [&amp;quot;actChangeMind&amp;quot;], //this action is possible if player is not in any private state which usually happens when they are inactive&lt;br /&gt;
        &amp;quot;transitions&amp;quot; =&amp;gt; [&amp;quot;playersDecide&amp;quot; =&amp;gt; 11] // this is normal next transition which will happen after all players finish their turns &lt;br /&gt;
    ],&lt;br /&gt;
&lt;br /&gt;
    50 =&amp;gt; [&lt;br /&gt;
        &amp;quot;name&amp;quot; =&amp;gt; &amp;quot;chooseFirst&amp;quot;,&lt;br /&gt;
        &amp;quot;descriptionmyturn&amp;quot; =&amp;gt; clienttranslate(&#039;${you} must make your first choice&#039;), // just this parameter is needed. description is not needed as no player is inactive in this state&lt;br /&gt;
        &amp;quot;type&amp;quot; =&amp;gt; &amp;quot;private&amp;quot;, // this state is reachable only as a private state&lt;br /&gt;
        &amp;quot;args&amp;quot; =&amp;gt; &amp;quot;argChooseFirst&amp;quot;, //this method will be called with playerId as a parametar and is used to calculate arguments for this action for specific player&lt;br /&gt;
        &amp;quot;action&amp;quot; =&amp;gt; &amp;quot;stChooseFirst&amp;quot;, // this method will be called with playerId as a parameter and can be used to make some changes when player enters this private state&lt;br /&gt;
        &amp;quot;possibleactions&amp;quot; =&amp;gt; [&amp;quot;actToSecond&amp;quot;],&lt;br /&gt;
        &amp;quot;transitions&amp;quot; =&amp;gt; [&lt;br /&gt;
          &#039;chooseSecond&#039; =&amp;gt; 51, // transition to another private state&lt;br /&gt;
        ]&lt;br /&gt;
      ],&lt;br /&gt;
   &lt;br /&gt;
    51 =&amp;gt; [&lt;br /&gt;
        &amp;quot;name&amp;quot; =&amp;gt; &amp;quot;chooseSecond&amp;quot;,&lt;br /&gt;
        &amp;quot;descriptionmyturn&amp;quot; =&amp;gt; clienttranslate(&#039;${you} must make your second choice&#039;),&lt;br /&gt;
        &amp;quot;type&amp;quot; =&amp;gt; &amp;quot;private&amp;quot;,&lt;br /&gt;
        &amp;quot;args&amp;quot; =&amp;gt; &amp;quot;argChooseSecond&amp;quot;,&lt;br /&gt;
        &amp;quot;possibleactions&amp;quot; =&amp;gt; [&amp;quot;actFinish&amp;quot;, &amp;quot;actBack&amp;quot;],&lt;br /&gt;
        &amp;quot;transitions&amp;quot; =&amp;gt; [&lt;br /&gt;
          &#039;back&#039; =&amp;gt; 50,&lt;br /&gt;
        ]&lt;br /&gt;
      ],&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
When entering the master state it is usually useful to set some players as multiactive and initialize their private state:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    function stPlayerTurn() {&lt;br /&gt;
        $this-&amp;gt;gamestate-&amp;gt;setAllPlayersMultiactive();&lt;br /&gt;
        &lt;br /&gt;
        //this is needed when starting private parallel states; players will be transitioned to initialprivate state defined in master state&lt;br /&gt;
        $this-&amp;gt;gamestate-&amp;gt;initializePrivateStateForAllActivePlayers(); &lt;br /&gt;
&lt;br /&gt;
        // in some cases you can move immediately some or all players to different private states&lt;br /&gt;
        if ($someCondition) {&lt;br /&gt;
            //move all players to different state &lt;br /&gt;
            $this-&amp;gt;gamestate-&amp;gt;nextPrivateStateForAllActivePlayers(&amp;quot;chooseSecond&amp;quot;);&lt;br /&gt;
            return;&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        if ($other condition) {&lt;br /&gt;
            //move single player to different state&lt;br /&gt;
            $this-&amp;gt;gamestate-&amp;gt;nextPrivateState($specificPlayerId, &amp;quot;chooseSecond&amp;quot;);&lt;br /&gt;
            return;&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
When some action is done by a player, you can move them to the next private state:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    function actToSecond() {&lt;br /&gt;
        $this-&amp;gt;checkAction(&amp;quot;actToSecond&amp;quot;);  //the action must be defined in private state; actions defined in master state are not possible&lt;br /&gt;
        $this-&amp;gt;gamestate-&amp;gt;nextPrivateState($this-&amp;gt;getCurrentPlayerId(), &amp;quot;chooseSecond&amp;quot;); //moving current player to different state&lt;br /&gt;
    }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Please check the detailed API [[Main_game_logic:_yourgamename.game.php#Private_parallel_states|here]].&lt;br /&gt;
&lt;br /&gt;
=== Client States ===&lt;br /&gt;
Client state almost have nothing to do with server states, except they can simulate same experience without actually changing server states.&lt;br /&gt;
&lt;br /&gt;
See description here: https://en.doc.boardgamearena.com/BGA_Studio_Cookbook#Multi_Step_Interactions:_Select_Worker.2FPlace_Worker_-_Using_Client_States&lt;br /&gt;
&lt;br /&gt;
In many cases you can achive similar results by using client states vs private server states. The only caveat - when using client states during multiactive server state&lt;br /&gt;
other player will trigger state changes (multiactive player set) which will call onUpdateActionButtons. Some measures have to be taken to preserve client state in this case.&lt;br /&gt;
&lt;br /&gt;
=== Using Named Constants for States ===&lt;br /&gt;
&lt;br /&gt;
Using numeric constants is prone to errors. If you want you can declare state constants as PHP named constants. This way you can&lt;br /&gt;
use them in the states file and in game.php as well&lt;br /&gt;
&lt;br /&gt;
EXAMPLE:&lt;br /&gt;
&lt;br /&gt;
states.inc.php:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
// define contants for state ids&lt;br /&gt;
if (!defined(&#039;STATE_END_GAME&#039;)) { // ensure this block is only invoked once, since it is included multiple times&lt;br /&gt;
   define(&amp;quot;STATE_PLAYER_TURN&amp;quot;, 2);&lt;br /&gt;
   define(&amp;quot;STATE_GAME_TURN&amp;quot;, 3);&lt;br /&gt;
   define(&amp;quot;STATE_PLAYER_TURN_CUBES&amp;quot;, 4);&lt;br /&gt;
   define(&amp;quot;STATE_END_GAME&amp;quot;, 99);&lt;br /&gt;
}&lt;br /&gt;
 &lt;br /&gt;
$machinestates = array(&lt;br /&gt;
&lt;br /&gt;
   ...&lt;br /&gt;
&lt;br /&gt;
    STATE_PLAYER_TURN =&amp;gt; array(&lt;br /&gt;
    		&amp;quot;name&amp;quot; =&amp;gt; &amp;quot;playerTurn&amp;quot;,&lt;br /&gt;
    		&amp;quot;description&amp;quot; =&amp;gt; clienttranslate(&#039;${actplayer} must select an Action Space or Pass&#039;),&lt;br /&gt;
    		&amp;quot;descriptionmyturn&amp;quot; =&amp;gt; clienttranslate(&#039;${you} must select an Action Space or Pass&#039;),&lt;br /&gt;
    		&amp;quot;type&amp;quot; =&amp;gt; &amp;quot;activeplayer&amp;quot;,&lt;br /&gt;
                &amp;quot;args&amp;quot; =&amp;gt; &#039;arg_playerTurn&#039;,&lt;br /&gt;
    		&amp;quot;possibleactions&amp;quot; =&amp;gt; array( &amp;quot;actSelectWorkerAction&amp;quot;, &amp;quot;actPass&amp;quot; ),&lt;br /&gt;
    		&amp;quot;transitions&amp;quot; =&amp;gt; array( &lt;br /&gt;
    		        &amp;quot;loopback&amp;quot; =&amp;gt; STATE_PLAYER_TURN,&lt;br /&gt;
    		        &amp;quot;playCubes&amp;quot; =&amp;gt; STATE_PLAYER_TURN_CUBES,&lt;br /&gt;
    		        &amp;quot;pass&amp;quot; =&amp;gt; STATE_GAME_TURN )&lt;br /&gt;
    ),&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Example of multipleactiveplayer state ===&lt;br /&gt;
&lt;br /&gt;
This is an example of a multipleactiveplayer state:&lt;br /&gt;
&lt;br /&gt;
  2 =&amp;gt;  array (&lt;br /&gt;
    &#039;name&#039; =&amp;gt; &#039;playerTurnSetup&#039;,&lt;br /&gt;
    &#039;type&#039; =&amp;gt; &#039;multipleactiveplayer&#039;,&lt;br /&gt;
    &#039;description&#039; =&amp;gt; clienttranslate(&#039;Other players must choose one Objective&#039;),&lt;br /&gt;
    &#039;descriptionmyturn&#039; =&amp;gt; clienttranslate(&#039;${you} must choose one Objective card to keep&#039;),&lt;br /&gt;
    &#039;possibleactions&#039; =&amp;gt;     array (&#039;actPlayKeep&#039; ),&lt;br /&gt;
    &#039;transitions&#039; =&amp;gt;    array (       &#039;next&#039; =&amp;gt; 5, &#039;loopback&#039; =&amp;gt; 2, ),&lt;br /&gt;
    &#039;action&#039; =&amp;gt; &#039;st_MultiPlayerInit&#039;,&lt;br /&gt;
    &#039;args&#039; =&amp;gt; &#039;arg_playerTurnSetup&#039;,&lt;br /&gt;
  ),&lt;br /&gt;
&lt;br /&gt;
In game.php:&lt;br /&gt;
    // this will make all players multiactive just before entering the state&lt;br /&gt;
    function st_MultiPlayerInit() {&lt;br /&gt;
        $this-&amp;gt;gamestate-&amp;gt;setAllPlayersMultiactive();&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
Note: if you want exact this function its already defined in table class its called &#039;stMakeEveryoneActive&#039;&lt;br /&gt;
&lt;br /&gt;
When ending the player action, instead of a state transition, deactivate player.&lt;br /&gt;
&lt;br /&gt;
    function actPlayKeep($cardId) {&lt;br /&gt;
        $this-&amp;gt;checkAction(&#039;actPlayKeep&#039;);&lt;br /&gt;
        $player_id = $this-&amp;gt;getCurrentPlayerId(); // CURRENT!!! not active&lt;br /&gt;
        ... // some logic here&lt;br /&gt;
        $this-&amp;gt;gamestate-&amp;gt;setPlayerNonMultiactive($player_id, &#039;next&#039;); // deactivate player; if none left, transition to &#039;next&#039; state&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
=== Difference between Single active and Multi active states ===&lt;br /&gt;
In a classic &amp;quot;activePlayer&amp;quot; state:&lt;br /&gt;
&lt;br /&gt;
* You cannot change the active player DURING the state. This is to ensure that during 1 activePlayer state, only ONE player is active&lt;br /&gt;
* As a consequence, you must set the active player BEFORE entering the activePlayer state&lt;br /&gt;
* In such states on JS side onUpdateActionButtons is called before onEnteringState during game play (but after during reload, i.e. F5)&lt;br /&gt;
* Finally, during onEnteringState, on JS side, the active player is signaled as active and the information is reliable and usable.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
In a &amp;quot;multiplePlayer&amp;quot; state:&lt;br /&gt;
&lt;br /&gt;
* You can (and must) change the active players DURING the state&lt;br /&gt;
* During such a state, players can be activated/desactivated anytime during the state, giving you the maximum of possibilities.&lt;br /&gt;
* You shouldn&#039;t set active player before entering the state. But you can set it in &amp;quot;state initializer&amp;quot; php function (see example above st_MultiPlayerInit)&lt;br /&gt;
* Finally, during onEnteringState, on JS side, the active players are NOT active yet so you must use onUpdateActionButtons to perform the client side operation which depends on a player active/inactive status.&lt;br /&gt;
&lt;br /&gt;
Note: in some off cases other players can perform special actions even if they are not active, see example https://en.doc.boardgamearena.com/BGA_Studio_Cookbook#Out-of-turn_actions%3A_Un-pass. Do not abuse this technique!&lt;br /&gt;
&lt;br /&gt;
=== Designing states ===&lt;br /&gt;
&lt;br /&gt;
As a general rule you state machine should resemble &amp;quot;round/turn overview&amp;quot; from the game rule-book. Normally if book say its player turn and player can do multiple things during their turn it is still only&lt;br /&gt;
one player state (plus a game to switch player), not multiple states.&lt;br /&gt;
&lt;br /&gt;
In a classic game (i.e. chess), there is only active player at any time, so it is simple playerTurn/gameTurn sequence and you only need 2 states.&lt;br /&gt;
&lt;br /&gt;
[[File:Simplestates.png]]&lt;br /&gt;
&lt;br /&gt;
In complex euro game there can be multiple rounds, and each round have phases which can be distinctly unique, i.e. in first phase everybody draws card and discard (multi-player), then player have one turn each (single-active), then another is resolution of actions from players and some of them may become active again, then there is round upkeep/reset. This would require one multi-player state for phase 1, pair of states for phase2 (singel-active + game), pair of states for phase3 and finally round-end/unkeep game state.&lt;br /&gt;
&lt;br /&gt;
For pair of active player/game states you can make player state first, which transitions to game state, or the other way around, you start with game state which transition to active player state, its loop in any case but depends on how you want to do &amp;quot;phase&amp;quot; initiazations.&lt;br /&gt;
&lt;br /&gt;
[[File:Eurogamestates.png]]&lt;br /&gt;
&lt;br /&gt;
=== Complete examples ===&lt;br /&gt;
&lt;br /&gt;
Example of simple game where player take turns&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
if ( !defined(&#039;STATE_END_GAME&#039;)) { // guard since this included multiple times&lt;br /&gt;
    define(&amp;quot;STATE_PLAYER_TURN&amp;quot;, 2);&lt;br /&gt;
    define(&amp;quot;STATE_GAME_TURN_NEXT_PLAYER&amp;quot;, 3);&lt;br /&gt;
    define(&amp;quot;STATE_PLAYER_GAME_END&amp;quot;, 4);&lt;br /&gt;
    define(&amp;quot;STATE_END_GAME&amp;quot;, 99);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
$machinestates = [    &lt;br /&gt;
        1 =&amp;gt; [ // The initial state. Please do not modify.&lt;br /&gt;
               &amp;quot;name&amp;quot; =&amp;gt; &amp;quot;gameSetup&amp;quot;,&lt;br /&gt;
               &amp;quot;description&amp;quot; =&amp;gt; &amp;quot;&amp;quot;,&lt;br /&gt;
               &amp;quot;type&amp;quot; =&amp;gt; &amp;quot;manager&amp;quot;,&lt;br /&gt;
               &amp;quot;action&amp;quot; =&amp;gt; &amp;quot;stGameSetup&amp;quot;,&lt;br /&gt;
               &amp;quot;transitions&amp;quot; =&amp;gt; [ &amp;quot;&amp;quot; =&amp;gt; STATE_PLAYER_TURN ] ],&lt;br /&gt;
        // Game states &lt;br /&gt;
        STATE_PLAYER_TURN =&amp;gt; [ // main active player state &lt;br /&gt;
                &amp;quot;name&amp;quot; =&amp;gt; &amp;quot;playerTurn&amp;quot;,&lt;br /&gt;
                &amp;quot;description&amp;quot; =&amp;gt; clienttranslate(&#039;${actplayer} must do something or pass&#039;),&lt;br /&gt;
                &amp;quot;descriptionmyturn&amp;quot; =&amp;gt; clienttranslate(&#039;${you} must do something or pass&#039;),&lt;br /&gt;
                &amp;quot;type&amp;quot; =&amp;gt; &amp;quot;activeplayer&amp;quot;,&lt;br /&gt;
                &amp;quot;args&amp;quot; =&amp;gt; &amp;quot;arg_playerTurn&amp;quot;,&lt;br /&gt;
                &amp;quot;possibleactions&amp;quot; =&amp;gt; [ &amp;quot;actDSomething&amp;quot;,&amp;quot;actPass&amp;quot; ],&lt;br /&gt;
                &amp;quot;transitions&amp;quot; =&amp;gt; [ &amp;quot;next&amp;quot; =&amp;gt; STATE_GAME_TURN_NEXT_PLAYER,&amp;quot;last&amp;quot; =&amp;gt; STATE_PLAYER_GAME_END ] // &lt;br /&gt;
        ],&lt;br /&gt;
        STATE_GAME_TURN_NEXT_PLAYER =&amp;gt; [ // next player state&lt;br /&gt;
                &amp;quot;name&amp;quot; =&amp;gt; &amp;quot;gameTurnNextPlayer&amp;quot;,&lt;br /&gt;
                &amp;quot;description&amp;quot; =&amp;gt; clienttranslate(&#039;Upkeep...&#039;),&lt;br /&gt;
                &amp;quot;type&amp;quot; =&amp;gt; &amp;quot;game&amp;quot;, //&lt;br /&gt;
                &amp;quot;action&amp;quot; =&amp;gt; &amp;quot;st_gameTurnNextPlayer&amp;quot;, //&lt;br /&gt;
                &amp;quot;updateGameProgression&amp;quot; =&amp;gt; true,&lt;br /&gt;
                &amp;quot;transitions&amp;quot; =&amp;gt; [ &amp;quot;next&amp;quot; =&amp;gt; STATE_PLAYER_TURN,&amp;quot;loopback&amp;quot; =&amp;gt; STATE_GAME_TURN_NEXT_PLAYER,&lt;br /&gt;
                        &amp;quot;last&amp;quot; =&amp;gt; STATE_PLAYER_GAME_END ], // TODO replace with STATE_END_GAME, its there to use undo/restore during dev&lt;br /&gt;
        ],&lt;br /&gt;
    &lt;br /&gt;
        STATE_PLAYER_GAME_END =&amp;gt; [ // active player state for debugging end of game&lt;br /&gt;
                &amp;quot;name&amp;quot; =&amp;gt; &amp;quot;playerGameEnd&amp;quot;,&lt;br /&gt;
                &amp;quot;description&amp;quot; =&amp;gt; clienttranslate(&#039;${actplayer} Game Over&#039;),&lt;br /&gt;
                &amp;quot;descriptionmyturn&amp;quot; =&amp;gt; clienttranslate(&#039;${you} Game Over&#039;),&lt;br /&gt;
                &amp;quot;type&amp;quot; =&amp;gt; &amp;quot;activeplayer&amp;quot;,&lt;br /&gt;
                &amp;quot;args&amp;quot; =&amp;gt; &amp;quot;arg_playerTurn&amp;quot;,&lt;br /&gt;
                &amp;quot;possibleactions&amp;quot; =&amp;gt; [&amp;quot;actEndGame&amp;quot;],&lt;br /&gt;
                &amp;quot;transitions&amp;quot; =&amp;gt; [&amp;quot;next&amp;quot; =&amp;gt; STATE_END_GAME,&amp;quot;loopback&amp;quot; =&amp;gt; STATE_PLAYER_GAME_END ] // &lt;br /&gt;
        ],&lt;br /&gt;
        // End of Game states &lt;br /&gt;
        // Final state.&lt;br /&gt;
        // Please do not modify (and do not overload action/args methods).&lt;br /&gt;
        STATE_END_GAME =&amp;gt; [&lt;br /&gt;
                &amp;quot;name&amp;quot; =&amp;gt; &amp;quot;gameEnd&amp;quot;,&lt;br /&gt;
                &amp;quot;description&amp;quot; =&amp;gt; clienttranslate(&amp;quot;End of game&amp;quot;),&amp;quot;type&amp;quot; =&amp;gt; &amp;quot;manager&amp;quot;,&lt;br /&gt;
                &amp;quot;action&amp;quot; =&amp;gt; &amp;quot;stGameEnd&amp;quot;,&lt;br /&gt;
                &amp;quot;args&amp;quot; =&amp;gt; &amp;quot;argGameEnd&amp;quot; ] &lt;br /&gt;
&lt;br /&gt;
];&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Category:Studio]]&lt;/div&gt;</summary>
		<author><name>Sguzzer Gunayer</name></author>
	</entry>
	<entry>
		<id>https://en.doc.boardgamearena.com/index.php?title=Your_game_state_machine:_states.inc.php&amp;diff=22598</id>
		<title>Your game state machine: states.inc.php</title>
		<link rel="alternate" type="text/html" href="https://en.doc.boardgamearena.com/index.php?title=Your_game_state_machine:_states.inc.php&amp;diff=22598"/>
		<updated>2024-09-16T18:14:24Z</updated>

		<summary type="html">&lt;p&gt;Sguzzer Gunayer: /* Client States */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Studio_Framework_Navigation}}&lt;br /&gt;
&lt;br /&gt;
This file describes the state machine of your game (all the game states properties, and the transitions to get from one state to another).&lt;br /&gt;
&lt;br /&gt;
Important: to understand the game state machine, it&#039;s recommended that you read this presentation first:&lt;br /&gt;
&lt;br /&gt;
[http://www.slideshare.net/boardgamearena/bga-studio-focus-on-bga-game-state-machine Focus on BGA game state machine]&lt;br /&gt;
&lt;br /&gt;
== Overall structure ==&lt;br /&gt;
&lt;br /&gt;
The machine states are described by a PHP associative array.&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$machinestates = array(&lt;br /&gt;
&lt;br /&gt;
    // The initial state. Please do not modify.&lt;br /&gt;
    1 =&amp;gt; array(&lt;br /&gt;
        &amp;quot;name&amp;quot; =&amp;gt; &amp;quot;gameSetup&amp;quot;,&lt;br /&gt;
        &amp;quot;description&amp;quot; =&amp;gt; clienttranslate(&amp;quot;Game setup&amp;quot;),&lt;br /&gt;
        &amp;quot;type&amp;quot; =&amp;gt; &amp;quot;manager&amp;quot;,&lt;br /&gt;
        &amp;quot;action&amp;quot; =&amp;gt; &amp;quot;stGameSetup&amp;quot;,&lt;br /&gt;
        &amp;quot;transitions&amp;quot; =&amp;gt; array( &amp;quot;&amp;quot; =&amp;gt; 2 )&lt;br /&gt;
    ),&lt;br /&gt;
    &lt;br /&gt;
    // Note: ID=2 =&amp;gt; your first state&lt;br /&gt;
&lt;br /&gt;
    2 =&amp;gt; array(&lt;br /&gt;
    		&amp;quot;name&amp;quot; =&amp;gt; &amp;quot;playerTurn&amp;quot;,&lt;br /&gt;
    		&amp;quot;description&amp;quot; =&amp;gt; clienttranslate(&#039;${actplayer} must play a card or pass&#039;),&lt;br /&gt;
    		&amp;quot;descriptionmyturn&amp;quot; =&amp;gt; clienttranslate(&#039;${you} must play a card or pass&#039;),&lt;br /&gt;
    		&amp;quot;type&amp;quot; =&amp;gt; &amp;quot;activeplayer&amp;quot;,&lt;br /&gt;
    		&amp;quot;possibleactions&amp;quot; =&amp;gt; array( &amp;quot;actPlayCard&amp;quot;, &amp;quot;actPass&amp;quot; ),&lt;br /&gt;
    		&amp;quot;transitions&amp;quot; =&amp;gt; array( &amp;quot;playCard&amp;quot; =&amp;gt; 2, &amp;quot;pass&amp;quot; =&amp;gt; 2 )&lt;br /&gt;
    ),&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Syntax ==&lt;br /&gt;
&lt;br /&gt;
=== id ===&lt;br /&gt;
&lt;br /&gt;
The keys determine game state IDs (in the example above: 1 and 2).&lt;br /&gt;
&lt;br /&gt;
IDs must be positive integers.&lt;br /&gt;
&lt;br /&gt;
ID=1 is reserved for the first game state and should not be used (and you must not modify it).&lt;br /&gt;
&lt;br /&gt;
ID=99 is reserved for the last game state (end of the game) (and you must not modify it).&lt;br /&gt;
&lt;br /&gt;
Note: you may use any ID, even an ID greater than 100. But you cannot use 1 or 99.&lt;br /&gt;
&lt;br /&gt;
Note²: You must not use the same ID twice.&lt;br /&gt;
&lt;br /&gt;
Note³: When a game is in prod and you change the ID of a state, all active games (including many turn based) will behave unpredictably.&lt;br /&gt;
&lt;br /&gt;
=== name ===&lt;br /&gt;
&lt;br /&gt;
(&#039;&#039;&#039;Mandatory&#039;&#039;&#039;)&lt;br /&gt;
&lt;br /&gt;
The name of a game state is used to identify it in your game logic.&lt;br /&gt;
&lt;br /&gt;
Several game states can share the same name; however, this is not recommended.&lt;br /&gt;
&lt;br /&gt;
Warning! Do not put spaces in the name. This could cause unexpected problems in some cases.&lt;br /&gt;
&lt;br /&gt;
PHP example:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
// Get current game state&lt;br /&gt;
$state = $this-&amp;gt;gamestate-&amp;gt;state();&lt;br /&gt;
if( $state[&#039;name&#039;] == &#039;myGameState&#039; )&lt;br /&gt;
{&lt;br /&gt;
...&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
JS example:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        onEnteringState: function( stateName, args )&lt;br /&gt;
        {&lt;br /&gt;
            console.log( &#039;Entering state: &#039;+stateName );&lt;br /&gt;
            &lt;br /&gt;
            switch( stateName )&lt;br /&gt;
            case &#039;myGameState&#039;:&lt;br /&gt;
            &lt;br /&gt;
                // Do some stuff at the beginning at this game state&lt;br /&gt;
                ....&lt;br /&gt;
                &lt;br /&gt;
                break;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== type ===&lt;br /&gt;
&lt;br /&gt;
(&#039;&#039;&#039;Mandatory&#039;&#039;&#039;)&lt;br /&gt;
&lt;br /&gt;
You can use 3 types of game states:&lt;br /&gt;
* activeplayer (1 player is active and must play.)&lt;br /&gt;
* multipleactiveplayer (1..N players can be active and must play.)&lt;br /&gt;
* private (during multiactive states players can independently move to different private parallel states. See more details [[#Private_parallel_states|here]].&lt;br /&gt;
* game (No player is active. This is a transitional state to do something automatic specified by the game rules.)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note:&#039;&#039;&#039; Make sure you don&#039;t mistype the value of this attribute. If you do (e.g. &#039;multiactiveplayer&#039; instead of &#039;multipleactiveplayer&#039;), things won&#039;t work, and you might have a hard time figuring out why.&lt;br /&gt;
&lt;br /&gt;
=== description ===&lt;br /&gt;
&lt;br /&gt;
(&#039;&#039;&#039;Mandatory&#039;&#039;&#039;)&lt;br /&gt;
&lt;br /&gt;
The description is the string that is displayed in the main action bar (top of the screen) when the state is active.&lt;br /&gt;
&lt;br /&gt;
When a string is specified as a description, you must use &amp;quot;clienttranslate&amp;quot; in order for the string to be translated on the client side:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 		&amp;quot;description&amp;quot; =&amp;gt; clienttranslate(&#039;${actplayer} must play a card or pass&#039;),&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In the description string, you can use ${actplayer} to refer to the active player.&lt;br /&gt;
&lt;br /&gt;
You can also use custom arguments in your description. These custom arguments correspond to values returned by your &amp;quot;args&amp;quot; PHP method (see below &amp;quot;args&amp;quot; field).&lt;br /&gt;
&lt;br /&gt;
Example of custom field:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In states.inc.php:&lt;br /&gt;
        &amp;quot;description&amp;quot; =&amp;gt; clienttranslate(&#039;${actplayer} must choose ${nbr} identical energies&#039;),&lt;br /&gt;
        &amp;quot;args&amp;quot; =&amp;gt; &amp;quot;argMyArgumentMethod&amp;quot;&lt;br /&gt;
&lt;br /&gt;
In mygame.game.php:&lt;br /&gt;
    function argMyArgumentMethod()&lt;br /&gt;
    {&lt;br /&gt;
        return array(&lt;br /&gt;
            &#039;nbr&#039; =&amp;gt; 2  // In this case ${nbr} in the description will be replaced by &amp;quot;2&amp;quot;&lt;br /&gt;
        );    &lt;br /&gt;
    }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note: You may specify an empty string (&amp;quot;&amp;quot;) here if it never happens that the game remains in this state (i.e., if this state immediately jumps to another state when activated).&lt;br /&gt;
&lt;br /&gt;
Note²: Usually, you specify a string for &amp;quot;activeplayer&amp;quot; and &amp;quot;multipleactiveplayer&amp;quot; game states, and you specify an empty string for &amp;quot;game&amp;quot; game states. BUT, if you are using synchronous notifications, the client can remain on a &amp;quot;game&amp;quot; type game state for a few seconds, and in this case it may be useful to display a description in the status bar while in this state.&lt;br /&gt;
&lt;br /&gt;
=== descriptionmyturn ===&lt;br /&gt;
&lt;br /&gt;
(&#039;&#039;&#039;Mandatory&#039;&#039;&#039; when the state type is &amp;quot;activeplayer&amp;quot; or &amp;quot;multipleactiveplayer&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
&amp;quot;descriptionmyturn&amp;quot; has exactly the same role and properties as &amp;quot;description&amp;quot;, except that this value is displayed to the current active player - or to all active players in case of a multipleactiveplayer game state.&lt;br /&gt;
&lt;br /&gt;
In general, we have this situation:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        &amp;quot;description&amp;quot; =&amp;gt; clienttranslate(&#039;${actplayer} can take some actions&#039;),&lt;br /&gt;
        &amp;quot;descriptionmyturn&amp;quot; =&amp;gt; clienttranslate(&#039;${you} can take some actions&#039;),&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note: you can use ${you} in descriptionmyturn so the description will display &amp;quot;You&amp;quot; instead of the name of the player.&lt;br /&gt;
&lt;br /&gt;
Note 2: you can use ${otherplayer} to refer to some other player if you want this to be shown in player&#039;s color, but you must provide otherplayer_id as argument (along with otherplayer) to specify this player&#039;s id in this case or game won&#039;t load.&lt;br /&gt;
&lt;br /&gt;
I.e.&lt;br /&gt;
&lt;br /&gt;
 &amp;quot;descriptionmyturn&amp;quot; =&amp;gt; clienttranslate(&#039;${you} can follow action of ${otherplayer}&#039;),&lt;br /&gt;
&lt;br /&gt;
And this will have to be state arguments for this&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    function arg_playerTurnFollow(){&lt;br /&gt;
        return [&#039;otherplayer&#039;=&amp;gt; $this-&amp;gt;getLeaderPlayerName(),&lt;br /&gt;
                &#039;otherplayer_id&#039;=&amp;gt; $this-&amp;gt;getLeaderPlayerId()&lt;br /&gt;
        ];&lt;br /&gt;
    }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== action ===&lt;br /&gt;
&lt;br /&gt;
(&#039;&#039;&#039;Mandatory&#039;&#039;&#039; when the state type is &amp;quot;game.&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
&amp;quot;action&amp;quot; specifies a PHP method to call when entering this game state.&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
In states.inc.php:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    28 =&amp;gt; array(&lt;br /&gt;
        &amp;quot;name&amp;quot; =&amp;gt; &amp;quot;gameTurnNextPlayer&amp;quot;,&lt;br /&gt;
        &amp;quot;description&amp;quot; =&amp;gt; clienttranslate(&#039;Updating some stuff...&#039;),&lt;br /&gt;
        &amp;quot;type&amp;quot; =&amp;gt; &amp;quot;game&amp;quot;,&lt;br /&gt;
        &amp;quot;action&amp;quot; =&amp;gt; &amp;quot;st_gameTurnNextPlayer&amp;quot;,&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
In mygame.game.php:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    function st_gameTurnNextPlayer() {&lt;br /&gt;
        $player_id = $this-&amp;gt;getActivePlayerId();&lt;br /&gt;
        $next_player_id = $this-&amp;gt;getPlayerAfter($player_id);&lt;br /&gt;
        $this-&amp;gt;giveExtraTime($next_player_id);&lt;br /&gt;
        $this-&amp;gt;incStat(1, &#039;turns_number&#039;, $next_player_id);&lt;br /&gt;
        $this-&amp;gt;incStat(1, &#039;turns_number&#039;);&lt;br /&gt;
        $this-&amp;gt;gamestate-&amp;gt;changeActivePlayer($next_player_id);&lt;br /&gt;
        $this-&amp;gt;gamestate-&amp;gt;nextState(&#039;next&#039;);&lt;br /&gt;
    }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Usually, for a &amp;quot;game&amp;quot; state type, the action method is used to perform automatic functions specified by the rules (for example: check victory conditions, deal cards for a new round, go to the next player, etc.) and then jump to another game state.&lt;br /&gt;
&lt;br /&gt;
Note: a BGA convention specifies that PHP methods called with &amp;quot;action&amp;quot; are prefixed by &amp;quot;st&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
Note: this field CAN be used for player states to set something up; e.g., for multiplayer states, it can make all players active.&lt;br /&gt;
&lt;br /&gt;
Example for action in player state:&lt;br /&gt;
in states.inc.php:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    2 =&amp;gt; array(&lt;br /&gt;
    		&amp;quot;name&amp;quot; =&amp;gt; &amp;quot;playerTurnPlace&amp;quot;,&lt;br /&gt;
    		&amp;quot;description&amp;quot; =&amp;gt; clienttranslate(&#039;Other player must place ships&#039;),&lt;br /&gt;
    		&amp;quot;descriptionmyturn&amp;quot; =&amp;gt; clienttranslate(&#039;${you} must place ships (click on YOUR SHIPS board to place)&#039;),&lt;br /&gt;
    		&amp;quot;type&amp;quot; =&amp;gt; &amp;quot;multipleactiveplayer&amp;quot;,&lt;br /&gt;
            &#039;action&#039; =&amp;gt; &#039;st_MultiPlayerInit&#039;,&lt;br /&gt;
            &#039;args&#039; =&amp;gt; &#039;arg_playerTurnPlace&#039;,&lt;br /&gt;
    		&amp;quot;possibleactions&amp;quot; =&amp;gt; array( &amp;quot;playPlace&amp;quot; ),&lt;br /&gt;
            &amp;quot;transitions&amp;quot; =&amp;gt; array( &amp;quot;next&amp;quot; =&amp;gt; 4, &amp;quot;last&amp;quot; =&amp;gt; 99)&lt;br /&gt;
    ),&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
in mygame.game.php:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    function st_MultiPlayerInit() {&lt;br /&gt;
        $this-&amp;gt;gamestate-&amp;gt;setAllPlayersMultiactive();&lt;br /&gt;
    }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&#039;&#039;&#039;Warning&#039;&#039;&#039;: Prevent to do anything on stGameEnd() and argGameEnd() in mygame.game.php. It may cause game never end and always stuck in &amp;quot;Recording game results + computing statistics in progress...&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
=== transitions ===&lt;br /&gt;
&lt;br /&gt;
(&#039;&#039;&#039;Mandatory&#039;&#039;&#039;)&lt;br /&gt;
&lt;br /&gt;
With &amp;quot;transitions&amp;quot; you specify which game state(s) you can jump to from a given game state.&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    25 =&amp;gt; array(&lt;br /&gt;
        &amp;quot;name&amp;quot; =&amp;gt; &amp;quot;myGameState&amp;quot;,&lt;br /&gt;
        &amp;quot;transitions&amp;quot; =&amp;gt; array( &amp;quot;nextPlayer&amp;quot; =&amp;gt; 27, &amp;quot;endRound&amp;quot; =&amp;gt; 39 ),&lt;br /&gt;
        ....&lt;br /&gt;
    }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In the example above, if &amp;quot;myGameState&amp;quot; is the current active game state, I can jump to the game state with ID 27 or the game state with ID 39.&lt;br /&gt;
&lt;br /&gt;
Example to jump to ID 27:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
In mygame.game.php:&lt;br /&gt;
    $this-&amp;gt;gamestate-&amp;gt;nextState( &amp;quot;nextPlayer&amp;quot; );&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Important: &amp;quot;nextPlayer&amp;quot; is the name of the transition, and NOT the name of the target game state. Multiple transitions can lead to the same game state.&lt;br /&gt;
&lt;br /&gt;
Note: If there is only 1 transition, you may give it an empty name.&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
In states.inc.php:&lt;br /&gt;
    &amp;quot;transitions&amp;quot; =&amp;gt; array( &amp;quot;&amp;quot; =&amp;gt; 27 ),&lt;br /&gt;
&lt;br /&gt;
In mygame.game.php:&lt;br /&gt;
    $this-&amp;gt;gamestate-&amp;gt;nextState(  );     // We don&#039;t need to specify a transition as there is only one here&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== possibleactions ===&lt;br /&gt;
&lt;br /&gt;
(&#039;&#039;&#039;Mandatory&#039;&#039;&#039; when the game state is &amp;quot;activeplayer&amp;quot; or &amp;quot;multipleactiveplayer&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
&amp;quot;possibleactions&amp;quot; defines the actions possible by the players in this game state, and ensures they cannot perform actions that are not allowed in this state.&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
In states.game.php:&lt;br /&gt;
       	&amp;quot;possibleactions&amp;quot; =&amp;gt; array( &amp;quot;actPlayCard&amp;quot;, &amp;quot;actPass&amp;quot; ),&lt;br /&gt;
&lt;br /&gt;
In mygame.game.php:&lt;br /&gt;
        function actPlayCard( ...)&lt;br /&gt;
        {&lt;br /&gt;
             $this-&amp;gt;checkAction( &amp;quot;actPlayCard&amp;quot; );    // Will fail if &amp;quot;actPlayCard&amp;quot; is not specified in &amp;quot;possibleactions&amp;quot; in the current game state.&lt;br /&gt;
&lt;br /&gt;
            ....&lt;br /&gt;
&lt;br /&gt;
In mygame.js:&lt;br /&gt;
        playCard: function( ... )&lt;br /&gt;
        {&lt;br /&gt;
            if( this.checkAction( &amp;quot;actPlayCard&amp;quot; ) ) // Will fail if &amp;quot;actPlayCard&amp;quot; is not specified in &amp;quot;possibleactions&amp;quot; in the current game state.&lt;br /&gt;
            {  return ;   }&lt;br /&gt;
// or &lt;br /&gt;
        playCard: function( ... )&lt;br /&gt;
        {&lt;br /&gt;
            if( this.bgaPerformAction( &amp;quot;actPlayCard&amp;quot;, { id} ) ) // Will not trigger if &amp;quot;actPlayCard&amp;quot; is not specified in &amp;quot;possibleactions&amp;quot; in the current game state.&lt;br /&gt;
            {  return ;   }&lt;br /&gt;
&lt;br /&gt;
            ....&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== args ===&lt;br /&gt;
&lt;br /&gt;
(optional)&lt;br /&gt;
&lt;br /&gt;
Sometimes it happens that you need some information on the client side (i.e., for your game interface) only for a specific game state.&lt;br /&gt;
&lt;br /&gt;
Example 1: in &#039;&#039;Reversi&#039;&#039;, the list of possible moves during the playerTurn state.&lt;br /&gt;
&lt;br /&gt;
Example 2: in &#039;&#039;Caylus&#039;&#039;, the number of remaining king&#039;s favors to choose in the state where the player is choosing a favor.&lt;br /&gt;
&lt;br /&gt;
Example 3: in &#039;&#039;Can&#039;t Stop&#039;&#039;, the list of possible die combinations to be displayed to the active player so that he can choose from among them.&lt;br /&gt;
&lt;br /&gt;
In such a situation, you can specify a method name as the « args » argument for your game state. This method must retrieve some piece of information about the game (example: for &#039;&#039;Reversi&#039;&#039;, the list of possible moves) and return it.&lt;br /&gt;
&lt;br /&gt;
Thus, this data can be transmitted to the clients and used by the clients to display it. It should always be an associative array.&lt;br /&gt;
&lt;br /&gt;
Let&#039;s see a complete example using args with &#039;&#039;Reversi&#039;&#039; game:&lt;br /&gt;
&lt;br /&gt;
In states.inc.php, we specify an &#039;&#039;&#039;args&#039;&#039;&#039; argument for gamestate &#039;&#039;&#039;playerTurn&#039;&#039;&#039;:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    10 =&amp;gt; array(&lt;br /&gt;
        &amp;quot;name&amp;quot; =&amp;gt; &amp;quot;playerTurn&amp;quot;,&lt;br /&gt;
		&amp;quot;description&amp;quot; =&amp;gt; clienttranslate(&#039;${actplayer} must play a disc&#039;),&lt;br /&gt;
		&amp;quot;descriptionmyturn&amp;quot; =&amp;gt; clienttranslate(&#039;${you} must play a disc&#039;),&lt;br /&gt;
        &amp;quot;type&amp;quot; =&amp;gt; &amp;quot;activeplayer&amp;quot;,&lt;br /&gt;
        &amp;quot;args&amp;quot; =&amp;gt; &amp;quot;argPlayerTurn&amp;quot;,    // &amp;lt;==== HERE&lt;br /&gt;
        &amp;quot;possibleactions&amp;quot; =&amp;gt; array( &#039;actPlayDisc&#039; ),&lt;br /&gt;
        &amp;quot;transitions&amp;quot; =&amp;gt; array( &amp;quot;playDisc&amp;quot; =&amp;gt; 11, &amp;quot;zombiePass&amp;quot; =&amp;gt; 11 )&lt;br /&gt;
    ),&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
It corresponds to a &#039;&#039;&#039;argPlayerTurn&#039;&#039;&#039; method in our PHP code (reversi.game.php):&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    function argPlayerTurn() {&lt;br /&gt;
        return array(&lt;br /&gt;
            &#039;possibleMoves&#039; =&amp;gt; $this-&amp;gt;getPossibleMoves()&lt;br /&gt;
        );&lt;br /&gt;
    }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Then, when we enter into the &#039;&#039;&#039;playerTurn&#039;&#039;&#039; game state on the client side, we can highlight the possible moves on the board using information returned by &#039;&#039;&#039;argPlayerTurn&#039;&#039;&#039;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        onEnteringState: function( stateName, args )  {&lt;br /&gt;
           console.log( &#039;Entering state: &#039;+stateName );&lt;br /&gt;
            &lt;br /&gt;
            switch( stateName )  {&lt;br /&gt;
            case &#039;playerTurn&#039;:&lt;br /&gt;
                this.updatePossibleMoves( args.args.possibleMoves );&lt;br /&gt;
                break;&lt;br /&gt;
            }&lt;br /&gt;
        },&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Naming and API conventions ====&lt;br /&gt;
&lt;br /&gt;
As a BGA convention, PHP methods called with &amp;quot;args&amp;quot; are prefixed by &amp;quot;arg&amp;quot; followed by state name (example: &#039;&#039;&#039;argPlayerTurn&#039;&#039;&#039;).&lt;br /&gt;
&lt;br /&gt;
All &amp;quot;arg*&amp;quot; methods are put into corresponding section of .game.php file commented as&lt;br /&gt;
   //////////// Game state arguments&lt;br /&gt;
&lt;br /&gt;
Arg method MUST return array. Return integer or string will result in some undebuggable exceptions.&lt;br /&gt;
&lt;br /&gt;
Arg method MUST be defined in php if it is declared in state description, if you don&#039;t need it comment it out from the states.inc.php file (the &#039;&#039;&#039;args&#039;&#039;&#039; parameter). If you not sure if you need it or not you can keep it returning empty array until you figure it out.&lt;br /&gt;
&lt;br /&gt;
    function argPlayerTurn() {&lt;br /&gt;
        return array(); // must be an array&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Warning&#039;&#039;&#039;: the &amp;quot;args&amp;quot; method is ALWAYS called before the &amp;quot;action&amp;quot; method so don&#039;t expect data modifications by the &amp;quot;action&amp;quot; method to be available in the &amp;quot;args&amp;quot; method!&lt;br /&gt;
Also don&#039;t modify database in this method!&lt;br /&gt;
&lt;br /&gt;
You should NOT be calling getCurrentPlayer() in the context of this function, since state transitions are broadcasted to all player independent of who initiated it. Instead you should send information on per player basis (Note: if this is private info see section below). &lt;br /&gt;
&lt;br /&gt;
If you using this function in multi-player state, you should not call getActivePlayer() either, you should send per player info:&lt;br /&gt;
&lt;br /&gt;
    function arg_playerTurn() {&lt;br /&gt;
        $res = array ();&lt;br /&gt;
        $players = $this-&amp;gt;loadPlayersBasicInfos();&lt;br /&gt;
        foreach ( $players as $player_id =&amp;gt; $player_info ) {&lt;br /&gt;
            $color = $player_info [&#039;player_color&#039;];&lt;br /&gt;
            $res [$player_id] = array(&amp;quot;color&amp;quot;=&amp;gt;$color);&lt;br /&gt;
        }&lt;br /&gt;
        return $res;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
Note: you never need to send player color like this, this is just an example.&lt;br /&gt;
&lt;br /&gt;
Note 2: you CAN call methods that return all active players if multi-player states if its relevant.&lt;br /&gt;
&lt;br /&gt;
==== Other usages ====&lt;br /&gt;
&lt;br /&gt;
You can use values returned by your &amp;quot;args&amp;quot; method to have some custom values in your &amp;quot;description&amp;quot;/&amp;quot;descriptionmyturn&amp;quot;, i.e. in states.inc.php:&lt;br /&gt;
&lt;br /&gt;
   &amp;quot;descriptionmyturn&amp;quot; =&amp;gt; clienttranslate(&#039;${you} must play ${color} disc&#039;),&lt;br /&gt;
&lt;br /&gt;
So arg function will be something like:&lt;br /&gt;
&lt;br /&gt;
  function argPlayerTurn() {&lt;br /&gt;
        return array(&#039;color&#039;=&amp;gt;$this-&amp;gt;getActivePlayerColor()); &lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
You can use args also in &#039;&#039;&#039;onUpdateActionButtons&#039;&#039;&#039; function on js side, however two important notes:&lt;br /&gt;
* it is just &#039;&#039;&#039;args&#039;&#039;&#039; (not args.args like in &#039;&#039;&#039;onEnteringState&#039;&#039;&#039;)&lt;br /&gt;
* it is args of the current state, which may not be state you think it will be! This method is called during change of active player, which happens in some weird place especially during &amp;quot;multipleactiveplayer&amp;quot; states. If you pulling your hair thinking why its &amp;quot;undefined&amp;quot; on js side - check the current state.&lt;br /&gt;
&lt;br /&gt;
==== Private info in args ====&lt;br /&gt;
&lt;br /&gt;
By default, all data provided through this method are PUBLIC TO ALL PLAYERS. Please do not send any private data with this method, as a cheater could see it even it is not used explicitly by the game interface logic.&lt;br /&gt;
&lt;br /&gt;
However, it is possible to specify that some data should be sent to specific players only.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note: You cannot use Example 1 and Example 2 together. If you have to send private args to multiple players, use Example 2.&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Example 1: send information to active player(s) only:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    function argPlayerTurn()  {&lt;br /&gt;
        return array(&lt;br /&gt;
            &#039;_private&#039; =&amp;gt; array(          // Using &amp;quot;_private&amp;quot; keyword, all data inside this array will be made private&lt;br /&gt;
                &#039;active&#039; =&amp;gt; array(       // Using &amp;quot;active&amp;quot; keyword inside &amp;quot;_private&amp;quot;, you select active player(s)&lt;br /&gt;
                    &#039;somePrivateData&#039; =&amp;gt; $this-&amp;gt;getSomePrivateData()   // will be send only to active player(s)&lt;br /&gt;
                )&lt;br /&gt;
            ),&lt;br /&gt;
            &#039;possibleMoves&#039; =&amp;gt; $this-&amp;gt;getPossibleMoves()          // will be sent to all players&lt;br /&gt;
        );&lt;br /&gt;
    }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Inside the js file, these variables will be available through `args.args._private`. (e.g. `args.args._private.somePrivateData` -- it is not `args._private.active.somePrivateData` nor is it `args.somePrivateData`)&lt;br /&gt;
&lt;br /&gt;
Example 2: send information to a specific player (&amp;lt;specific_player_id&amp;gt;) only:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    function argPlayerTurn()  {&lt;br /&gt;
        $specific_player_id = ...; // calculate some-how&lt;br /&gt;
        return array(&lt;br /&gt;
            &#039;_private&#039; =&amp;gt; array(   // all data inside this array will be private&lt;br /&gt;
                $specific_player_id =&amp;gt; array(   // will be sent only to that player   &lt;br /&gt;
                    &#039;somePrivateData&#039; =&amp;gt; $this-&amp;gt;getSomePrivateData()   &lt;br /&gt;
                )&lt;br /&gt;
            ),&lt;br /&gt;
&lt;br /&gt;
            &#039;possibleMoves&#039; =&amp;gt; $this-&amp;gt;getPossibleMoves()   // will be sent to all players&lt;br /&gt;
        );&lt;br /&gt;
    }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
IMPORTANT: in certain situations (i.e. &amp;quot;multipleactiveplayer&amp;quot; game state) these &amp;quot;private data&amp;quot; features can have a significant impact on performance. Please do not use if not needed.&lt;br /&gt;
&lt;br /&gt;
It is also possible to use these private args in the &amp;quot;description&amp;quot; messages, like &amp;quot;${you} have to play ${_private.count} cards&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
==== Flag to indicate a skipped state ====&lt;br /&gt;
&lt;br /&gt;
By default, The front-end will be notified of entering/leaving all states. To speed up the front-end chaining of automatically passed states, you can disable this state change notification, so the front-end doesn&#039;t trigger the preparation steps for a state that you know will be automatically skipped, and it may reduce sent args. In this case, define the &#039;&#039;&#039;_no_notify&#039;&#039;&#039; flag to true in the state args.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
function argPlayerTurn()  {&lt;br /&gt;
  $playableCardsIds = ...;&lt;br /&gt;
  return [&lt;br /&gt;
    &#039;playableCardsIds&#039; =&amp;gt; $playableCardsIds,&lt;br /&gt;
    &#039;_no_notify&#039; =&amp;gt; count(playableCardsIds) === 0,&lt;br /&gt;
  ];&lt;br /&gt;
}&lt;br /&gt;
function stPlayerTurn()  {&lt;br /&gt;
  $args = $this-&amp;gt;argPlayerTurn();&lt;br /&gt;
  if ($args[&#039;_no_notify&#039;]) {&lt;br /&gt;
    $this-&amp;gt;gamestate-&amp;gt;nextState(&#039;next&#039;);&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In this example, it might avoid a blinking message &amp;quot;You must play a card&amp;quot; (quickly replaced by the next state message) when you cannot play a card and the game automatically skips this state.&lt;br /&gt;
&lt;br /&gt;
IMPORTANT: if you use _no_notify, you must handle a redirection to another state on the st function!&lt;br /&gt;
&lt;br /&gt;
Note that if you play synced notifications during a skipped state, it will display the notifications on the previous state. For example, for an endScore state width description &amp;quot;Computing end score...&amp;quot; sending a lot of animated notifications, you should NOT use this flag so the description is visible.&lt;br /&gt;
&lt;br /&gt;
==== Translations in args ====&lt;br /&gt;
You can do the same as in notification by adding i18n parameter, i.e&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
function argPlayerTurn()  {&lt;br /&gt;
 return [&lt;br /&gt;
      &#039;i18n&#039; =&amp;gt; [&#039;terrainName&#039; ],&lt;br /&gt;
      &#039;terrainName&#039; =&amp;gt; ($this-&amp;gt;token_types[$terrain][&#039;name&#039;]), // this should be defined in material.inc.php and with clienttranslate &lt;br /&gt;
      &#039;terrain&#039; =&amp;gt; $terrain,&lt;br /&gt;
   ];&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Than you can do something like this in state:&lt;br /&gt;
  &amp;quot;descriptionmyturn&amp;quot; =&amp;gt; clienttranslate(&#039;${you} must place a house on ${terrainName}&#039;),&lt;br /&gt;
&lt;br /&gt;
See more in [[Translations]]&lt;br /&gt;
&lt;br /&gt;
=== updateGameProgression ===&lt;br /&gt;
&lt;br /&gt;
(optional)&lt;br /&gt;
&lt;br /&gt;
If you specify &amp;quot;updateGameProgression =&amp;gt; true&amp;quot; in a game state, your &amp;quot;getGameProgression&amp;quot; PHP method will be called at the beginning of this game state - and thus the game progression of the game will be updated.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;At least one&#039;&#039; of your game states (any one) must specify &amp;quot;updateGameProgression=&amp;gt;true&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
=== initialprivate ===&lt;br /&gt;
&lt;br /&gt;
(optional)&lt;br /&gt;
&lt;br /&gt;
This parameter will enable private parallel states in a multiplayer state. Parameter should be set to first private parallel state a player will be transitioned to.&lt;br /&gt;
See more details about Private parallel states [[#Private_parallel_states|here]].&lt;br /&gt;
&lt;br /&gt;
== Implementation Notes ==&lt;br /&gt;
&lt;br /&gt;
=== Private parallel states ===&lt;br /&gt;
&lt;br /&gt;
Private parallel states are useful when multiple players are active and their turn is very complex. In that case it is possible with parallel states for each player to be in a independent state. &lt;br /&gt;
&lt;br /&gt;
Lets say that players need to do three complex action one after another in multiactive state. With parallel states each player can independently be in a different state (i.e. one player still need to decide about first action while some players are deciding their second action and the fastest player is already on their third action. Normally this can be handled with two simple, but limited, approaches:&lt;br /&gt;
&lt;br /&gt;
* Moving all players to different states together - this is limiting for faster players as they need to wait other players for each separate action. The more problematic thing is that it would be hard to implement an undo feature when one player wants to change their previous action. In that case all players should be moved back to previous state which will interrupt their flow.&lt;br /&gt;
* Using client states, by changing the state in which the player is in javascript - the problem with this approach is that players will lose their progress on browser refresh (F5). Furthermore the validation logic of specific actions should be implemented on both server side and client side and we cannot have specific args for each different action, but they should be calculated only at the beginning of the first action and possibly calculated on client side after each action, which again duplicates logic on client and server.&lt;br /&gt;
&lt;br /&gt;
With private parallel states, each specific action can be implemented as a parallel state. Parallel states are defined with the type &#039;private&#039; and players are moved to those private states during one master multiactive state. Lets look at the example:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    10 =&amp;gt; [&lt;br /&gt;
        &amp;quot;name&amp;quot; =&amp;gt; &amp;quot;playerTurn&amp;quot;,&lt;br /&gt;
        &amp;quot;description&amp;quot; =&amp;gt; clienttranslate(&#039;Waiting for other players to end their turn.&#039;),&lt;br /&gt;
        &amp;quot;descriptionmyturn&amp;quot; =&amp;gt; clienttranslate(&#039;${you} must do your turn&#039;), // Won&#039;t be displayed anyway since each private state has its own description&lt;br /&gt;
        &amp;quot;type&amp;quot; =&amp;gt; &amp;quot;multipleactiveplayer&amp;quot;,&lt;br /&gt;
        &amp;quot;initialprivate&amp;quot; =&amp;gt; 50, // This makes this state a master multiactive state and enables private states, this is also a first private state&lt;br /&gt;
        &amp;quot;action&amp;quot; =&amp;gt; &amp;quot;stPlayerTurn&amp;quot;,&lt;br /&gt;
        &amp;quot;args&amp;quot; =&amp;gt; &amp;quot;argPlayerTurn&amp;quot;,&lt;br /&gt;
        &amp;quot;possibleactions&amp;quot; =&amp;gt; [&amp;quot;actChangeMind&amp;quot;], //this action is possible if player is not in any private state which usually happens when they are inactive&lt;br /&gt;
        &amp;quot;transitions&amp;quot; =&amp;gt; [&amp;quot;playersDecide&amp;quot; =&amp;gt; 11] // this is normal next transition which will happen after all players finish their turns &lt;br /&gt;
    ],&lt;br /&gt;
&lt;br /&gt;
    50 =&amp;gt; [&lt;br /&gt;
        &amp;quot;name&amp;quot; =&amp;gt; &amp;quot;chooseFirst&amp;quot;,&lt;br /&gt;
        &amp;quot;descriptionmyturn&amp;quot; =&amp;gt; clienttranslate(&#039;${you} must make your first choice&#039;), // just this parameter is needed. description is not needed as no player is inactive in this state&lt;br /&gt;
        &amp;quot;type&amp;quot; =&amp;gt; &amp;quot;private&amp;quot;, // this state is reachable only as a private state&lt;br /&gt;
        &amp;quot;args&amp;quot; =&amp;gt; &amp;quot;argChooseFirst&amp;quot;, //this method will be called with playerId as a parametar and is used to calculate arguments for this action for specific player&lt;br /&gt;
        &amp;quot;action&amp;quot; =&amp;gt; &amp;quot;stChooseFirst&amp;quot;, // this method will be called with playerId as a parameter and can be used to make some changes when player enters this private state&lt;br /&gt;
        &amp;quot;possibleactions&amp;quot; =&amp;gt; [&amp;quot;actToSecond&amp;quot;],&lt;br /&gt;
        &amp;quot;transitions&amp;quot; =&amp;gt; [&lt;br /&gt;
          &#039;chooseSecond&#039; =&amp;gt; 51, // transition to another private state&lt;br /&gt;
        ]&lt;br /&gt;
      ],&lt;br /&gt;
   &lt;br /&gt;
    51 =&amp;gt; [&lt;br /&gt;
        &amp;quot;name&amp;quot; =&amp;gt; &amp;quot;chooseSecond&amp;quot;,&lt;br /&gt;
        &amp;quot;descriptionmyturn&amp;quot; =&amp;gt; clienttranslate(&#039;${you} must make your second choice&#039;),&lt;br /&gt;
        &amp;quot;type&amp;quot; =&amp;gt; &amp;quot;private&amp;quot;,&lt;br /&gt;
        &amp;quot;args&amp;quot; =&amp;gt; &amp;quot;argChooseSecond&amp;quot;,&lt;br /&gt;
        &amp;quot;possibleactions&amp;quot; =&amp;gt; [&amp;quot;actFinish&amp;quot;, &amp;quot;actBack&amp;quot;],&lt;br /&gt;
        &amp;quot;transitions&amp;quot; =&amp;gt; [&lt;br /&gt;
          &#039;back&#039; =&amp;gt; 50,&lt;br /&gt;
        ]&lt;br /&gt;
      ],&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
When entering the master state it is usually useful to set some players as multiactive and initialize their private state:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    function stPlayerTurn() {&lt;br /&gt;
        $this-&amp;gt;gamestate-&amp;gt;setAllPlayersMultiactive();&lt;br /&gt;
        &lt;br /&gt;
        //this is needed when starting private parallel states; players will be transitioned to initialprivate state defined in master state&lt;br /&gt;
        $this-&amp;gt;gamestate-&amp;gt;initializePrivateStateForAllActivePlayers(); &lt;br /&gt;
&lt;br /&gt;
        // in some cases you can move immediately some or all players to different private states&lt;br /&gt;
        if ($someCondition) {&lt;br /&gt;
            //move all players to different state &lt;br /&gt;
            $this-&amp;gt;gamestate-&amp;gt;nextPrivateStateForAllActivePlayers(&amp;quot;chooseSecond&amp;quot;);&lt;br /&gt;
            return;&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        if ($other condition) {&lt;br /&gt;
            //move single player to different state&lt;br /&gt;
            $this-&amp;gt;gamestate-&amp;gt;nextPrivateState($specificPlayerId, &amp;quot;chooseSecond&amp;quot;);&lt;br /&gt;
            return;&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
When some action is done by a player, you can move them to the next private state:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    function actToSecond() {&lt;br /&gt;
        $this-&amp;gt;checkAction(&amp;quot;actToSecond&amp;quot;);  //the action must be defined in private state; actions defined in master state are not possible&lt;br /&gt;
        $this-&amp;gt;gamestate-&amp;gt;nextPrivateState($this-&amp;gt;getCurrentPlayerId(), &amp;quot;chooseSecond&amp;quot;); //moving current player to different state&lt;br /&gt;
    }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Please check the detailed API [[Main_game_logic:_yourgamename.game.php#Private_parallel_states|here]].&lt;br /&gt;
&lt;br /&gt;
=== Client States ===&lt;br /&gt;
Client state almost have nothing to do with server states, except they can simulate same experience without actually changing server states.&lt;br /&gt;
&lt;br /&gt;
See description here: https://en.doc.boardgamearena.com/BGA_Studio_Cookbook#Multi_Step_Interactions:_Select_Worker.2FPlace_Worker_-_Using_Client_States&lt;br /&gt;
&lt;br /&gt;
In many cases you can achive similar results by using client states vs private server states. The only caveat - when using client states during multiactive server state&lt;br /&gt;
other player will trigger state changes (multiactive player set) which will call onUpdateActionButtons. Some measures have to be taken to preserve client state in this case.&lt;br /&gt;
&lt;br /&gt;
=== Using Named Constants for States ===&lt;br /&gt;
&lt;br /&gt;
Using numeric constants is prone to errors. If you want you can declare state constants as PHP named constants. This way you can&lt;br /&gt;
use them in the states file and in game.php as well&lt;br /&gt;
&lt;br /&gt;
EXAMPLE:&lt;br /&gt;
&lt;br /&gt;
states.inc.php:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
// define contants for state ids&lt;br /&gt;
if (!defined(&#039;STATE_END_GAME&#039;)) { // ensure this block is only invoked once, since it is included multiple times&lt;br /&gt;
   define(&amp;quot;STATE_PLAYER_TURN&amp;quot;, 2);&lt;br /&gt;
   define(&amp;quot;STATE_GAME_TURN&amp;quot;, 3);&lt;br /&gt;
   define(&amp;quot;STATE_PLAYER_TURN_CUBES&amp;quot;, 4);&lt;br /&gt;
   define(&amp;quot;STATE_END_GAME&amp;quot;, 99);&lt;br /&gt;
}&lt;br /&gt;
 &lt;br /&gt;
$machinestates = array(&lt;br /&gt;
&lt;br /&gt;
   ...&lt;br /&gt;
&lt;br /&gt;
    STATE_PLAYER_TURN =&amp;gt; array(&lt;br /&gt;
    		&amp;quot;name&amp;quot; =&amp;gt; &amp;quot;playerTurn&amp;quot;,&lt;br /&gt;
    		&amp;quot;description&amp;quot; =&amp;gt; clienttranslate(&#039;${actplayer} must select an Action Space or Pass&#039;),&lt;br /&gt;
    		&amp;quot;descriptionmyturn&amp;quot; =&amp;gt; clienttranslate(&#039;${you} must select an Action Space or Pass&#039;),&lt;br /&gt;
    		&amp;quot;type&amp;quot; =&amp;gt; &amp;quot;activeplayer&amp;quot;,&lt;br /&gt;
                &amp;quot;args&amp;quot; =&amp;gt; &#039;arg_playerTurn&#039;,&lt;br /&gt;
    		&amp;quot;possibleactions&amp;quot; =&amp;gt; array( &amp;quot;actSelectWorkerAction&amp;quot;, &amp;quot;actPass&amp;quot; ),&lt;br /&gt;
    		&amp;quot;transitions&amp;quot; =&amp;gt; array( &lt;br /&gt;
    		        &amp;quot;loopback&amp;quot; =&amp;gt; STATE_PLAYER_TURN,&lt;br /&gt;
    		        &amp;quot;playCubes&amp;quot; =&amp;gt; STATE_PLAYER_TURN_CUBES,&lt;br /&gt;
    		        &amp;quot;pass&amp;quot; =&amp;gt; STATE_GAME_TURN )&lt;br /&gt;
    ),&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Example of multipleactiveplayer state ===&lt;br /&gt;
&lt;br /&gt;
This is an example of a multipleactiveplayer state:&lt;br /&gt;
&lt;br /&gt;
  2 =&amp;gt;  array (&lt;br /&gt;
    &#039;name&#039; =&amp;gt; &#039;playerTurnSetup&#039;,&lt;br /&gt;
    &#039;type&#039; =&amp;gt; &#039;multipleactiveplayer&#039;,&lt;br /&gt;
    &#039;description&#039; =&amp;gt; clienttranslate(&#039;Other players must choose one Objective&#039;),&lt;br /&gt;
    &#039;descriptionmyturn&#039; =&amp;gt; clienttranslate(&#039;${you} must choose one Objective card to keep&#039;),&lt;br /&gt;
    &#039;possibleactions&#039; =&amp;gt;     array (&#039;actPlayKeep&#039; ),&lt;br /&gt;
    &#039;transitions&#039; =&amp;gt;    array (       &#039;next&#039; =&amp;gt; 5, &#039;loopback&#039; =&amp;gt; 2, ),&lt;br /&gt;
    &#039;action&#039; =&amp;gt; &#039;st_MultiPlayerInit&#039;,&lt;br /&gt;
    &#039;args&#039; =&amp;gt; &#039;arg_playerTurnSetup&#039;,&lt;br /&gt;
  ),&lt;br /&gt;
&lt;br /&gt;
In game.php:&lt;br /&gt;
    // this will make all players multiactive just before entering the state&lt;br /&gt;
    function st_MultiPlayerInit() {&lt;br /&gt;
        $this-&amp;gt;gamestate-&amp;gt;setAllPlayersMultiactive();&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
Note: if you want exact this function its already defined in table class its called &#039;stMakeEveryoneActive&#039;&lt;br /&gt;
&lt;br /&gt;
When ending the player action, instead of a state transition, deactivate player.&lt;br /&gt;
&lt;br /&gt;
    function actPlayKeep($cardId) {&lt;br /&gt;
        $this-&amp;gt;checkAction(&#039;actPlayKeep&#039;);&lt;br /&gt;
        $player_id = $this-&amp;gt;getCurrentPlayerId(); // CURRENT!!! not active&lt;br /&gt;
        ... // some logic here&lt;br /&gt;
        $this-&amp;gt;gamestate-&amp;gt;setPlayerNonMultiactive($player_id, &#039;next&#039;); // deactivate player; if none left, transition to &#039;next&#039; state&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
=== Difference between Single active and Multi active states ===&lt;br /&gt;
In a classic &amp;quot;activePlayer&amp;quot; state:&lt;br /&gt;
&lt;br /&gt;
* You cannot change the active player DURING the state. This is to ensure that during 1 activePlayer state, only ONE player is active&lt;br /&gt;
* As a consequence, you must set the active player BEFORE entering the activePlayer state&lt;br /&gt;
* In such states on JS side onUpdateActionButtons is called before onEnteringState during game play (but after during reload, i.e. F5)&lt;br /&gt;
* Finally, during onEnteringState, on JS side, the active player is signaled as active and the information is reliable and usable.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
In a &amp;quot;multiplePlayer&amp;quot; state:&lt;br /&gt;
&lt;br /&gt;
* You can (and must) change the active players DURING the state&lt;br /&gt;
* During such a state, players can be activated/desactivated anytime during the state, giving you the maximum of possibilities.&lt;br /&gt;
* You shouldn&#039;t set active player before entering the state. But you can set it in &amp;quot;state initializer&amp;quot; php function (see example above st_MultiPlayerInit)&lt;br /&gt;
* Finally, during onEnteringState, on JS side, the active players are NOT active yet so you must use onUpdateActionButtons to perform the client side operation which depends on a player active/inactive status.&lt;br /&gt;
&lt;br /&gt;
Note: in some off cases other players can perform special actions even if they are not active, see example https://en.doc.boardgamearena.com/BGA_Studio_Cookbook#Out-of-turn_actions%3A_Un-pass. Do not abuse this technique!&lt;br /&gt;
&lt;br /&gt;
=== Designing states ===&lt;br /&gt;
&lt;br /&gt;
As a general rule you state machine should resemble &amp;quot;round/turn overview&amp;quot; from the game rule-book. Normally if book say its player turn and player can do multiple things during their turn it is still only&lt;br /&gt;
one player state (plus a game to switch player), not muliple states.&lt;br /&gt;
&lt;br /&gt;
In a classic game (i.e. chess), there is only active player at any time, so it is simple playerTurn/gameTurn sequence and you only need 2 states.&lt;br /&gt;
&lt;br /&gt;
[[File:Simplestates.png]]&lt;br /&gt;
&lt;br /&gt;
In complex euro game there can be multiple rounds, and each round have phases which can be distinctly unique, i.e. in first phase everybody draws card and discard (multi-player), then player have one turn each (single-active), then another is resolution of actions from players and some of them may become active again, then there is round upkeep/reset. This would require one multi-player state for phase 1, pair of states for phase2 (singel-active + game), pair of states for phase3 and finally round-end/unkeep game state.&lt;br /&gt;
&lt;br /&gt;
For pair of active player/game states you can make player state first, which transitions to game state, or the other way around, you start with game state which transition to active player state, its loop in any case but depends on how you want to do &amp;quot;phase&amp;quot; initiazations.&lt;br /&gt;
&lt;br /&gt;
[[File:Eurogamestates.png]]&lt;br /&gt;
&lt;br /&gt;
=== Complete examples ===&lt;br /&gt;
&lt;br /&gt;
Example of simple game where player take turns&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
if ( !defined(&#039;STATE_END_GAME&#039;)) { // guard since this included multiple times&lt;br /&gt;
    define(&amp;quot;STATE_PLAYER_TURN&amp;quot;, 2);&lt;br /&gt;
    define(&amp;quot;STATE_GAME_TURN_NEXT_PLAYER&amp;quot;, 3);&lt;br /&gt;
    define(&amp;quot;STATE_PLAYER_GAME_END&amp;quot;, 4);&lt;br /&gt;
    define(&amp;quot;STATE_END_GAME&amp;quot;, 99);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
$machinestates = [    &lt;br /&gt;
        1 =&amp;gt; [ // The initial state. Please do not modify.&lt;br /&gt;
               &amp;quot;name&amp;quot; =&amp;gt; &amp;quot;gameSetup&amp;quot;,&lt;br /&gt;
               &amp;quot;description&amp;quot; =&amp;gt; &amp;quot;&amp;quot;,&lt;br /&gt;
               &amp;quot;type&amp;quot; =&amp;gt; &amp;quot;manager&amp;quot;,&lt;br /&gt;
               &amp;quot;action&amp;quot; =&amp;gt; &amp;quot;stGameSetup&amp;quot;,&lt;br /&gt;
               &amp;quot;transitions&amp;quot; =&amp;gt; [ &amp;quot;&amp;quot; =&amp;gt; STATE_PLAYER_TURN ] ],&lt;br /&gt;
        // Game states &lt;br /&gt;
        STATE_PLAYER_TURN =&amp;gt; [ // main active player state &lt;br /&gt;
                &amp;quot;name&amp;quot; =&amp;gt; &amp;quot;playerTurn&amp;quot;,&lt;br /&gt;
                &amp;quot;description&amp;quot; =&amp;gt; clienttranslate(&#039;${actplayer} must do something or pass&#039;),&lt;br /&gt;
                &amp;quot;descriptionmyturn&amp;quot; =&amp;gt; clienttranslate(&#039;${you} must do something or pass&#039;),&lt;br /&gt;
                &amp;quot;type&amp;quot; =&amp;gt; &amp;quot;activeplayer&amp;quot;,&lt;br /&gt;
                &amp;quot;args&amp;quot; =&amp;gt; &amp;quot;arg_playerTurn&amp;quot;,&lt;br /&gt;
                &amp;quot;possibleactions&amp;quot; =&amp;gt; [ &amp;quot;actDSomething&amp;quot;,&amp;quot;actPass&amp;quot; ],&lt;br /&gt;
                &amp;quot;transitions&amp;quot; =&amp;gt; [ &amp;quot;next&amp;quot; =&amp;gt; STATE_GAME_TURN_NEXT_PLAYER,&amp;quot;last&amp;quot; =&amp;gt; STATE_PLAYER_GAME_END ] // &lt;br /&gt;
        ],&lt;br /&gt;
        STATE_GAME_TURN_NEXT_PLAYER =&amp;gt; [ // next player state&lt;br /&gt;
                &amp;quot;name&amp;quot; =&amp;gt; &amp;quot;gameTurnNextPlayer&amp;quot;,&lt;br /&gt;
                &amp;quot;description&amp;quot; =&amp;gt; clienttranslate(&#039;Upkeep...&#039;),&lt;br /&gt;
                &amp;quot;type&amp;quot; =&amp;gt; &amp;quot;game&amp;quot;, //&lt;br /&gt;
                &amp;quot;action&amp;quot; =&amp;gt; &amp;quot;st_gameTurnNextPlayer&amp;quot;, //&lt;br /&gt;
                &amp;quot;updateGameProgression&amp;quot; =&amp;gt; true,&lt;br /&gt;
                &amp;quot;transitions&amp;quot; =&amp;gt; [ &amp;quot;next&amp;quot; =&amp;gt; STATE_PLAYER_TURN,&amp;quot;loopback&amp;quot; =&amp;gt; STATE_GAME_TURN_NEXT_PLAYER,&lt;br /&gt;
                        &amp;quot;last&amp;quot; =&amp;gt; STATE_PLAYER_GAME_END ], // TODO replace with STATE_END_GAME, its there to use undo/restore during dev&lt;br /&gt;
        ],&lt;br /&gt;
    &lt;br /&gt;
        STATE_PLAYER_GAME_END =&amp;gt; [ // active player state for debugging end of game&lt;br /&gt;
                &amp;quot;name&amp;quot; =&amp;gt; &amp;quot;playerGameEnd&amp;quot;,&lt;br /&gt;
                &amp;quot;description&amp;quot; =&amp;gt; clienttranslate(&#039;${actplayer} Game Over&#039;),&lt;br /&gt;
                &amp;quot;descriptionmyturn&amp;quot; =&amp;gt; clienttranslate(&#039;${you} Game Over&#039;),&lt;br /&gt;
                &amp;quot;type&amp;quot; =&amp;gt; &amp;quot;activeplayer&amp;quot;,&lt;br /&gt;
                &amp;quot;args&amp;quot; =&amp;gt; &amp;quot;arg_playerTurn&amp;quot;,&lt;br /&gt;
                &amp;quot;possibleactions&amp;quot; =&amp;gt; [&amp;quot;actEndGame&amp;quot;],&lt;br /&gt;
                &amp;quot;transitions&amp;quot; =&amp;gt; [&amp;quot;next&amp;quot; =&amp;gt; STATE_END_GAME,&amp;quot;loopback&amp;quot; =&amp;gt; STATE_PLAYER_GAME_END ] // &lt;br /&gt;
        ],&lt;br /&gt;
        // End of Game states &lt;br /&gt;
        // Final state.&lt;br /&gt;
        // Please do not modify (and do not overload action/args methods).&lt;br /&gt;
        STATE_END_GAME =&amp;gt; [&lt;br /&gt;
                &amp;quot;name&amp;quot; =&amp;gt; &amp;quot;gameEnd&amp;quot;,&lt;br /&gt;
                &amp;quot;description&amp;quot; =&amp;gt; clienttranslate(&amp;quot;End of game&amp;quot;),&amp;quot;type&amp;quot; =&amp;gt; &amp;quot;manager&amp;quot;,&lt;br /&gt;
                &amp;quot;action&amp;quot; =&amp;gt; &amp;quot;stGameEnd&amp;quot;,&lt;br /&gt;
                &amp;quot;args&amp;quot; =&amp;gt; &amp;quot;argGameEnd&amp;quot; ] &lt;br /&gt;
&lt;br /&gt;
];&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Category:Studio]]&lt;/div&gt;</summary>
		<author><name>Sguzzer Gunayer</name></author>
	</entry>
	<entry>
		<id>https://en.doc.boardgamearena.com/index.php?title=Bots_and_Artificial_Intelligence&amp;diff=22597</id>
		<title>Bots and Artificial Intelligence</title>
		<link rel="alternate" type="text/html" href="https://en.doc.boardgamearena.com/index.php?title=Bots_and_Artificial_Intelligence&amp;diff=22597"/>
		<updated>2024-09-16T14:55:55Z</updated>

		<summary type="html">&lt;p&gt;Sguzzer Gunayer: /* Server Bot as registered game Player */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;br /&gt;
&lt;br /&gt;
There is no framework support (now) for AI/Bots, so it is all custom stuff.&lt;br /&gt;
&lt;br /&gt;
What about &amp;quot;Can&#039;t Stop&amp;quot; Bot? Well it is the only game that has AI (without I) that is treated as separate player, admins won&#039;t &lt;br /&gt;
reveal how it is done nor that is feasible to implement in other games.&lt;br /&gt;
&lt;br /&gt;
== Games ==&lt;br /&gt;
The following game have modes that support bots Conspiracy, Glow, Crew, Crew Deepsea, Tapestry.&lt;br /&gt;
&lt;br /&gt;
NOTE: None of them currently is a real AI. Usually its implementation of &amp;quot;Automa&amp;quot; rules of the games, so you can play solo game.&lt;br /&gt;
== Techniques ==&lt;br /&gt;
=== Testing bot ===&lt;br /&gt;
Testing bot is actually JavaScript bot that presses on buttons on behalf of player. Its handy for testing on Studio.&lt;br /&gt;
Recommended way of doing it is add Studio only button (together with debug bar) &amp;quot;Run bot/Stop bot&amp;quot;, when running it can react to state changes and press stuff.&lt;br /&gt;
Example &amp;quot;Battleship&amp;quot; (this only appear on Studio as this is for testing only)&lt;br /&gt;
&lt;br /&gt;
=== JavaScript AI ===&lt;br /&gt;
Currently I don&#039;t see how it is feasible, JS code requires real player connected to game and browser, so it cannot be run as AI engine&lt;br /&gt;
&lt;br /&gt;
=== Server Bot as registered game Player ===&lt;br /&gt;
This would be ideal, but currently only Can&#039;t Stop does it and no other game can use this technique&lt;br /&gt;
&lt;br /&gt;
=== Server Bot as game state action ===&lt;br /&gt;
This is the only feasible way in production. In addition to whatever game states are doing, it can handle fake players and simulate their moves&lt;br /&gt;
&lt;br /&gt;
In some games Bot will take player color and whole player board similar to real player, and can even have resources.&lt;br /&gt;
So it natural that Bot behaive like a player in a game.&lt;br /&gt;
However you cannot add fake player into player table, so you cannot add any field in that table to track resources for examples. &lt;br /&gt;
You cannot make fake player active or multiactive. How you do it then? See playerextra table below.&lt;br /&gt;
&lt;br /&gt;
==== Bot Player ID ====&lt;br /&gt;
Reserve non-exising player id for bots (i.e. 1-6).&lt;br /&gt;
If bot needs color and order see below.&lt;br /&gt;
&lt;br /&gt;
==== Bot Color, Order and Resources ====&lt;br /&gt;
Create table similar player to track bots color, name, score, score_aux and possibly other stuff&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
CREATE TABLE IF NOT EXISTS `playerextra` (&lt;br /&gt;
 `player_id` int(10) unsigned NOT NULL,&lt;br /&gt;
 `player_name` varchar(32) NOT NULL,&lt;br /&gt;
 `player_avatar` varchar(10) NOT NULL,&lt;br /&gt;
 `player_color` varchar(6) NOT NULL,&lt;br /&gt;
 `player_no` int(10) NOT NULL,&lt;br /&gt;
 `player_score` int(10) NOT NULL DEFAULT &#039;0&#039;,&lt;br /&gt;
 `player_score_aux` int(10) NOT NULL DEFAULT &#039;0&#039;,&lt;br /&gt;
 `player_ai` tinyint(1) NOT NULL DEFAULT &#039;0&#039; COMMENT &#039;1 = player is an AI&#039;,&lt;br /&gt;
  PRIMARY KEY (`player_id`)&lt;br /&gt;
) ENGINE=InnoDB DEFAULT CHARSET=utf8 ;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Bot Actions ====&lt;br /&gt;
* All actions that can be done by Bot have to have $player_id as argument and not use active player&lt;br /&gt;
* Separate code of ajax actions themselves and functional code, so function can be run from ajax action or from game state action&lt;br /&gt;
* If you using getPlayerNameById to send player_name in notification, you may have to override id (same for player color)&lt;br /&gt;
    public function getPlayerNameById($player_id) {&lt;br /&gt;
        if ($player_id == PLAYER_AUTOMA)&lt;br /&gt;
            return (&#039;Automa&#039;);&lt;br /&gt;
        return parent::getPlayerNameById($player_id);&lt;br /&gt;
    } &lt;br /&gt;
* You may also create a function like loadPlayersBasicInfosWithBots which will return similar data as loadPlayersBasicInfos but with bots ids. Cache the result if using a lot&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    function loadPlayersBasicInfosWithBots() {&lt;br /&gt;
        $player_basic = $this-&amp;gt;loadPlayersBasicInfos();&lt;br /&gt;
        if ( !$this-&amp;gt;isAutoma())&lt;br /&gt;
            return $player_basic;           &lt;br /&gt;
        if ( !isset($this-&amp;gt;player_bots)) {&lt;br /&gt;
            $this-&amp;gt;player_bots = $this-&amp;gt;getCollectionFromDb(&amp;quot;SELECT * FROM playerextra&amp;quot;);&lt;br /&gt;
        }&lt;br /&gt;
        return $this-&amp;gt;player_bots + $player_basic;&lt;br /&gt;
    }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Bot Player Panel ====&lt;br /&gt;
If you want bot on player panel you have to add it manually.&lt;br /&gt;
You can either create template similar to real one or use this hack.&lt;br /&gt;
Below we get player_id and player from playerextra&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
var over = $(&#039;overall_player_board_&#039; + player_id);&lt;br /&gt;
if (!over) {&lt;br /&gt;
	let active_id = this.getActivePlayers()[0];&lt;br /&gt;
	let active_name = gamedatas.players[active_id].name;&lt;br /&gt;
	var xclone = $(&#039;overall_player_board_&#039; + active_id).outerHTML;&lt;br /&gt;
	xclone = xclone.replaceAll(String(active_id), player_id);&lt;br /&gt;
	xclone = xclone.replaceAll(active_name, player.name);&lt;br /&gt;
	xclone = xclone.replaceAll(gamedatas.players[active_id].color, player.color);&lt;br /&gt;
        var node = dojo.place(xclone, &#039;player_boards&#039;);&lt;br /&gt;
// tweak to change avatar status and such&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Bot Player Notifications ====&lt;br /&gt;
When you send notification with ${player_name} you also should send &#039;player_id&#039; with you fake id.&lt;br /&gt;
In additio getAllDatas() should contain record matching fake player id in players field, i.e if $player has data for fake player:&lt;br /&gt;
    protected function getAllDatas() {&lt;br /&gt;
        $result = [];&lt;br /&gt;
    ...&lt;br /&gt;
            $result [&#039;players&#039;] [$player_id] [&#039;id&#039;] = $player[&#039;id&#039;];&lt;br /&gt;
            $result [&#039;players&#039;] [$player_id] [&#039;score&#039;] = $player[&#039;score&#039;];&lt;br /&gt;
            $result [&#039;players&#039;] [$player_id] [&#039;color&#039;] = $player[&#039;color&#039;];&lt;br /&gt;
            $result [&#039;players&#039;] [$player_id] [&#039;name&#039;] = $player[&#039;name&#039;];&lt;br /&gt;
   ...&lt;br /&gt;
        return $result;&lt;br /&gt;
   }&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
 [[Category:Studio]]&lt;/div&gt;</summary>
		<author><name>Sguzzer Gunayer</name></author>
	</entry>
	<entry>
		<id>https://en.doc.boardgamearena.com/index.php?title=Create_a_game_in_BGA_Studio:_Complete_Walkthrough&amp;diff=22596</id>
		<title>Create a game in BGA Studio: Complete Walkthrough</title>
		<link rel="alternate" type="text/html" href="https://en.doc.boardgamearena.com/index.php?title=Create_a_game_in_BGA_Studio:_Complete_Walkthrough&amp;diff=22596"/>
		<updated>2024-09-16T14:39:19Z</updated>

		<summary type="html">&lt;p&gt;Sguzzer Gunayer: /* Level Up */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Introduction ==&lt;br /&gt;
&lt;br /&gt;
This document is not a tutorial, but step by step instructions on how to build your own first game adaptation using the BGA Studio framework.&lt;br /&gt;
&lt;br /&gt;
Before you read this material, you must:&lt;br /&gt;
* Read the overall presentations of the [[Studio|BGA Studio]].&lt;br /&gt;
* Know (at least somewhat) the languages used by BGA Studio: PHP, SQL, HTML, CSS, JavaScript&lt;br /&gt;
* Set up your development environment: [http://en.doc.boardgamearena.com/First_steps_with_BGA_Studio First Steps with BGA Studio]&lt;br /&gt;
* Create a game using one of the available tutorials. Don&#039;t bother trying to create a new game until you have completed at least one of the tutorials.&lt;br /&gt;
&lt;br /&gt;
If you&#039;re stuck or have questions about this page post on [https://forum.boardgamearena.com/viewforum.php?f=12 BGA Developers forum].&lt;br /&gt;
If you&#039;re uncomfortable posting on the public forum you can send messages directly to developers who post answers on that forum but NOT the BGA admins.&lt;br /&gt;
If you find typos in this wiki, fix them.&lt;br /&gt;
&lt;br /&gt;
== Select a First Game ==&lt;br /&gt;
&lt;br /&gt;
For your first &#039;&#039;&#039;real&#039;&#039;&#039; game (after you&#039;ve completed at least one tutorial), you must select a game from one of these options:&lt;br /&gt;
* [https://studio.boardgamearena.com/licensing Available Licenses]&lt;br /&gt;
* Public Domain&lt;br /&gt;
&lt;br /&gt;
But what if the game you want isn&#039;t in either of those categories? If you&#039;re able to successfully publish another game, you may gain the trust of the BGA admins, and they will then be happy to assist you in obtaining a license for a game you really want to do. Alternatively, you can request a license yourself. For more about game licenses, see the [[BGA Game licenses]] page.&lt;br /&gt;
&lt;br /&gt;
After you choose a game, but before creating a new project, take a few seconds to [http://studio.boardgamearena.com/#!projects check the list of current projects], to make sure that someone is not already developing that game. If they are, consider asking to join the project rather than starting a new project yourself.&lt;br /&gt;
&lt;br /&gt;
But even if you see a few projects with the name of the game in question, they may not be active. There are a lot of abandoned game projects. If it&#039;s not clear by the status of the project, then post to the Developers forum asking if anybody is actively working on the project, or send a message to the developers listed for the abandoned projects. At the same time, ask admins on the same forum to send you graphics for that game if they have them. (There&#039;s a button on the [https://studio.boardgamearena.com/licensing Available Licenses] page to request graphics, but that button just sends an email.)&lt;br /&gt;
&lt;br /&gt;
If your goal was to fix bugs in an existing project, first try to locate it on Studio, but note that projects developed by BGA admins are not in Studio. Then get read-only access to the project, and create your own as a copy of the existing one. Contact a project admin about getting write access to the original project, or ask if they are willing to apply your patches.&lt;br /&gt;
&lt;br /&gt;
If you want to take over an existing project, first ask on the forum to see if the project is abandoned, then get read-only access (via project list) and see if it&#039;s worth using the existing project. If it has no code or graphics, then just start from the scratch. Don&#039;t worry about the project name; it can be renamed later.&lt;br /&gt;
&lt;br /&gt;
== Create a project ==&lt;br /&gt;
&lt;br /&gt;
If you have not already, you have to create a project in BGA Studio for this game. If the original game name is taken use gamenameYOURINITIALS&lt;br /&gt;
template, i.e.&amp;quot;heartsla&amp;quot;. Don&#039;t worry too much about the name, if the game is good enough to publish, it will be renamed to its original name. &lt;br /&gt;
&lt;br /&gt;
Find and start the game in turn based mode, make sure it works.&lt;br /&gt;
&lt;br /&gt;
Second, modify the text in .tpl file, reload the page in the browser and make sure your ftp sync works as expected.&lt;br /&gt;
Note: if you have not setup [http://en.doc.boardgamearena.com/Tools_and_tips_of_BGA_Studio#File_Sync FTP auto-sync] yet, do it now, manually copying files is a no-starter.&lt;br /&gt;
&lt;br /&gt;
Update your project status on [http://studio.boardgamearena.com/#!studio Control Panel &amp;gt; Manage games] page, you can say &amp;quot;development started&amp;quot; or &amp;quot;waiting for the license&amp;quot; or &amp;quot;waiting for graphics&amp;quot; or a combination of those.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Development Tools ==&lt;br /&gt;
&lt;br /&gt;
At some point, you need to setup your development environment which consists of multiple tools, such as&lt;br /&gt;
* Editor or IDE&lt;br /&gt;
* Browser with dev tools&lt;br /&gt;
* File sync tools&lt;br /&gt;
* BGA Web tools&lt;br /&gt;
* Image manipulation tools&lt;br /&gt;
* Version control tools&lt;br /&gt;
&lt;br /&gt;
Please scan through articles from [[Studio#BGA_Studio_user_guide]] especially those related to debugging and tools, there is a lot of useful info there.&lt;br /&gt;
&lt;br /&gt;
== Hook version control system ==&lt;br /&gt;
&lt;br /&gt;
If it&#039;s a real game, I would commit the code to version control right at the start. You are going to find yourself in a situation where the game does not even start anymore and there is no way of debugging it unless you have a way to revert. That is where version control becomes very handy.&lt;br /&gt;
If you don&#039;t know what I am talking about then at least back-up your files after each of the major steps. Starting now.&lt;br /&gt;
You can also create a project on github, but make sure &#039;&#039;&#039;you don&#039;t commit original publisher graphics files&#039;&#039;&#039; and &#039;&#039;&#039;you don&#039;t include a file with your sftp password&#039;&#039;&#039; (github is automatically crawled for passwords by hackers; a hacking attempt occurred on BGA studio for this reason in June 2020).&lt;br /&gt;
You can (and should) also commit your modification periodically via Studio Control Panel.&lt;br /&gt;
&lt;br /&gt;
== Obtain game graphics ==&lt;br /&gt;
&lt;br /&gt;
If you developing a game from the Available Licenses section, ask the admins to send you graphics by using the &#039;&#039;&#039;Request Art Files&#039;&#039;&#039; button available on the studio license page. While that request is being processed (it can take time, as it often requires some back and forth between the admins and the publishers) you can proceed to the next step - project creation.&lt;br /&gt;
&lt;br /&gt;
If you don&#039;t get original graphics you go to &#039;&#039;&#039;Scavenger Hunt&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
* If you developing a public domain card game you can borrow standard cards from BGA generic assets, see [[Common_board_game_elements_image_resources]]&lt;br /&gt;
* Standard game pieces - meeples, cubes, dice can be found here as well [[Common_board_game_elements_image_resources]]&lt;br /&gt;
* Go to boardgamegeek.com find your game and obtain 3D game box image, 2D box image, and if you are lucky they also sometimes have boards and token scans in &amp;quot;Game Pieces&amp;quot; section of Images&lt;br /&gt;
* If that fails, google &amp;quot;boardgame &amp;lt;name&amp;gt;&amp;quot; and check the Images section&lt;br /&gt;
* Get the rules PDF as well, there&#039;re tools that allow you to extract graphics from PDF, which are usually good for meeples, cubes and such (can use pdfimages command line tool)&lt;br /&gt;
&lt;br /&gt;
Once you get the graphics one way or another you have to massage them to fit in the BGA criteria, which usually involves&lt;br /&gt;
* If the publisher sends graphics in one token/card per file mode, you have to stitch them in sprite and scale down&lt;br /&gt;
* For non square tiles and game pieces you need transparency&lt;br /&gt;
* Usually you chop off the scoring &amp;quot;ring&amp;quot; around the board of the game since the scoring track is not needed for online adaptation&lt;br /&gt;
&lt;br /&gt;
More details about graphics requirements can be found here [[Game art: img directory]].&lt;br /&gt;
&lt;br /&gt;
[[File:Rrr_search.png]]&lt;br /&gt;
&lt;br /&gt;
== Obtain game documentation ==&lt;br /&gt;
&lt;br /&gt;
Also at this time obtain an electronic copy of rules, such as PDF (English version). &lt;br /&gt;
&lt;br /&gt;
Also grab any other documents you may find on boardgamegeek such as FAQ, additional Reference books, and user created assistant documents, such&lt;br /&gt;
as cheat-sheets (may be easier to get data from these than trying to scrub pdf). You create and place them in the doc/ folder of the project then&lt;br /&gt;
exclude them from version control. There is also a misc/ folder now but it will hold up to 1 Mb of data files which would be checked in, so rules pdf&#039;s may not fit there.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Update game info and box graphics ==&lt;br /&gt;
&lt;br /&gt;
Even if is not playable yet, start with making sure the game looks descent in the game selector, meaning it has nice box graphics and the information is correct. &lt;br /&gt;
&lt;br /&gt;
For that we need to edit [[Game_meta-information: gameinfos.inc.php|gameinfos.inc.php]].&lt;br /&gt;
What you would do for the real game you would go to http://boardgamegeek.com find the game and use information from the website to fill the gameinfos.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The next step is to replace game_box.png with proper images, usually, you can find all images including the publisher logo on the boardgamegeek website.&lt;br /&gt;
&lt;br /&gt;
Game metadata images, such box image are now managed in separate tool.&lt;br /&gt;
&lt;br /&gt;
Details about images can be found here: [[Game art: img directory]].&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[File:Gamepanel_sharedcode.png]]&lt;br /&gt;
&lt;br /&gt;
Now try to start the game again. If you some-how introduced a syntax error in gameinfos file it may not actually work (game won&#039;t start).&lt;br /&gt;
Always use &amp;quot;Express Start&amp;quot; button to start the game. You should see a standard state prompt from template. You should see X players on the right, testdude0 .. testdudeX-1.&lt;br /&gt;
To switch between them press the red arrow button near their names, it will open another tab. This way you don&#039;t need to login and logout from multiple accounts!&lt;br /&gt;
&lt;br /&gt;
== Fix source copyright ==&lt;br /&gt;
&lt;br /&gt;
Now since you have your own project, you want to put your name in the copyright header, so replace&lt;br /&gt;
&lt;br /&gt;
  © &amp;lt;Your name here&amp;gt; &amp;lt;Your email address here&amp;gt;&lt;br /&gt;
with&lt;br /&gt;
  © John Snow &amp;lt;jsnow@gameofthrones.com&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Well not exactly this but whatever your real name is. For all files in the project directory, it&#039;s about 10 files. Make sure the project still starts after that :)&lt;br /&gt;
&lt;br /&gt;
== Reduce the Rules ==&lt;br /&gt;
&lt;br /&gt;
Programming a game will take a lot more time than you may think. Most of the projects in the studio are abandoned because of a lack of patience or skill.&lt;br /&gt;
To keep sane, start the game with *reduced* rules and try to complete that first.&lt;br /&gt;
&lt;br /&gt;
* If it has any expansions - do not even attempt to deal with them, not even - &amp;quot;I will just add graphics for them now and not use&amp;quot; - waste of time if you don&#039;t complete basic&lt;br /&gt;
* If it has advanced rules - start with basic rules only, i.e. &amp;quot;beginner game&amp;quot;&lt;br /&gt;
* If it has special rules for 2 players vs 4, start with the most basic form (i.e. 4), restrict to 4 players &lt;br /&gt;
* If it has 50 unique cards of 2 each - start with 2 unique cards with 25 each (just to keep it moving)&lt;br /&gt;
* Any sort of rules that you think can be removed and not included in base - set aside for now &lt;br /&gt;
* Ignore any sort of cool animations - dice rolling, card flipping, choo-choo sounds of the trains - all this fluff can be added later&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Design Game Elements ==&lt;br /&gt;
Technically game elements are already designed by a board game designer but your job is to map them to program space.&lt;br /&gt;
Each physical piece (card, token, cube) will leave footprints all over the code (unfortunately in multiple disconnected places).&lt;br /&gt;
To prepare the game you need to sort out these elements, i.e. categorize. I usually have the following categorization (in object oriented view):&lt;br /&gt;
* Instance - all individual pieces are instances, i.e. two red cubes are two instances of &#039;red cube&#039; type (class)&lt;br /&gt;
* Type - element type which distinctly represents that element in appearance (i.e. red cube is a different type than blue cube)&lt;br /&gt;
* Super Type - one of the more common types that similar properties (i.e. red OR cube)&lt;br /&gt;
* Player color - supertype specific for player color (sometimes there are no colors but like player 1 - but is conceptually the same, I use color because it&#039;s easier to track)&lt;br /&gt;
&lt;br /&gt;
Personally, I like to encode my elements in a string using reverse DNS notation listing all the properties above, i.e.&lt;br /&gt;
  meeple_ff0000_7 - this is instance #7 of type meeple_ff0000 (red meeple)&lt;br /&gt;
Or&lt;br /&gt;
  card_yellow_magic_2 - this is instance #2 of a yellow card (in this case yellow is the color of the deck, not related to player color) that can do magic&lt;br /&gt;
&lt;br /&gt;
So every game element would be in the&lt;br /&gt;
&lt;br /&gt;
1. Database - instances. The db record would be something like &lt;br /&gt;
  key|location|state&lt;br /&gt;
  meeple_ff0000_7|slot_action_2|1&lt;br /&gt;
  meeple_ff0000_2|tableau_ff0000|0&lt;br /&gt;
2. Material file - types and supertypes, we never need repeating info here, so never list individual instances but only types or supertypes, in this case, we don&#039;t really need to define red meeple vs blue meeple&lt;br /&gt;
  &#039;meeple&#039;=&amp;gt;{&#039;name&#039;=&amp;gt;totranslate(&#039;Meeple&#039;)}&lt;br /&gt;
3. Client (js, css, tpl, etc) - instances and types. For example my meeple will be like &lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  &amp;lt;div id=&amp;quot;meeple_ff0000_7&amp;quot; class=&amp;quot;meeple meeple_ff0000&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
with .css something like&lt;br /&gt;
  .meeple { background-image: url(img/tokens.png); width: 2em; height: 2em;}&lt;br /&gt;
  .meeple_ff0000 {background-position: 20% 0%;}&lt;br /&gt;
4. Game php - setup and logic. During setup, you have to generate all the pieces and place them in the right positions. Also sometimes you need to reference elements to code the logic (I usually try to encode all rules in the material file as much as possible)&lt;br /&gt;
&lt;br /&gt;
For complex card games, I think it is best to keep all these info and rules in a spreadsheet and generate other files such as material.inc.php.&lt;br /&gt;
See more info below about the design of the individual layers.&lt;br /&gt;
&lt;br /&gt;
== Create Initial Layout and Game Graphics ==&lt;br /&gt;
&lt;br /&gt;
Mentally it is easier to start with the game layout and graphics pieces. Even when nothing is working it gives you moral satisfaction!&lt;br /&gt;
&lt;br /&gt;
There are a few ways how the html could have been generated. You could have started with nothing and generate&lt;br /&gt;
it all by javascript, or you could have started with complete game markup in html and make javascript just hide and move pieces around. BGA framework also provides a third way, which is mix of both, plus a template engine to generate HTML using PHP. The only thing that is really annoying about the template engine is that you cannot put any translatable strings in the template (which means any visible text at all). If you are using the template approach all strings have to be extracted as variables and injected through PHP (.view.php). This page explains the template engine in great detail:[[Game_layout:_view_and_template:_yourgamename.view.php_and_yourgamename_yourgamename.tpl|Template Engine]].&lt;br /&gt;
&lt;br /&gt;
The other disadvantage of the template engine is you cannot run and debug it locally, in the beginning of development it&#039;s a lot faster run off local pages, &lt;br /&gt;
you can do it with some trickery described here [[Tools_and_tips_of_BGA_Studio#Speed_up_CSS_development_and_layout|Tools and Tips for BGA Studio]]&lt;br /&gt;
&lt;br /&gt;
During this step you have to decide what technical solutions you will be using, such as&lt;br /&gt;
* Use inline positioning of all moving pieces, controlled by JS. There are a few classes that already exist in Studio to help with that (see [[Studio#Game_interface_.28Client_side.29|Game Interface - Client Side]]). OR use html/css layout engine to position pieces (my personal choice).&lt;br /&gt;
* Use BGA template engine OR create all ui elements by JS OR manually write or generate complete html markup. The game usually contains 200-300 pieces, it seems wrong but actually its faster to type all of this up in html/css when trying write than debug code for page generator.&lt;br /&gt;
Static HTML markup also means you have to use players color or abstracted player number (such as red is 1, blue is 2) not player id&#039;s anywhere in JS, since player id is dynamic by nature.&lt;br /&gt;
&lt;br /&gt;
Start by creating and mapping all games assets, best way is probably to open rule book on &amp;quot;boardgame contents&amp;quot; page and go through every piece. Every piece of boardgame would have its &amp;quot;print&amp;quot; in multiple files in your game:&lt;br /&gt;
* Some sort of &amp;quot;div&amp;quot; in html, where id of element match id of element in database (easiest way)&lt;br /&gt;
* Css for the element (either unique or for class), usually with background property refering to part of sprite image&lt;br /&gt;
* Entry in material.inc.php referring to static properties of the element, i.e. name, tooltip, rules, etc&lt;br /&gt;
* Entry in .tpl file to represent a static or initial location on the table OR creation template&lt;br /&gt;
&lt;br /&gt;
Here are some specific examples:&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Game Board&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Create entry in .tpl file for the board, it will be static entry as we never need to create this dynamically&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  &amp;lt;div id=&amp;quot;board&amp;quot; class=&amp;quot;board shadow board4p&amp;quot;&amp;gt; ... &amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Create entry in .css file for this board and other board variants (in example below we have 4 ppl board which is diffrent than 2 ppl board)&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
.board {&lt;br /&gt;
	position: relative;&lt;br /&gt;
	width: 980px;&lt;br /&gt;
	height: 433px;&lt;br /&gt;
	margin-bottom: 5px;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.board4p {&lt;br /&gt;
	background-image: url(img/board4p.jpg);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
That would be pretty much it for the board itself, as it does not really need a tooltip so we don&#039;t need entry in material.inc.php&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Game Board Slots&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
These are interactive areas on the board, usually illustrated as such. In most cases you can get away with rectangular shapes, but sometimes you have to create circle or oval shapes (and in really advanced case would be some svg paths). For slots you can do the following:&lt;br /&gt;
&lt;br /&gt;
Entry in material.inc.php&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$this-&amp;gt;token_types = array(&lt;br /&gt;
...&lt;br /&gt;
&#039;slot_action_2&#039; =&amp;gt; array(&lt;br /&gt;
  &#039;type&#039; =&amp;gt; &#039;slot_action&#039;,&lt;br /&gt;
  &#039;name&#039; =&amp;gt; clienttranslate(&amp;quot;2 Gray Track Advancements&amp;quot;),&lt;br /&gt;
  &#039;tooltip&#039; =&amp;gt; clienttranslate(&amp;quot;This action gives you two advancements of gray track. You cannot use this action if you cannot complete all advancements.&amp;quot;),&lt;br /&gt;
  &#039;o&#039;=&amp;gt;&amp;quot;1,0,0,gg&amp;quot;, // automatic rules&lt;br /&gt;
),&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Entry in template inside the &amp;quot;board&amp;quot; div&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
	&amp;lt;div id=&amp;quot;slot_action_2&amp;quot; class=&amp;quot;slot_action_2 slot_action slot_w_1 slot&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Entry in .css with absolute position within the board (its actually better to use percentage - would be easier to scale later)&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
.slot_action_2 {&lt;br /&gt;
	top: 83px;&lt;br /&gt;
	left: 37px;&lt;br /&gt;
}&lt;br /&gt;
.slot_action {&lt;br /&gt;
	position: absolute;&lt;br /&gt;
	width: 46px;&lt;br /&gt;
	height: 26px;&lt;br /&gt;
	padding: 9px 7px 6px 4px;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Meeples&#039;&#039;&#039; - also cards, tokens, other mobile stuff&lt;br /&gt;
&lt;br /&gt;
In CSS these guys will use &amp;quot;sprite&amp;quot; images with transparency, so it will look like this this:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
.meeple {&lt;br /&gt;
	background-image: url(img/tokens.png);&lt;br /&gt;
	width: 25px;&lt;br /&gt;
	height: 25px;&lt;br /&gt;
}&lt;br /&gt;
.meeple_ff0000 { /* red */&lt;br /&gt;
	background-position: 14% 0%;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
As for creation you can either generate them using template (where whole thing wrapped in template block and {COLOR} replace with all possible colors in .view.php&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 &amp;lt;div id=&amp;quot;meeple_{COLOR}_1&amp;quot; class=&amp;quot;meeple meeple_{COLOR} meepleable&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
 &amp;lt;div id=&amp;quot;meeple_{COLOR}_2&amp;quot; class=&amp;quot;meeple meeple_{COLOR} meepleable&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
 ...&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Or you can declare a template js var in .tpl file &lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    var jstpl_mepple = &#039;&amp;lt;div id=&amp;quot;meeple_${color}_${num}&amp;quot; class=&amp;quot;meeple meeple_${color} meepleable&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&#039;; // this is in .tpl file at the bottom&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
and create in js, like this&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 var tokenDiv = this.format_block(&#039;jstpl_mepple&#039;, {&lt;br /&gt;
                                &amp;quot;color&amp;quot; : color,&lt;br /&gt;
                                &amp;quot;num&amp;quot; : i&lt;br /&gt;
                            }); // this in js code somewhere before placing it&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
If you dealing with cards and decks, there are pre-build components that can generate stuff for you.&lt;br /&gt;
&lt;br /&gt;
When do you create dom element matching game element?&lt;br /&gt;
* If you have static layout you create it in .tpl file and its always there, but during initial setup or during notification it moved in proper spot (including &amp;quot;removed from the game&amp;quot; spot)&lt;br /&gt;
* If you dynamically generated pieces you create the element during notification, and sometimes during animation. Also don&#039;t forgot to hook event listener to it if its interactive.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
One of the greatest parts about the web is all client side code can be viewed in your browser, so if you wondering how something is done in another BGA game just load the page and spy on it! In Chrome that would be right click and &amp;quot;Inspect Element&amp;quot;. That would immediately show html of the given element alongside with css used for it (on the right). Another great way to learn is you can add yourself to any BGA project as read only from the project page!&lt;br /&gt;
&lt;br /&gt;
So at the end of this stage you should complete the following (keeping in mind reduced rules/material for first iteration):&lt;br /&gt;
* Create a layout of the game, with positioning of main board, player areas, zones, other supporting areas, etc&lt;br /&gt;
* Create css and html snippets for all game pieces: boards, tokens, meeples, etc. Place them all in initial template (even if they&#039;re not supposed to be visible at start). I.e. create fake player&#039;s hand with cards, put meeples on the board&lt;br /&gt;
* Hook layout to number of players and colors picked by the game and test with multiple players&lt;br /&gt;
* Figure out what you want to display in mini-player boards and hook it up&lt;br /&gt;
* Create material.inc.php and populate with initial values (names, tooltips, rules) for all relevant game elements or classes of elements&lt;br /&gt;
&lt;br /&gt;
If at this time you don&#039;t have graphics yet create pieces with just CSS, you can use shape, background color and object text using css ::after construct to fake the pieces.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[File:Injected_text.png]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Create Database Schema ==&lt;br /&gt;
&lt;br /&gt;
At some point you have to design your game database. Do it sooner then later since it would be harder to change it later, since some&lt;br /&gt;
code decisions would be based on that.&lt;br /&gt;
&lt;br /&gt;
If you have grid-based abstract game use template from reversi, if you have a card game use template from hearts (the cards one also commented out in generated template for your project). The cards database goes with php class called [[Deck]].&lt;br /&gt;
&lt;br /&gt;
In general make it as simple as possible. &lt;br /&gt;
Think about it, your game has 300 pieces (likely less). Using database to store this amount of data is like shooting a mosquito with a tank.&lt;br /&gt;
Anything more complex then one table with 5 columns or two tables will only going to make it harder to develop and not improve performance.&lt;br /&gt;
You can forget about normalising and any fancy stuff you learn about databases in school. String field for a primary key would be as fast as integer when we talking about this size of data. So don&#039;t over-optimize with trying to have integers field that have state based on bitmask!&lt;br /&gt;
&lt;br /&gt;
Also remember that static (non dynamic) information about the game does not need to be stored in the database, that all include everything that does not change, i.e&lt;br /&gt;
all token/card properties such as name, tooltips, &amp;quot;strength&amp;quot;, color, etc. This is stored in material.inc.php and server has access to it from anywhere, as well as client&lt;br /&gt;
if you send it with getAllDatas(). The only reason store some of it in database if it can affect your queries (i.e. type of token).&lt;br /&gt;
&lt;br /&gt;
Usually design process will contain the following steps:&lt;br /&gt;
* Design game model - model that represent your game in progress, such as at any given step you can restore the game from that model&lt;br /&gt;
* Mapping - now map real game to that model&lt;br /&gt;
* Encoding - now represent this model in database and material file with reasonable amount of fields&lt;br /&gt;
&lt;br /&gt;
Example: &#039;&#039;&#039;The card game&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
* In real word to &amp;quot;save&amp;quot; the game we take a picture a play area, save cards from it, then put away draw deck, discard and hand of each player separately and mark it, also we will record current scoring (if any) and who&#039;s turn was it&lt;br /&gt;
* Framework handles state machine transition, so you don&#039;t have to worry about database design for that (i.e. who&#039;s turn it is, what phase of the game we are at, you still have to design it but as part of state machine step)&lt;br /&gt;
* Also framework supports basic player information, color, order around the table, basic scoring, etc, so you don&#039;t have to worry about it either&lt;br /&gt;
* The only thing you need in your database is state of the &amp;quot;board&amp;quot;, which is &amp;quot;where each pieces is, and in what state&amp;quot;, or (position,rotation) pair.&lt;br /&gt;
* The card state is very simple, it&#039;s usually &amp;quot;face up/face down&amp;quot;, &amp;quot;tapped/untapped&amp;quot;, &amp;quot;right side up/up side down&amp;quot;&lt;br /&gt;
* As position go we never need real x,y,z. We need to know what &amp;quot;zone&amp;quot; card was, and depending on the zone it may sometimes need an extra &amp;quot;z&amp;quot; or &amp;quot;x&amp;quot; as card order. The zone position itself usually static or irrelevant.&lt;br /&gt;
* So our model is: we have cards, which have some attributes, at any given point in time they belong to a &amp;quot;zone&amp;quot;, and can also have order and state&lt;br /&gt;
* Now for mapping we should consider what info changes and what info is static, static info is always candidate for material file or html&lt;br /&gt;
* For dynamic stuff we should try to reduce amount of fields we need, i.e. we need a field for card, so its one, we need to know what zone cards belong to, its 2, and we have possible few other fields, but if you look closely at you game you may find out that most of the zone only need one attribute at a time, i.e. draw pile always have cards face  down, hand always face up, also for hand and discard order does not matter at all (but for draw it does matter). So in majority of cases we can get away with one single extra integer field representing state or order&lt;br /&gt;
* In real database both card and zone will be integers as primary keys referring to additional tables, but in our case its total overkill, so they can be strings as easily&lt;br /&gt;
&lt;br /&gt;
You can also use cards database schema and [[Deck]] implementation for most purposes (even you not dealing with cards).&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
CREATE TABLE IF NOT EXISTS `card` (&lt;br /&gt;
  `card_id` int(10) unsigned NOT NULL AUTO_INCREMENT,&lt;br /&gt;
  `card_type` varchar(16) NOT NULL,&lt;br /&gt;
  `card_type_arg` int(11) NOT NULL,&lt;br /&gt;
  `card_location` varchar(16) NOT NULL,&lt;br /&gt;
  `card_location_arg` int(11) NOT NULL,&lt;br /&gt;
  PRIMARY KEY (`card_id`)&lt;br /&gt;
) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=1 ;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Another Example: &#039;&#039;&#039;The euro game&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
See details on database design for euro game at [[BGA_Studio_Cookbook#Database_for_The_euro_game]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
So the piece mapping for non-grid based &lt;br /&gt;
games can be in most case represented by (string: token_key, string: location, int: state), example of such database schema can be found here:&lt;br /&gt;
[https://github.com/elaskavaia/bga-sharedcode/blob/master/dbmodel.sql dbmodel.sql] and class implementing access to it here [https://github.com/elaskavaia/bga-sharedcode/blob/master/modules/tokens.php tokens.php].&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
CREATE TABLE IF NOT EXISTS `token` (&lt;br /&gt;
  `token_key` varchar(32) NOT NULL,&lt;br /&gt;
  `token_location` varchar(32) NOT NULL,&lt;br /&gt;
  `token_state` int(10),&lt;br /&gt;
  PRIMARY KEY (`token_key`)&lt;br /&gt;
) ENGINE=InnoDB DEFAULT CHARSET=utf8;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
See [[Game database model: dbmodel.sql]] for details about editing the file.&lt;br /&gt;
&lt;br /&gt;
Note: the simpler the database is the less debugging of db issues you have to deal with including database migration. The tokens database above - if you use it you never have to worry about migration because you don&#039;t need extra tables in 95% of the games.&lt;br /&gt;
Here are some example of how real games are mapped to such database:&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Chess&#039;&#039;&#039; &lt;br /&gt;
&lt;br /&gt;
- chess is grid base game and normally you would use positional columns, but just for the sake of argument, the chess game will look like this&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+token&lt;br /&gt;
! token_key&lt;br /&gt;
! token_location&lt;br /&gt;
! token_state&lt;br /&gt;
|-&lt;br /&gt;
|Q_white&lt;br /&gt;
|f3&lt;br /&gt;
|0&lt;br /&gt;
|-&lt;br /&gt;
|P_black_2&lt;br /&gt;
|c6&lt;br /&gt;
|0&lt;br /&gt;
|-&lt;br /&gt;
|K_black&lt;br /&gt;
|e8&lt;br /&gt;
|1&lt;br /&gt;
|}&lt;br /&gt;
And the state in this case indicated that kind was moved for example (which means castling cannot be performed)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Classic card game&#039;&#039;&#039; &lt;br /&gt;
&lt;br /&gt;
Lets pretend we need 2 decks for that game&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+token&lt;br /&gt;
! token_key&lt;br /&gt;
! token_location&lt;br /&gt;
! token_state&lt;br /&gt;
|-&lt;br /&gt;
|Q_spades_1&lt;br /&gt;
|hand_ff0000&lt;br /&gt;
|0 /* state not used for hand */&lt;br /&gt;
|-&lt;br /&gt;
|10_hearts_2&lt;br /&gt;
|tableau_ff0000&lt;br /&gt;
|2 /* position */&lt;br /&gt;
|-&lt;br /&gt;
|10_hearts_1&lt;br /&gt;
|tableau_common&lt;br /&gt;
|1 /* face down */&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Eminent Domain (card game)&#039;&#039;&#039; &lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+token&lt;br /&gt;
! token_key&lt;br /&gt;
! token_location&lt;br /&gt;
! token_state&lt;br /&gt;
|-&lt;br /&gt;
|card_tech_23&lt;br /&gt;
|hand_ff0000&lt;br /&gt;
|0 /* state not used for hand */&lt;br /&gt;
|-&lt;br /&gt;
|card_planet_19&lt;br /&gt;
|tableau_ff0000&lt;br /&gt;
|1 /* face up */&lt;br /&gt;
|-&lt;br /&gt;
|reource_s_22 /* silicon */&lt;br /&gt;
|card_planet_19&lt;br /&gt;
|2 /*  production state */&lt;br /&gt;
|-&lt;br /&gt;
|fighter_F_1&lt;br /&gt;
|tableau_ff0000&lt;br /&gt;
|0&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
You can also look at other games that use Tokens database and access layer: Nippon, Dungeon Petz, Lewis &amp;amp; Clark, Battleship, Russian Railroads, Khronos&lt;br /&gt;
&lt;br /&gt;
== Implement Game Setup ==&lt;br /&gt;
&lt;br /&gt;
Once you have your database schema you can do a proper game setup. Usually you open rulebook on the &amp;quot;Game Setup&amp;quot; page&lt;br /&gt;
and implement these step by step populating the database (using db access API).&lt;br /&gt;
Game initialization is performed in php method setupNewGame, this method is called once when game table is created.&lt;br /&gt;
Game notifications cannot be sent during this time.&lt;br /&gt;
&lt;br /&gt;
It very hard to debug this method, so this is how we recommend to structure it:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
protected function setupNewGame($players, $options = []) { &lt;br /&gt;
   &lt;br /&gt;
   // here is some generate code from template LEAVE IT UNTOUCHED&lt;br /&gt;
   ...&lt;br /&gt;
&lt;br /&gt;
   $this-&amp;gt;initTables(); // this is YOUR new method&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
function initTables() {&lt;br /&gt;
       try {&lt;br /&gt;
            $players = $this-&amp;gt;loadPlayersBasicInfos();&lt;br /&gt;
            // code the function&lt;br /&gt;
            $this-&amp;gt;activeNextPlayer(); // just in case so its not 0&lt;br /&gt;
            $this-&amp;gt;initStats(); // to be coded&lt;br /&gt;
            // Setup the initial game situation here&lt;br /&gt;
            $this-&amp;gt;initGameTables(); // to be coded&lt;br /&gt;
            // beggining of the turn for active player (if player state if first state)&lt;br /&gt;
            $player_id = $this-&amp;gt;getActivePlayerId();&lt;br /&gt;
            $this-&amp;gt;incStat(1, &#039;turns_number&#039;, $player_id);&lt;br /&gt;
            $this-&amp;gt;incStat(1, &#039;turns_number&#039;);&lt;br /&gt;
       } catch ( Exception $e ) {&lt;br /&gt;
           // logging does not actually work in game init :(&lt;br /&gt;
           // but if you calling from php chat it will work&lt;br /&gt;
           $this-&amp;gt;error(&amp;quot;Fatal error while creating game&amp;quot;);&lt;br /&gt;
           $this-&amp;gt;dump(&#039;err&#039;, $e);&lt;br /&gt;
       }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
For more tricks debugging this See [https://en.doc.boardgamearena.com/Practical_debugging#Debugging_setupNewGame Debugging setupNewGame]&lt;br /&gt;
&lt;br /&gt;
For the init stats, its likely that all of the are int and you can just use this genetic initializer, but your stats have to start with game_ prefix (verbatim):&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    public function initStats()&lt;br /&gt;
    {&lt;br /&gt;
        // INIT GAME STATISTIC&lt;br /&gt;
        $all_stats = $this-&amp;gt;getStatTypes();&lt;br /&gt;
        $player_stats = $all_stats[&#039;player&#039;];&lt;br /&gt;
        // auto-initialize all stats that starts with game_&lt;br /&gt;
        // we need a prefix because there is some other system stuff&lt;br /&gt;
        foreach ($player_stats as $key =&amp;gt; $value) {&lt;br /&gt;
            if (str_starts_with($key, &#039;game_&#039;)) {&lt;br /&gt;
                $this-&amp;gt;initStat(&#039;player&#039;, $key, 0);&lt;br /&gt;
            }&lt;br /&gt;
            if ($key === &#039;turns_number&#039;) {&lt;br /&gt;
                $this-&amp;gt;initStat(&#039;player&#039;, $key, 0);&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
        $table_stats = $all_stats[&#039;table&#039;];&lt;br /&gt;
        foreach ($table_stats as $key =&amp;gt; $value) {&lt;br /&gt;
            if (str_starts_with($key, &#039;game_&#039;)) {&lt;br /&gt;
                $this-&amp;gt;initStat(&#039;table&#039;, $key, 0);&lt;br /&gt;
            }&lt;br /&gt;
            if ($key === &#039;turns_number&#039;) {&lt;br /&gt;
                $this-&amp;gt;initStat(&#039;table&#039;, $key, 0);&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
As for init game tables - if you have SQL layer you can use it to initialize everything, if not - the best would be to push everything in php array and then do one inset at the end (after all the fiddling and shuffling).&lt;br /&gt;
&lt;br /&gt;
For example for the token database above, I will push all data into array, then at the end run insert, i.e.&lt;br /&gt;
&lt;br /&gt;
        $values=[]; &lt;br /&gt;
        $values [] = &amp;quot;(&#039;meeple_ff0000_1&#039;, &#039;home_ff0000&#039;, 0)&amp;quot;; // this is actually string not array&lt;br /&gt;
        ...&lt;br /&gt;
        $sql = &amp;quot;INSERT INTO tokens (token_id, place_id, state) VALUES &amp;quot; . implode($values, &#039;,&#039;);&lt;br /&gt;
        $this-&amp;gt;DbQuery($sql);&lt;br /&gt;
&lt;br /&gt;
== Implement One time game model synchronisation ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Now at any point in the game we need to make sure that database information can be reflected back in UI, so we fix getAllDatas function&lt;br /&gt;
to return all possible data we need to reconstruct the game. The template for getAllDatas already taking care of player info, but you &lt;br /&gt;
have to alter it to return all other data from database visible to the &amp;quot;current&amp;quot; player.&lt;br /&gt;
&lt;br /&gt;
After that on the client side we should display this data, so in your .js file in setup function (which is the receiver of getAllDatas) you add calls that handle data send by server, usually by calling animation function such as &amp;quot;placeToken&amp;quot; or &amp;quot;placeCard&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
So this is roughtly what you need to include in getAllDatas():&lt;br /&gt;
&lt;br /&gt;
* Extra player info &lt;br /&gt;
* Material file variables, unfortunately they are not included automatically. Note - I strongly recommend using only one variable for generic data information, such as $this-&amp;gt;token_types. If you start splitting it i.e. card_types, meeple_types, building_types - it very hard to deal with this programmatically it will be lots of switches. Also call it the same as in php - otherwise its really hard to correlate.&lt;br /&gt;
* Game options (if you know how to access them on cient without passing via getAllData() edit this wiki). Example has generic code to pass all options, but you can use custom individual options&lt;br /&gt;
* Dump of database tables filtered by current player view&lt;br /&gt;
* To be fancy you can also include php constans so you can access them in js as well, example not included&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    protected function getAllDatas() {&lt;br /&gt;
        $result = [];&lt;br /&gt;
&lt;br /&gt;
        // 1. Get information about players&lt;br /&gt;
        // Note: you can retrieve some extra field you added for &amp;quot;player&amp;quot; table in &amp;quot;dbmodel.sql&amp;quot; if you need it.&lt;br /&gt;
        // would have been much better if its just * but we not looking for easy solutions here! so it all have to be aliases&lt;br /&gt;
        $sql = &amp;quot;SELECT player_id id, player_score score, player_no no FROM player&amp;quot;; // note - the framework will all bunch of more fields&lt;br /&gt;
        $result [&#039;players&#039;] = self::getCollectionFromDb($sql);&lt;br /&gt;
&lt;br /&gt;
        // 2. Material data&lt;br /&gt;
        $result[&#039;token_types&#039;] = $this-&amp;gt;token_types;&lt;br /&gt;
        // 3. Game options&lt;br /&gt;
        $table_options = $this-&amp;gt;getTableOptions();&lt;br /&gt;
        $result [&#039;table_options&#039;] = [];&lt;br /&gt;
        foreach ( $table_options as $option_id =&amp;gt; $option ) {&lt;br /&gt;
            $value = 0;&lt;br /&gt;
            if (array_key_exists($option_id, $this-&amp;gt;gamestate-&amp;gt;table_globals)) {&lt;br /&gt;
                $value = (int) $this-&amp;gt;gamestate-&amp;gt;table_globals [$option_id];&lt;br /&gt;
            }&lt;br /&gt;
            $result [&#039;table_options&#039;] [$option_id] = $option;&lt;br /&gt;
            $result [&#039;table_options&#039;] [$option_id] [&#039;value&#039;] = $value;&lt;br /&gt;
        }&lt;br /&gt;
        // 4. Rest of the database filtered by current player&lt;br /&gt;
        $current_player_id = self::getCurrentPlayerId(); // !! We must only return informations visible by this player !!&lt;br /&gt;
        $result [&#039;tokens&#039;] = [];&lt;br /&gt;
        $players_basic = $this-&amp;gt;loadPlayersBasicInfos();&lt;br /&gt;
        foreach ( $players_basic as $player_id =&amp;gt; $player_info ) {&lt;br /&gt;
            $color = $player_info [&#039;player_color&#039;];&lt;br /&gt;
            // tableau is public info&lt;br /&gt;
            $result [&#039;tokens&#039;]+=$this-&amp;gt;tokens-&amp;gt;getTokensInLocation(&amp;quot;tableau_$color&amp;quot;); // this is sql access layer for tokens table but it can be just raw SQL query with getCollectionFromDb kind of call&lt;br /&gt;
            //  hand if private info&lt;br /&gt;
            if ($current_player_id==$player_id) {&lt;br /&gt;
                $result [&#039;tokens&#039;]+=$this-&amp;gt;tokens-&amp;gt;getTokensInLocation(&amp;quot;hand_$color&amp;quot;);&lt;br /&gt;
            } else {&lt;br /&gt;
                $result [&#039;counters&#039;][&amp;quot;hand_$color&amp;quot;]=$this-&amp;gt;tokens-&amp;gt;countTokensInLocation(&amp;quot;hand_$color&amp;quot;);&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
        $result [&#039;counters&#039;][&amp;quot;deck]=$this-&amp;gt;tokens-&amp;gt;countTokensInLocation(&amp;quot;deck&amp;quot;);&lt;br /&gt;
        $result [&#039;counters&#039;][&amp;quot;discard&amp;quot;]=$this-&amp;gt;tokens-&amp;gt;countTokensInLocation(&amp;quot;discard&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
        return $result;&lt;br /&gt;
    }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Create State Machine ==&lt;br /&gt;
&lt;br /&gt;
Now you need to create a game state machine. &lt;br /&gt;
&lt;br /&gt;
The state handling spread across 4 files, so you have to make sure all the pieces are connected together.&lt;br /&gt;
The state machine states.inc.php defines all the states, and function handlers on php side in a form of string,&lt;br /&gt;
and if any of these functions are not implemented it would be very hard to debug because it will break in random places.&lt;br /&gt;
&lt;br /&gt;
Please first watch this again [http://www.slideshare.net/boardgamearena/bga-studio-focus-on-bga-game-state-machine  BGA game state machine]&lt;br /&gt;
and then please read [[Your game state machine: states.inc.php]].&lt;br /&gt;
&lt;br /&gt;
Now the state machine should be relatively simple. If you find yourself with machine with more than 20 states its probably not the way to go.&lt;br /&gt;
Not all the player interactions need separate states, a lot of things can be implemented directly on client, i.e. if your player need to select&lt;br /&gt;
a reward token, which offers choice of resource, instead of two states on server just have one state on server and possible few states on client (client side states)&lt;br /&gt;
to collect this info.&lt;br /&gt;
&lt;br /&gt;
It is important to implement proper state handling on the client, usually it results in big switch in onUpdateActionButtons method.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
			onUpdateActionButtons: function(stateName, args) {&lt;br /&gt;
				console.log(&#039;onUpdateActionButtons: &#039; + stateName + &amp;quot; &amp;quot; + this.isCurrentPlayerActive() + &amp;quot; args:&amp;quot;, args);&lt;br /&gt;
				if (!this.isCurrentPlayerActive()) return;&lt;br /&gt;
				&lt;br /&gt;
				switch (stateName) {&lt;br /&gt;
					case &#039;playerTurn&#039;:&lt;br /&gt;
					        dojo.query(&#039;.card&#039;).addClass(&#039;active_slot&#039;); // activate board elements, when using static connector, see user input below&lt;br /&gt;
                                                // add buttons&lt;br /&gt;
						this.addActionButton(&#039;button_pass&#039;, _(&#039;Pass&#039;), () =&amp;gt; {&lt;br /&gt;
							this.bgaPerformAction(&#039;pass&#039;);&lt;br /&gt;
						});&lt;br /&gt;
                                        // case...&lt;br /&gt;
				}&lt;br /&gt;
&lt;br /&gt;
				if (this.on_client_state &amp;amp;&amp;amp; !$(&#039;button_cancel&#039;)) {&lt;br /&gt;
					this.addActionButton(&#039;button_cancel&#039;, _(&#039;Cancel&#039;), &#039;cancelLocalStateEffects&#039;, 0, 0, &#039;gray&#039;);&lt;br /&gt;
					this.addTooltip(&#039;button_cancel&#039;, _(&amp;quot;This means cancel current action and start thinking&amp;quot;), &#039;&#039;);&lt;br /&gt;
				}&lt;br /&gt;
			},&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
I keep onLeavingState pretty generic (and onEnteringState just for logging)&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
                onLeavingState: function (stateName) {&lt;br /&gt;
                    console.log(&#039;Leaving state: &#039; + stateName);&lt;br /&gt;
                    dojo.query(&#039;.active_slot&#039;).removeClass(&#039;active_slot&#039;);&lt;br /&gt;
                    dojo.query(&#039;.selected&#039;).removeClass(&#039;selected&#039;);&lt;br /&gt;
                },			&lt;br /&gt;
				&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Handle Turn Order ==&lt;br /&gt;
&lt;br /&gt;
If your game goes in clockwise order in natural sitting position nothing really needed you just use standard API and you are good. However if position is complecated&lt;br /&gt;
it may require some trickery.&lt;br /&gt;
&lt;br /&gt;
Usually turn order is done by &amp;quot;game state&amp;quot; (see state machine above). Basically it would be two choices:&lt;br /&gt;
* Turn order depends on game situation (such as we take player with highest number of red cubes)&lt;br /&gt;
* Turn order is custom and assign on previos step - i.e. we not playing in clockwise order anymore. In this case you either need to extend player table with new order info (CANNOT use player_no column) or use order markers that come with game (i.e. marker_ff0000 on position_1). In this we can build player array in right order and pick next player based on previous player using existing helper function such as $this-&amp;gt;createNextPlayerTable($player_ids)&lt;br /&gt;
&lt;br /&gt;
Handling turn order would go to the game state which is usually follows active player state.&lt;br /&gt;
&lt;br /&gt;
== Hook User Input  ==&lt;br /&gt;
&lt;br /&gt;
This step can be done before or after some of the server steps, or you go in iterations switching back and forward until you get it done, up to you.&lt;br /&gt;
&lt;br /&gt;
Usually all pieces will be hooked to onclick during JS &amp;quot;setup&amp;quot; method, in addition if you create elements during server notification they have to be hooked up at that time.&lt;br /&gt;
&lt;br /&gt;
Also its a good idea to give player a visual cues on what game elements are clickable now, usually it will be a style, such as &amp;quot;active_slot&amp;quot;, with visual effect of white dashed outline (outline is better then border, because border changes will make piece slightly move since it changes the size) or box-shadow (i.e. neon glow), that part is done in onUpdateActionsButtons (see above)&lt;br /&gt;
&lt;br /&gt;
So classic is static handlers, means handler is added in setup method using framework connect function:&lt;br /&gt;
&lt;br /&gt;
  this.connect( $(&#039;my_element&#039;), &#039;onclick&#039;, &#039;onClickOnMyElement&#039; );&lt;br /&gt;
&lt;br /&gt;
This is what is advertized in tutorials, however this is best suited for static html model - where elements are not deleted and recreated. When elements created dinamically if you using this method please be aware of memory leaks - this&lt;br /&gt;
method stores the pointer to dom element in arrays of handlers (to be able to disconnect later), but if element is deleted you must call this.disconnect before deleting with same node reference, or it will leak.&lt;br /&gt;
&lt;br /&gt;
If you using this method your handlers usually look like big ugly switch because it usually depending on state it will do right thing or deny action, typically it will look this this:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
                onCard: function(event) {&lt;br /&gt;
                    dojo.stopEvent(event);&lt;br /&gt;
                    var id = event.currentTarget.id;&lt;br /&gt;
                    console.trace(&amp;quot;on slot &amp;quot; + id);&lt;br /&gt;
                    if (!id) return null;&lt;br /&gt;
                    // check player is active&lt;br /&gt;
                    if (!this.isCurrentPlayerActive()) {&lt;br /&gt;
                        this.showMessage(__(&amp;quot;lang_mainsite&amp;quot;, &amp;quot;This is not your turn&amp;quot;), &amp;quot;error&amp;quot;);&lt;br /&gt;
                        return false;&lt;br /&gt;
                    }&lt;br /&gt;
                    // check node is marked with &amp;quot;active_slot&amp;quot; class (class name is whatever you want)&lt;br /&gt;
                    if (!dojo.hasClass(id, &#039;active_slot&#039;)) {&lt;br /&gt;
                        this.showMoveUnauthorized();&lt;br /&gt;
                        return false;&lt;br /&gt;
                    }&lt;br /&gt;
                    switch (this.gamedatas.gamestate.name) {&lt;br /&gt;
                        case &#039;playerTurn&#039;: // in this case we directly sending data to the server&lt;br /&gt;
                            this.bgaPerformAction(&#039;playCard&#039;, { id }); // note that this wrapper also calls &#039;checkAction&#039; on action parameter&lt;br /&gt;
                            return true;&lt;br /&gt;
                        case &#039;playerDiscard&#039;:  // in this case we need to collect more information, so we using cient state for that&lt;br /&gt;
                            dojo.addClass(id,&#039;selected&#039;); // mark card&lt;br /&gt;
                            this.setClientState(&amp;quot;client_playerTurnSelectBonus&amp;quot;, {&lt;br /&gt;
                                descriptionmyturn: _(&#039;${you} must select bonus for discard&#039;),&lt;br /&gt;
                            });&lt;br /&gt;
                            return true;&lt;br /&gt;
                        default:&lt;br /&gt;
                            this.showMoveUnauthorized();&lt;br /&gt;
                            return false;&lt;br /&gt;
                    }&lt;br /&gt;
                },&lt;br /&gt;
&lt;br /&gt;
You can also manage listeners yourself (vanilla event listeners or dojo). In this case be aware of registering double listener. See more example in [[Game_interface_logic:_yourgamename.js#Players_input|Player&#039;s Input]].&lt;br /&gt;
&lt;br /&gt;
Alternative to static handler are dynamic handlers which are only installed on elements that are active for specific game state, given the example above we would register the listeners in playerTurn state, i.e.&lt;br /&gt;
in onUpdateActionButtons for playerTurn:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
   			dojo.query(&#039;.card&#039;).forEach((node) =&amp;gt; {&lt;br /&gt;
			        dojo.addClass(node, &#039;active_slot&#039;);&lt;br /&gt;
			        dojo.addClass(node, &#039;temp_click_handler&#039;);&lt;br /&gt;
			        this.connect(node, &#039;click&#039;, event =&amp;gt; this.bgaPerformAction(&#039;playCard&#039;, { id: event.currentTarget.id }));&lt;br /&gt;
			});&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Above we did not need to do the heavy validation because we only presumably added handler in right state to right node and right active player (and removed correctly in between!)&lt;br /&gt;
&lt;br /&gt;
And in onLeavingState we will disconnect all of them (important!):&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
   			dojo.query(&#039;.temp_click_handler&#039;).forEach((node) =&amp;gt; {&lt;br /&gt;
			        dojo.removeClass(node, &#039;active_slot&#039;);&lt;br /&gt;
			        dojo.removeClass(node, &#039;temp_click_handler&#039;);&lt;br /&gt;
			        this.disconnect(node, &#039;click&#039;);&lt;br /&gt;
			});&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
When user clicks on something, client sends an ajax call to server, server processes it and updates database, server sends&lt;br /&gt;
notification in response, client hooks animations to server notification. See [[Game_interface_logic:_yourgamename.js#Notifications|JS Notifications]].&lt;br /&gt;
&lt;br /&gt;
Exception to this is client states, if you need to process two step user interaction such as select meeple, place meeple, you may want &lt;br /&gt;
to avoid sending data to server until step is complete (which may involve direct client side animation). See [[BGA_Studio_Cookbook#Multi_Step_Interactions:_Select_Worker.2FPlace_Worker_-_Using_Selection|Multi-Step Interactions]]&lt;br /&gt;
&lt;br /&gt;
Part of the sending notifications would be to update player&#039;s scoring, BGA uses standard control for score (on JS side), see [[Game_interface_logic:_yourgamename.js#Update_players_score|Update Player&#039;s Score]].&lt;br /&gt;
&lt;br /&gt;
In BGA there is only two ways interact with the server (officially)&lt;br /&gt;
* Initial data dump - when JS client starts it gets all current data via setup() method&lt;br /&gt;
* Game actions - bgaPerformAction/ajaxcall from client, it returns error or ok (not data), then server send butch of notifications to client&lt;br /&gt;
&lt;br /&gt;
Note current ajaxcall is super vebosy, bgaPerformAction should be used instead.&lt;br /&gt;
&lt;br /&gt;
When you insert a single action you have to update multiples files:&lt;br /&gt;
* in ggg.js add ajaxcall, i.e. something like &lt;br /&gt;
  this.addActionButton(&#039;pass&#039;, _(&#039;Pass&#039;), () =&amp;gt; this.bgaPerformAction(&#039;pass&#039;));&lt;br /&gt;
* in states.php - add action &#039;pass&#039; to list of possible actions&lt;br /&gt;
  &#039;possibleactions&#039; =&amp;gt; [&#039;pass&#039;,&#039;playCard&#039;]&lt;br /&gt;
* in action.php - add action hander, see https://en.doc.boardgamearena.com/Players_actions:_yourgamename.action.php&lt;br /&gt;
* in game.php - add action hander, there you must do the following&lt;br /&gt;
** call checkAction to validate the action&lt;br /&gt;
** possible do more game specific check to validate what player doing is legal (even its not possible from your js side - player can cheat - not allow that)&lt;br /&gt;
** do some database maniplations, using access api&lt;br /&gt;
** send notifications - this is the &amp;quot;reply&amp;quot; for action&lt;br /&gt;
** transition to new state (it very rare that  user will remain in the same state, except for multi-active states)&lt;br /&gt;
* back to ggg.js add notification subsciption and notification handler (two separate things)&lt;br /&gt;
&lt;br /&gt;
== Implement Notification handling and Animation ==&lt;br /&gt;
&lt;br /&gt;
To handle notification you have to subscribe to it and implement the handlers, see [[Game_interface_logic:_yourgamename.js#Notifications|JS Notifications]].&lt;br /&gt;
&lt;br /&gt;
You can play with animation effects you want put in place, in general all the pieces that move in real game should be moving, such as meeples, resources tokens/cubes, cards, vp tokens. &lt;br /&gt;
Regular piece animation is provided by BGA framework, but if you use html layout positioning not inline positioning you have to remove absolute positions (inline position styling) after each move. The set of functions for relative position token animation can found in https://github.com/elaskavaia/bga-sharedcode/blob/master/sharedcode.js &lt;br /&gt;
&lt;br /&gt;
If you read [http://www.slideshare.net/boardgamearena/bga-studio-guidelines BGA developers guidelines] you know that you should not get carried away with animation, you are creating a board game not a video game... That also applies to sound effects (in general, you should not use any sounds effects beside already provided by framework).&lt;br /&gt;
&lt;br /&gt;
See  [[Game_interface_logic:_yourgamename.js#Access_and_manipulate_the_DOM|Animation and DOM Manipulation]] for JS reference.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Wrap Up ==&lt;br /&gt;
&lt;br /&gt;
* Implement game progression (getGameProgression() in php)&lt;br /&gt;
* Implement Zombie turn  (zombieTurn() in php)&lt;br /&gt;
* Define and implemented some meaningful statistics for your game (i.e. total points, point from source A, B, C...)&lt;br /&gt;
* The games logs should explain what happened if player was not looking&lt;br /&gt;
* You need to implemented tiebreaking (using aux score field) and updated tiebreaker description in meta-data&lt;br /&gt;
* Make sure all UI strings are marked for translation&lt;br /&gt;
* UI elements which are images (i.e. tokens, cards) should have tooltips&lt;br /&gt;
&lt;br /&gt;
== Alpha ==&lt;br /&gt;
When you think you game is completely working there is still bunch of stuff you have to do/check before telling admin that game is ready, please go though this [[Pre-release checklist]].&lt;br /&gt;
&lt;br /&gt;
If you think its completely ready, create a build and click on the &amp;quot;Request ALPHA status&amp;quot; button and admins will check your game and push it to alpha.&lt;br /&gt;
&lt;br /&gt;
Finally, visit the game page for your alpha game (https://boardgamearena.com/gamepanel?game=…) to add the following information if you can:&lt;br /&gt;
* Links to the rules (in multiple languages if available).&lt;br /&gt;
* Links to teaching videos.&lt;br /&gt;
* In the &amp;quot;On the web&amp;quot; section, links to:&lt;br /&gt;
** The official website for the game (if there is one).&lt;br /&gt;
** The BoardGameGeek page for the game.&lt;br /&gt;
* Consider writing a summary of the rules.&lt;br /&gt;
&lt;br /&gt;
Note: later can be done by community members, you don&#039;t actually have to do it yourself&lt;br /&gt;
&lt;br /&gt;
== Level Up ==&lt;br /&gt;
&lt;br /&gt;
When you successfully created a basic game and you want more, it&#039;s time to make it fancy!&lt;br /&gt;
&lt;br /&gt;
* Add game extentions and variants using gameoptions file&lt;br /&gt;
* Add user preferences for customizations&lt;br /&gt;
* Use theming! That involves replacing hardwood background, changing tooltips, using different sounds, different fonts, changing state prompt and logs&lt;br /&gt;
* You can use fancy scoring board at the end of game instead of default nothing&lt;br /&gt;
* And finally super cool dice rolling, card flipping and victory points evaporating effects&lt;br /&gt;
&lt;br /&gt;
[[Category:Studio]]&lt;/div&gt;</summary>
		<author><name>Sguzzer Gunayer</name></author>
	</entry>
	<entry>
		<id>https://en.doc.boardgamearena.com/index.php?title=Game_material_description:_material.inc.php&amp;diff=22586</id>
		<title>Game material description: material.inc.php</title>
		<link rel="alternate" type="text/html" href="https://en.doc.boardgamearena.com/index.php?title=Game_material_description:_material.inc.php&amp;diff=22586"/>
		<updated>2024-09-15T10:24:58Z</updated>

		<summary type="html">&lt;p&gt;Sguzzer Gunayer: /* Adjusting material */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Studio_Framework_Navigation}}&lt;br /&gt;
&lt;br /&gt;
== Overview ==&lt;br /&gt;
This PHP file describes all the material of your game.&lt;br /&gt;
&lt;br /&gt;
This file is included by the constructor of your main game logic (yourgame.game.php), and then the variables defined here are accessible everywhere in your game logic file (and also view.php file).&lt;br /&gt;
&lt;br /&gt;
Using material.inc.php makes your PHP logic file smaller and clean. Normally you put ALL static information about your cards, tokens, tiles, etc in that file which do not change. Do not store static info in database.&lt;br /&gt;
&lt;br /&gt;
== Definition ==&lt;br /&gt;
Example from &amp;quot;Eminent Domain&amp;quot;: &lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$this-&amp;gt;token_types = [&lt;br /&gt;
 &#039;card_role_survey&#039; =&amp;gt; [&lt;br /&gt;
   &#039;type&#039; =&amp;gt; &#039;card_role&#039;,&lt;br /&gt;
   &#039;name&#039; =&amp;gt; clienttranslate(&amp;quot;Survey&amp;quot;),&lt;br /&gt;
   &#039;tooltip&#039; =&amp;gt; clienttranslate(&amp;quot;ACTION: Draw 2 Cards&amp;lt;br/&amp;gt;&amp;lt;br/&amp;gt;ROLE: Look at &amp;lt;div class=&#039;icon survey&#039;&amp;gt;&amp;lt;/div&amp;gt; - 1 planet cards, keep 1&amp;lt;br/&amp;gt; &amp;lt;span class=&#039;yellow&#039;&amp;gt;Leader:&amp;lt;/span&amp;gt; Look at 1 additional card&amp;quot;),&lt;br /&gt;
   &#039;b&#039;=&amp;gt;0,&lt;br /&gt;
   &#039;p&#039;=&amp;gt;&#039;&#039;,&lt;br /&gt;
   &#039;i&#039;=&amp;gt;&#039;S&#039;,&lt;br /&gt;
   &#039;v&#039;=&amp;gt;0,&lt;br /&gt;
   &#039;a&#039;=&amp;gt;&#039;dd&#039;,&lt;br /&gt;
   &#039;r&#039;=&amp;gt;&#039;S&#039;, &lt;br /&gt;
   &#039;l&#039;=&amp;gt;&#039;v&#039;,&lt;br /&gt;
  ],&lt;br /&gt;
&lt;br /&gt;
 &#039;card_tech_1_51&#039; =&amp;gt; [&lt;br /&gt;
   &#039;type&#039; =&amp;gt; &#039;tech&#039;,&lt;br /&gt;
   &#039;name&#039; =&amp;gt; clienttranslate(&amp;quot;Improved Trade&amp;quot;),&lt;br /&gt;
   &#039;b&#039; =&amp;gt; 3,&lt;br /&gt;
   &#039;p&#039; =&amp;gt; &#039;E&#039;,&lt;br /&gt;
   &#039;i&#039; =&amp;gt; &#039;TP&#039;,&lt;br /&gt;
   &#039;v&#039; =&amp;gt; 0,&lt;br /&gt;
   &#039;a&#039; =&amp;gt; &#039;i&#039;,&lt;br /&gt;
   &#039;side&#039; =&amp;gt; 0,&lt;br /&gt;
   &#039;tooltip&#039; =&amp;gt; clienttranslate(&amp;quot;Collect 1 Influence from the supply.&amp;quot;),&lt;br /&gt;
 ],&lt;br /&gt;
&lt;br /&gt;
...&lt;br /&gt;
];&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
So this defines all info about cards, including types, names, tooltips (to be show on client), rules, payment cost, etc.&lt;br /&gt;
&lt;br /&gt;
You can also define PHP constants that can be used in material file and game.php file:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
if (!defined(&#039;TAPESTRY&#039;)) { // guard since this included multiple times&lt;br /&gt;
    define(&amp;quot;TAPESTRY&amp;quot;, 0);&lt;br /&gt;
    define(&amp;quot;TRACK_EXPLORATION&amp;quot;, 1);&lt;br /&gt;
    define(&amp;quot;TRACK_SCIENCE&amp;quot;, 2);&lt;br /&gt;
    define(&amp;quot;TRACK_MILITARY&amp;quot;, 3);&lt;br /&gt;
    define(&amp;quot;TRACK_TECHNOLOGY&amp;quot;, 4);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Access ==&lt;br /&gt;
&lt;br /&gt;
=== Data fields ===&lt;br /&gt;
To access this in PHP side:&lt;br /&gt;
  $type = $this-&amp;gt;token_types[&#039;card_tech_1_51&#039;][&#039;type&#039;];&lt;br /&gt;
&lt;br /&gt;
To access on JS side you have to send all variables from material file via getAllDatas first:&lt;br /&gt;
    protected function getAllDatas() {&lt;br /&gt;
        $result = array ();&lt;br /&gt;
        $result [&#039;token_types&#039;] = $this-&amp;gt;token_types;&lt;br /&gt;
        ...&lt;br /&gt;
        return $result;&lt;br /&gt;
    }&lt;br /&gt;
  &lt;br /&gt;
Then you can access it in similar way:&lt;br /&gt;
  var type = this.gamedatas.token_types[&#039;card_tech_1_51&#039;].type; // not translatable&lt;br /&gt;
  var name = _(this.gamedatas.token_types[&#039;card_tech_1_51&#039;].name); // to be shown to user (NOI18N)&lt;br /&gt;
&lt;br /&gt;
To send this in notification from PHP side:&lt;br /&gt;
  $this-&amp;gt;notifyAllUsers(&#039;gainCard&#039;,clienttranslate(&#039;player gains ${card_name}&#039;), [&lt;br /&gt;
       &#039;i18n&#039;=&amp;gt;[&#039;card_name&#039;],&lt;br /&gt;
       &#039;card_id&#039; =&amp;gt; $card_id,&lt;br /&gt;
       &#039;card_name&#039; =&amp;gt; $this-&amp;gt;token_types[$card_id][&#039;name&#039;]&lt;br /&gt;
  ]);&lt;br /&gt;
&lt;br /&gt;
=== PHP constants ===&lt;br /&gt;
If you also want to access constants in JS side, you can send them via getAllData like this&lt;br /&gt;
&lt;br /&gt;
        $cc = get_defined_constants(true)[&#039;user&#039;];&lt;br /&gt;
        $result[&#039;constants&#039;]=$cc; // this will be all constants though, you may have to filter some stuff out for security reasons&lt;br /&gt;
&lt;br /&gt;
Alternately you can include a material.inc.php in local php file and call this method to print constants in JS format, then include this file in JS, you may have to synchronize this manually, but its better for auto-complete also.&lt;br /&gt;
        // this needs to be run locally after including materal file (see example in testing below)&lt;br /&gt;
        $cc = get_defined_constants(true)[&#039;user&#039;];&lt;br /&gt;
        foreach ($cc as $key =&amp;gt; $value) {          &lt;br /&gt;
            print (&amp;quot;const $key = $value;\n&amp;quot;);&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
== Testing ==&lt;br /&gt;
If you screw up you material file such as miss some brackets it is very hard to diagnose. But you can test it locally like this&lt;br /&gt;
&lt;br /&gt;
misc/material_test.php:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;?php&lt;br /&gt;
class material_test {&lt;br /&gt;
    function __construct() {&lt;br /&gt;
        include &#039;../material.inc.php&#039;;&lt;br /&gt;
        var_dump($this-&amp;gt;token_types); // whatever your var&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
// stub&lt;br /&gt;
function clienttranslate($x) { return $x; }&lt;br /&gt;
&lt;br /&gt;
new material_test();&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Adjusting material ==&lt;br /&gt;
&lt;br /&gt;
In rare cases expansions of the game change the materials of the original game, in such cases same card for example was re-printed with a different text/rules.&lt;br /&gt;
Can you keep same card and have material adjust based on selected game options? It is possible with some trickery.&lt;br /&gt;
&lt;br /&gt;
You need to modify the data in that file AFTER constructor when database access is initialized, and have it available for all php entry points.&lt;br /&gt;
This is possible if you override function initTable() in your game.php file:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    /**&lt;br /&gt;
     * This is called before every action, unlike constructor this method has initialized state of the table so it can&lt;br /&gt;
     * access db&lt;br /&gt;
     *&lt;br /&gt;
     * @Override&lt;br /&gt;
     */&lt;br /&gt;
    protected function initTable() {&lt;br /&gt;
        // this fiddles with material file depending on the extension selected&lt;br /&gt;
        $this-&amp;gt;adjustMaterial();&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function adjustMaterial($force = false) {&lt;br /&gt;
        if ( !$force &amp;amp;&amp;amp; $this-&amp;gt;token_types_adjusted)&lt;br /&gt;
            return;&lt;br /&gt;
        $this-&amp;gt;token_types_adjusted = true;&lt;br /&gt;
        ... // fiddle with data in material file&lt;br /&gt;
    }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
To adjust material itself - you can do it in any number of ways I personally use this method: for modified values I specify key posfix that match my game option, and adjustment function re-write my keys, for example&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 &#039;card_tech_1_51&#039; =&amp;gt; [&lt;br /&gt;
   &#039;name&#039; =&amp;gt; clienttranslate(&amp;quot;Improved Trade&amp;quot;),&lt;br /&gt;
   &#039;name@e3&#039; =&amp;gt; clienttranslate(&amp;quot;Much Improved Trade&amp;quot;),&lt;br /&gt;
   &#039;cost&#039; =&amp;gt; 3,&lt;br /&gt;
   &#039;cost@p2&#039; =&amp;gt; 2&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In this example if player selects game expansion 3, the key name@e2 would override key name, and if there is 2 players, cost@p2 will override cost. If you need exact code, check adjustMaterial in Ultimate Railroads&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Note: if you need to add some data to material.inc.php programmatically which does not require database, you can just do it right in that file. Keep in mind will run multiple time for each php call back, so it should be very light&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$this-&amp;gt;decks = array (&lt;br /&gt;
        &#039;g&#039; =&amp;gt; array (&#039;id&#039; =&amp;gt; &#039;green&#039;,&#039;name&#039; =&amp;gt; clienttranslate(&#039;Green&#039;),&#039;num&#039; =&amp;gt; 1 ),&lt;br /&gt;
        &#039;r&#039; =&amp;gt; array (&#039;id&#039; =&amp;gt; &#039;red&#039;,&#039;name&#039; =&amp;gt; clienttranslate(&#039;Red&#039;),&#039;num&#039; =&amp;gt; 3 ),&lt;br /&gt;
        &#039;v&#039; =&amp;gt; array (&#039;id&#039; =&amp;gt; &#039;violet&#039;,&#039;name&#039; =&amp;gt; clienttranslate(&#039;Violet&#039;),&#039;num&#039; =&amp;gt; 4 ),&lt;br /&gt;
        &#039;y&#039; =&amp;gt; array (&#039;id&#039; =&amp;gt; &#039;yellow&#039;,&#039;name&#039; =&amp;gt; clienttranslate(&#039;Yellow&#039;),&#039;num&#039; =&amp;gt; 2 ) )&lt;br /&gt;
;&lt;br /&gt;
    &lt;br /&gt;
$this-&amp;gt;dcolor_map = array();&lt;br /&gt;
// reverse map&lt;br /&gt;
foreach ($this-&amp;gt;decks as $info) {&lt;br /&gt;
    $this-&amp;gt;dcolor_map[$info[&#039;num&#039;]]=$info[&#039;id&#039;];&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Category:Studio]]&lt;/div&gt;</summary>
		<author><name>Sguzzer Gunayer</name></author>
	</entry>
	<entry>
		<id>https://en.doc.boardgamearena.com/index.php?title=Your_game_state_machine:_states.inc.php&amp;diff=22557</id>
		<title>Your game state machine: states.inc.php</title>
		<link rel="alternate" type="text/html" href="https://en.doc.boardgamearena.com/index.php?title=Your_game_state_machine:_states.inc.php&amp;diff=22557"/>
		<updated>2024-09-14T09:49:07Z</updated>

		<summary type="html">&lt;p&gt;Sguzzer Gunayer: /* action */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Studio_Framework_Navigation}}&lt;br /&gt;
&lt;br /&gt;
This file describes the state machine of your game (all the game states properties, and the transitions to get from one state to another).&lt;br /&gt;
&lt;br /&gt;
Important: to understand the game state machine, it&#039;s recommended that you read this presentation first:&lt;br /&gt;
&lt;br /&gt;
[http://www.slideshare.net/boardgamearena/bga-studio-focus-on-bga-game-state-machine Focus on BGA game state machine]&lt;br /&gt;
&lt;br /&gt;
== Overall structure ==&lt;br /&gt;
&lt;br /&gt;
The machine states are described by a PHP associative array.&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$machinestates = array(&lt;br /&gt;
&lt;br /&gt;
    // The initial state. Please do not modify.&lt;br /&gt;
    1 =&amp;gt; array(&lt;br /&gt;
        &amp;quot;name&amp;quot; =&amp;gt; &amp;quot;gameSetup&amp;quot;,&lt;br /&gt;
        &amp;quot;description&amp;quot; =&amp;gt; clienttranslate(&amp;quot;Game setup&amp;quot;),&lt;br /&gt;
        &amp;quot;type&amp;quot; =&amp;gt; &amp;quot;manager&amp;quot;,&lt;br /&gt;
        &amp;quot;action&amp;quot; =&amp;gt; &amp;quot;stGameSetup&amp;quot;,&lt;br /&gt;
        &amp;quot;transitions&amp;quot; =&amp;gt; array( &amp;quot;&amp;quot; =&amp;gt; 2 )&lt;br /&gt;
    ),&lt;br /&gt;
    &lt;br /&gt;
    // Note: ID=2 =&amp;gt; your first state&lt;br /&gt;
&lt;br /&gt;
    2 =&amp;gt; array(&lt;br /&gt;
    		&amp;quot;name&amp;quot; =&amp;gt; &amp;quot;playerTurn&amp;quot;,&lt;br /&gt;
    		&amp;quot;description&amp;quot; =&amp;gt; clienttranslate(&#039;${actplayer} must play a card or pass&#039;),&lt;br /&gt;
    		&amp;quot;descriptionmyturn&amp;quot; =&amp;gt; clienttranslate(&#039;${you} must play a card or pass&#039;),&lt;br /&gt;
    		&amp;quot;type&amp;quot; =&amp;gt; &amp;quot;activeplayer&amp;quot;,&lt;br /&gt;
    		&amp;quot;possibleactions&amp;quot; =&amp;gt; array( &amp;quot;actPlayCard&amp;quot;, &amp;quot;actPass&amp;quot; ),&lt;br /&gt;
    		&amp;quot;transitions&amp;quot; =&amp;gt; array( &amp;quot;playCard&amp;quot; =&amp;gt; 2, &amp;quot;pass&amp;quot; =&amp;gt; 2 )&lt;br /&gt;
    ),&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Syntax ==&lt;br /&gt;
&lt;br /&gt;
=== id ===&lt;br /&gt;
&lt;br /&gt;
The keys determine game state IDs (in the example above: 1 and 2).&lt;br /&gt;
&lt;br /&gt;
IDs must be positive integers.&lt;br /&gt;
&lt;br /&gt;
ID=1 is reserved for the first game state and should not be used (and you must not modify it).&lt;br /&gt;
&lt;br /&gt;
ID=99 is reserved for the last game state (end of the game) (and you must not modify it).&lt;br /&gt;
&lt;br /&gt;
Note: you may use any ID, even an ID greater than 100. But you cannot use 1 or 99.&lt;br /&gt;
&lt;br /&gt;
Note²: You must not use the same ID twice.&lt;br /&gt;
&lt;br /&gt;
Note³: When a game is in prod and you change the ID of a state, all active games (including many turn based) will behave unpredictably.&lt;br /&gt;
&lt;br /&gt;
=== name ===&lt;br /&gt;
&lt;br /&gt;
(&#039;&#039;&#039;Mandatory&#039;&#039;&#039;)&lt;br /&gt;
&lt;br /&gt;
The name of a game state is used to identify it in your game logic.&lt;br /&gt;
&lt;br /&gt;
Several game states can share the same name; however, this is not recommended.&lt;br /&gt;
&lt;br /&gt;
Warning! Do not put spaces in the name. This could cause unexpected problems in some cases.&lt;br /&gt;
&lt;br /&gt;
PHP example:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
// Get current game state&lt;br /&gt;
$state = $this-&amp;gt;gamestate-&amp;gt;state();&lt;br /&gt;
if( $state[&#039;name&#039;] == &#039;myGameState&#039; )&lt;br /&gt;
{&lt;br /&gt;
...&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
JS example:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        onEnteringState: function( stateName, args )&lt;br /&gt;
        {&lt;br /&gt;
            console.log( &#039;Entering state: &#039;+stateName );&lt;br /&gt;
            &lt;br /&gt;
            switch( stateName )&lt;br /&gt;
            case &#039;myGameState&#039;:&lt;br /&gt;
            &lt;br /&gt;
                // Do some stuff at the beginning at this game state&lt;br /&gt;
                ....&lt;br /&gt;
                &lt;br /&gt;
                break;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== type ===&lt;br /&gt;
&lt;br /&gt;
(&#039;&#039;&#039;Mandatory&#039;&#039;&#039;)&lt;br /&gt;
&lt;br /&gt;
You can use 3 types of game states:&lt;br /&gt;
* activeplayer (1 player is active and must play.)&lt;br /&gt;
* multipleactiveplayer (1..N players can be active and must play.)&lt;br /&gt;
* private (during multiactive states players can independently move to different private parallel states. See more details [[#Private_parallel_states|here]].&lt;br /&gt;
* game (No player is active. This is a transitional state to do something automatic specified by the game rules.)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note:&#039;&#039;&#039; Make sure you don&#039;t mistype the value of this attribute. If you do (e.g. &#039;multiactiveplayer&#039; instead of &#039;multipleactiveplayer&#039;), things won&#039;t work, and you might have a hard time figuring out why.&lt;br /&gt;
&lt;br /&gt;
=== description ===&lt;br /&gt;
&lt;br /&gt;
(&#039;&#039;&#039;Mandatory&#039;&#039;&#039;)&lt;br /&gt;
&lt;br /&gt;
The description is the string that is displayed in the main action bar (top of the screen) when the state is active.&lt;br /&gt;
&lt;br /&gt;
When a string is specified as a description, you must use &amp;quot;clienttranslate&amp;quot; in order for the string to be translated on the client side:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 		&amp;quot;description&amp;quot; =&amp;gt; clienttranslate(&#039;${actplayer} must play a card or pass&#039;),&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In the description string, you can use ${actplayer} to refer to the active player.&lt;br /&gt;
&lt;br /&gt;
You can also use custom arguments in your description. These custom arguments correspond to values returned by your &amp;quot;args&amp;quot; PHP method (see below &amp;quot;args&amp;quot; field).&lt;br /&gt;
&lt;br /&gt;
Example of custom field:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In states.inc.php:&lt;br /&gt;
        &amp;quot;description&amp;quot; =&amp;gt; clienttranslate(&#039;${actplayer} must choose ${nbr} identical energies&#039;),&lt;br /&gt;
        &amp;quot;args&amp;quot; =&amp;gt; &amp;quot;argMyArgumentMethod&amp;quot;&lt;br /&gt;
&lt;br /&gt;
In mygame.game.php:&lt;br /&gt;
    function argMyArgumentMethod()&lt;br /&gt;
    {&lt;br /&gt;
        return array(&lt;br /&gt;
            &#039;nbr&#039; =&amp;gt; 2  // In this case ${nbr} in the description will be replaced by &amp;quot;2&amp;quot;&lt;br /&gt;
        );    &lt;br /&gt;
    }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note: You may specify an empty string (&amp;quot;&amp;quot;) here if it never happens that the game remains in this state (i.e., if this state immediately jumps to another state when activated).&lt;br /&gt;
&lt;br /&gt;
Note²: Usually, you specify a string for &amp;quot;activeplayer&amp;quot; and &amp;quot;multipleactiveplayer&amp;quot; game states, and you specify an empty string for &amp;quot;game&amp;quot; game states. BUT, if you are using synchronous notifications, the client can remain on a &amp;quot;game&amp;quot; type game state for a few seconds, and in this case it may be useful to display a description in the status bar while in this state.&lt;br /&gt;
&lt;br /&gt;
=== descriptionmyturn ===&lt;br /&gt;
&lt;br /&gt;
(&#039;&#039;&#039;Mandatory&#039;&#039;&#039; when the state type is &amp;quot;activeplayer&amp;quot; or &amp;quot;multipleactiveplayer&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
&amp;quot;descriptionmyturn&amp;quot; has exactly the same role and properties as &amp;quot;description&amp;quot;, except that this value is displayed to the current active player - or to all active players in case of a multipleactiveplayer game state.&lt;br /&gt;
&lt;br /&gt;
In general, we have this situation:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        &amp;quot;description&amp;quot; =&amp;gt; clienttranslate(&#039;${actplayer} can take some actions&#039;),&lt;br /&gt;
        &amp;quot;descriptionmyturn&amp;quot; =&amp;gt; clienttranslate(&#039;${you} can take some actions&#039;),&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note: you can use ${you} in descriptionmyturn so the description will display &amp;quot;You&amp;quot; instead of the name of the player.&lt;br /&gt;
&lt;br /&gt;
Note 2: you can use ${otherplayer} to refer to some other player if you want this to be shown in player&#039;s color, but you must provide otherplayer_id as argument (along with otherplayer) to specify this player&#039;s id in this case or game won&#039;t load.&lt;br /&gt;
&lt;br /&gt;
I.e.&lt;br /&gt;
&lt;br /&gt;
 &amp;quot;descriptionmyturn&amp;quot; =&amp;gt; clienttranslate(&#039;${you} can follow action of ${otherplayer}&#039;),&lt;br /&gt;
&lt;br /&gt;
And this will have to be state arguments for this&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    function arg_playerTurnFollow(){&lt;br /&gt;
        return [&#039;otherplayer&#039;=&amp;gt; $this-&amp;gt;getLeaderPlayerName(),&lt;br /&gt;
                &#039;otherplayer_id&#039;=&amp;gt; $this-&amp;gt;getLeaderPlayerId()&lt;br /&gt;
        ];&lt;br /&gt;
    }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== action ===&lt;br /&gt;
&lt;br /&gt;
(&#039;&#039;&#039;Mandatory&#039;&#039;&#039; when the state type is &amp;quot;game.&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
&amp;quot;action&amp;quot; specifies a PHP method to call when entering this game state.&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
In states.inc.php:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    28 =&amp;gt; array(&lt;br /&gt;
        &amp;quot;name&amp;quot; =&amp;gt; &amp;quot;gameTurnNextPlayer&amp;quot;,&lt;br /&gt;
        &amp;quot;description&amp;quot; =&amp;gt; clienttranslate(&#039;Updating some stuff...&#039;),&lt;br /&gt;
        &amp;quot;type&amp;quot; =&amp;gt; &amp;quot;game&amp;quot;,&lt;br /&gt;
        &amp;quot;action&amp;quot; =&amp;gt; &amp;quot;st_gameTurnNextPlayer&amp;quot;,&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
In mygame.game.php:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    function st_gameTurnNextPlayer() {&lt;br /&gt;
        $player_id = $this-&amp;gt;getActivePlayerId();&lt;br /&gt;
        $next_player_id = $this-&amp;gt;getPlayerAfter($player_id);&lt;br /&gt;
        $this-&amp;gt;giveExtraTime($next_player_id);&lt;br /&gt;
        $this-&amp;gt;incStat(1, &#039;turns_number&#039;, $next_player_id);&lt;br /&gt;
        $this-&amp;gt;incStat(1, &#039;turns_number&#039;);&lt;br /&gt;
        $this-&amp;gt;gamestate-&amp;gt;changeActivePlayer($next_player_id);&lt;br /&gt;
        $this-&amp;gt;gamestate-&amp;gt;nextState(&#039;next&#039;);&lt;br /&gt;
    }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Usually, for a &amp;quot;game&amp;quot; state type, the action method is used to perform automatic functions specified by the rules (for example: check victory conditions, deal cards for a new round, go to the next player, etc.) and then jump to another game state.&lt;br /&gt;
&lt;br /&gt;
Note: a BGA convention specifies that PHP methods called with &amp;quot;action&amp;quot; are prefixed by &amp;quot;st&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
Note: this field CAN be used for player states to set something up; e.g., for multiplayer states, it can make all players active.&lt;br /&gt;
&lt;br /&gt;
Example for action in player state:&lt;br /&gt;
in states.inc.php:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    2 =&amp;gt; array(&lt;br /&gt;
    		&amp;quot;name&amp;quot; =&amp;gt; &amp;quot;playerTurnPlace&amp;quot;,&lt;br /&gt;
    		&amp;quot;description&amp;quot; =&amp;gt; clienttranslate(&#039;Other player must place ships&#039;),&lt;br /&gt;
    		&amp;quot;descriptionmyturn&amp;quot; =&amp;gt; clienttranslate(&#039;${you} must place ships (click on YOUR SHIPS board to place)&#039;),&lt;br /&gt;
    		&amp;quot;type&amp;quot; =&amp;gt; &amp;quot;multipleactiveplayer&amp;quot;,&lt;br /&gt;
            &#039;action&#039; =&amp;gt; &#039;st_MultiPlayerInit&#039;,&lt;br /&gt;
            &#039;args&#039; =&amp;gt; &#039;arg_playerTurnPlace&#039;,&lt;br /&gt;
    		&amp;quot;possibleactions&amp;quot; =&amp;gt; array( &amp;quot;playPlace&amp;quot; ),&lt;br /&gt;
            &amp;quot;transitions&amp;quot; =&amp;gt; array( &amp;quot;next&amp;quot; =&amp;gt; 4, &amp;quot;last&amp;quot; =&amp;gt; 99)&lt;br /&gt;
    ),&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
in mygame.game.php:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    function st_MultiPlayerInit() {&lt;br /&gt;
        $this-&amp;gt;gamestate-&amp;gt;setAllPlayersMultiactive();&lt;br /&gt;
    }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&#039;&#039;&#039;Warning&#039;&#039;&#039;: Prevent to do anything on stGameEnd() and argGameEnd() in mygame.game.php. It may cause game never end and always stuck in &amp;quot;Recording game results + computing statistics in progress...&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
=== transitions ===&lt;br /&gt;
&lt;br /&gt;
(&#039;&#039;&#039;Mandatory&#039;&#039;&#039;)&lt;br /&gt;
&lt;br /&gt;
With &amp;quot;transitions&amp;quot; you specify which game state(s) you can jump to from a given game state.&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    25 =&amp;gt; array(&lt;br /&gt;
        &amp;quot;name&amp;quot; =&amp;gt; &amp;quot;myGameState&amp;quot;,&lt;br /&gt;
        &amp;quot;transitions&amp;quot; =&amp;gt; array( &amp;quot;nextPlayer&amp;quot; =&amp;gt; 27, &amp;quot;endRound&amp;quot; =&amp;gt; 39 ),&lt;br /&gt;
        ....&lt;br /&gt;
    }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In the example above, if &amp;quot;myGameState&amp;quot; is the current active game state, I can jump to the game state with ID 27 or the game state with ID 39.&lt;br /&gt;
&lt;br /&gt;
Example to jump to ID 27:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
In mygame.game.php:&lt;br /&gt;
    $this-&amp;gt;gamestate-&amp;gt;nextState( &amp;quot;nextPlayer&amp;quot; );&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Important: &amp;quot;nextPlayer&amp;quot; is the name of the transition, and NOT the name of the target game state. Multiple transitions can lead to the same game state.&lt;br /&gt;
&lt;br /&gt;
Note: If there is only 1 transition, you may give it an empty name.&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
In states.inc.php:&lt;br /&gt;
    &amp;quot;transitions&amp;quot; =&amp;gt; array( &amp;quot;&amp;quot; =&amp;gt; 27 ),&lt;br /&gt;
&lt;br /&gt;
In mygame.game.php:&lt;br /&gt;
    $this-&amp;gt;gamestate-&amp;gt;nextState(  );     // We don&#039;t need to specify a transition as there is only one here&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== possibleactions ===&lt;br /&gt;
&lt;br /&gt;
(&#039;&#039;&#039;Mandatory&#039;&#039;&#039; when the game state is &amp;quot;activeplayer&amp;quot; or &amp;quot;multipleactiveplayer&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
&amp;quot;possibleactions&amp;quot; defines the actions possible by the players in this game state, and ensures they cannot perform actions that are not allowed in this state.&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
In states.game.php:&lt;br /&gt;
       	&amp;quot;possibleactions&amp;quot; =&amp;gt; array( &amp;quot;actPlayCard&amp;quot;, &amp;quot;actPass&amp;quot; ),&lt;br /&gt;
&lt;br /&gt;
In mygame.game.php:&lt;br /&gt;
        function actPlayCard( ...)&lt;br /&gt;
        {&lt;br /&gt;
             $this-&amp;gt;checkAction( &amp;quot;actPlayCard&amp;quot; );    // Will fail if &amp;quot;actPlayCard&amp;quot; is not specified in &amp;quot;possibleactions&amp;quot; in the current game state.&lt;br /&gt;
&lt;br /&gt;
            ....&lt;br /&gt;
&lt;br /&gt;
In mygame.js:&lt;br /&gt;
        playCard: function( ... )&lt;br /&gt;
        {&lt;br /&gt;
            if( this.checkAction( &amp;quot;actPlayCard&amp;quot; ) ) // Will fail if &amp;quot;actPlayCard&amp;quot; is not specified in &amp;quot;possibleactions&amp;quot; in the current game state.&lt;br /&gt;
            {  return ;   }&lt;br /&gt;
// or &lt;br /&gt;
        playCard: function( ... )&lt;br /&gt;
        {&lt;br /&gt;
            if( this.bgaPerformAction( &amp;quot;actPlayCard&amp;quot;, { id} ) ) // Will not trigger if &amp;quot;actPlayCard&amp;quot; is not specified in &amp;quot;possibleactions&amp;quot; in the current game state.&lt;br /&gt;
            {  return ;   }&lt;br /&gt;
&lt;br /&gt;
            ....&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== args ===&lt;br /&gt;
&lt;br /&gt;
(optional)&lt;br /&gt;
&lt;br /&gt;
Sometimes it happens that you need some information on the client side (i.e., for your game interface) only for a specific game state.&lt;br /&gt;
&lt;br /&gt;
Example 1: in &#039;&#039;Reversi&#039;&#039;, the list of possible moves during the playerTurn state.&lt;br /&gt;
&lt;br /&gt;
Example 2: in &#039;&#039;Caylus&#039;&#039;, the number of remaining king&#039;s favors to choose in the state where the player is choosing a favor.&lt;br /&gt;
&lt;br /&gt;
Example 3: in &#039;&#039;Can&#039;t Stop&#039;&#039;, the list of possible die combinations to be displayed to the active player so that he can choose from among them.&lt;br /&gt;
&lt;br /&gt;
In such a situation, you can specify a method name as the « args » argument for your game state. This method must retrieve some piece of information about the game (example: for &#039;&#039;Reversi&#039;&#039;, the list of possible moves) and return it.&lt;br /&gt;
&lt;br /&gt;
Thus, this data can be transmitted to the clients and used by the clients to display it. It should always be an associative array.&lt;br /&gt;
&lt;br /&gt;
Let&#039;s see a complete example using args with &#039;&#039;Reversi&#039;&#039; game:&lt;br /&gt;
&lt;br /&gt;
In states.inc.php, we specify an &#039;&#039;&#039;args&#039;&#039;&#039; argument for gamestate &#039;&#039;&#039;playerTurn&#039;&#039;&#039;:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    10 =&amp;gt; array(&lt;br /&gt;
        &amp;quot;name&amp;quot; =&amp;gt; &amp;quot;playerTurn&amp;quot;,&lt;br /&gt;
		&amp;quot;description&amp;quot; =&amp;gt; clienttranslate(&#039;${actplayer} must play a disc&#039;),&lt;br /&gt;
		&amp;quot;descriptionmyturn&amp;quot; =&amp;gt; clienttranslate(&#039;${you} must play a disc&#039;),&lt;br /&gt;
        &amp;quot;type&amp;quot; =&amp;gt; &amp;quot;activeplayer&amp;quot;,&lt;br /&gt;
        &amp;quot;args&amp;quot; =&amp;gt; &amp;quot;argPlayerTurn&amp;quot;,    // &amp;lt;==== HERE&lt;br /&gt;
        &amp;quot;possibleactions&amp;quot; =&amp;gt; array( &#039;actPlayDisc&#039; ),&lt;br /&gt;
        &amp;quot;transitions&amp;quot; =&amp;gt; array( &amp;quot;playDisc&amp;quot; =&amp;gt; 11, &amp;quot;zombiePass&amp;quot; =&amp;gt; 11 )&lt;br /&gt;
    ),&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
It corresponds to a &#039;&#039;&#039;argPlayerTurn&#039;&#039;&#039; method in our PHP code (reversi.game.php):&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    function argPlayerTurn() {&lt;br /&gt;
        return array(&lt;br /&gt;
            &#039;possibleMoves&#039; =&amp;gt; $this-&amp;gt;getPossibleMoves()&lt;br /&gt;
        );&lt;br /&gt;
    }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Then, when we enter into the &#039;&#039;&#039;playerTurn&#039;&#039;&#039; game state on the client side, we can highlight the possible moves on the board using information returned by &#039;&#039;&#039;argPlayerTurn&#039;&#039;&#039;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        onEnteringState: function( stateName, args )  {&lt;br /&gt;
           console.log( &#039;Entering state: &#039;+stateName );&lt;br /&gt;
            &lt;br /&gt;
            switch( stateName )  {&lt;br /&gt;
            case &#039;playerTurn&#039;:&lt;br /&gt;
                this.updatePossibleMoves( args.args.possibleMoves );&lt;br /&gt;
                break;&lt;br /&gt;
            }&lt;br /&gt;
        },&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Naming and API conventions ====&lt;br /&gt;
&lt;br /&gt;
As a BGA convention, PHP methods called with &amp;quot;args&amp;quot; are prefixed by &amp;quot;arg&amp;quot; followed by state name (example: &#039;&#039;&#039;argPlayerTurn&#039;&#039;&#039;).&lt;br /&gt;
&lt;br /&gt;
All &amp;quot;arg*&amp;quot; methods are put into corresponding section of .game.php file commented as&lt;br /&gt;
   //////////// Game state arguments&lt;br /&gt;
&lt;br /&gt;
Arg method MUST return array. Return integer or string will result in some undebuggable exceptions.&lt;br /&gt;
&lt;br /&gt;
Arg method MUST be defined in php if it is declared in state description, if you don&#039;t need it comment it out from the states.inc.php file (the &#039;&#039;&#039;args&#039;&#039;&#039; parameter). If you not sure if you need it or not you can keep it returning empty array until you figure it out.&lt;br /&gt;
&lt;br /&gt;
    function argPlayerTurn() {&lt;br /&gt;
        return array(); // must be an array&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Warning&#039;&#039;&#039;: the &amp;quot;args&amp;quot; method is ALWAYS called before the &amp;quot;action&amp;quot; method so don&#039;t expect data modifications by the &amp;quot;action&amp;quot; method to be available in the &amp;quot;args&amp;quot; method!&lt;br /&gt;
Also don&#039;t modify database in this method!&lt;br /&gt;
&lt;br /&gt;
You should NOT be calling getCurrentPlayer() in the context of this function, since state transitions are broadcasted to all player independent of who initiated it. Instead you should send information on per player basis (Note: if this is private info see section below). &lt;br /&gt;
&lt;br /&gt;
If you using this function in multi-player state, you should not call getActivePlayer() either, you should send per player info:&lt;br /&gt;
&lt;br /&gt;
    function arg_playerTurn() {&lt;br /&gt;
        $res = array ();&lt;br /&gt;
        $players = $this-&amp;gt;loadPlayersBasicInfos();&lt;br /&gt;
        foreach ( $players as $player_id =&amp;gt; $player_info ) {&lt;br /&gt;
            $color = $player_info [&#039;player_color&#039;];&lt;br /&gt;
            $res [$player_id] = array(&amp;quot;color&amp;quot;=&amp;gt;$color);&lt;br /&gt;
        }&lt;br /&gt;
        return $res;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
Note: you never need to send player color like this, this is just an example.&lt;br /&gt;
&lt;br /&gt;
Note 2: you CAN call methods that return all active players if multi-player states if its relevant.&lt;br /&gt;
&lt;br /&gt;
==== Other usages ====&lt;br /&gt;
&lt;br /&gt;
You can use values returned by your &amp;quot;args&amp;quot; method to have some custom values in your &amp;quot;description&amp;quot;/&amp;quot;descriptionmyturn&amp;quot;, i.e. in states.inc.php:&lt;br /&gt;
&lt;br /&gt;
   &amp;quot;descriptionmyturn&amp;quot; =&amp;gt; clienttranslate(&#039;${you} must play ${color} disc&#039;),&lt;br /&gt;
&lt;br /&gt;
So arg function will be something like:&lt;br /&gt;
&lt;br /&gt;
  function argPlayerTurn() {&lt;br /&gt;
        return array(&#039;color&#039;=&amp;gt;$this-&amp;gt;getActivePlayerColor()); &lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
You can use args also in &#039;&#039;&#039;onUpdateActionButtons&#039;&#039;&#039; function on js side, however two important notes:&lt;br /&gt;
* it is just &#039;&#039;&#039;args&#039;&#039;&#039; (not args.args like in &#039;&#039;&#039;onEnteringState&#039;&#039;&#039;)&lt;br /&gt;
* it is args of the current state, which may not be state you think it will be! This method is called during change of active player, which happens in some weird place especially during &amp;quot;multipleactiveplayer&amp;quot; states. If you pulling your hair thinking why its &amp;quot;undefined&amp;quot; on js side - check the current state.&lt;br /&gt;
&lt;br /&gt;
==== Private info in args ====&lt;br /&gt;
&lt;br /&gt;
By default, all data provided through this method are PUBLIC TO ALL PLAYERS. Please do not send any private data with this method, as a cheater could see it even it is not used explicitly by the game interface logic.&lt;br /&gt;
&lt;br /&gt;
However, it is possible to specify that some data should be sent to specific players only.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note: You cannot use Example 1 and Example 2 together. If you have to send private args to multiple players, use Example 2.&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Example 1: send information to active player(s) only:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    function argPlayerTurn()  {&lt;br /&gt;
        return array(&lt;br /&gt;
            &#039;_private&#039; =&amp;gt; array(          // Using &amp;quot;_private&amp;quot; keyword, all data inside this array will be made private&lt;br /&gt;
                &#039;active&#039; =&amp;gt; array(       // Using &amp;quot;active&amp;quot; keyword inside &amp;quot;_private&amp;quot;, you select active player(s)&lt;br /&gt;
                    &#039;somePrivateData&#039; =&amp;gt; $this-&amp;gt;getSomePrivateData()   // will be send only to active player(s)&lt;br /&gt;
                )&lt;br /&gt;
            ),&lt;br /&gt;
            &#039;possibleMoves&#039; =&amp;gt; $this-&amp;gt;getPossibleMoves()          // will be sent to all players&lt;br /&gt;
        );&lt;br /&gt;
    }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Inside the js file, these variables will be available through `args.args._private`. (e.g. `args.args._private.somePrivateData` -- it is not `args._private.active.somePrivateData` nor is it `args.somePrivateData`)&lt;br /&gt;
&lt;br /&gt;
Example 2: send information to a specific player (&amp;lt;specific_player_id&amp;gt;) only:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    function argPlayerTurn()  {&lt;br /&gt;
        $specific_player_id = ...; // calculate some-how&lt;br /&gt;
        return array(&lt;br /&gt;
            &#039;_private&#039; =&amp;gt; array(   // all data inside this array will be private&lt;br /&gt;
                $specific_player_id =&amp;gt; array(   // will be sent only to that player   &lt;br /&gt;
                    &#039;somePrivateData&#039; =&amp;gt; $this-&amp;gt;getSomePrivateData()   &lt;br /&gt;
                )&lt;br /&gt;
            ),&lt;br /&gt;
&lt;br /&gt;
            &#039;possibleMoves&#039; =&amp;gt; $this-&amp;gt;getPossibleMoves()   // will be sent to all players&lt;br /&gt;
        );&lt;br /&gt;
    }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
IMPORTANT: in certain situations (i.e. &amp;quot;multipleactiveplayer&amp;quot; game state) these &amp;quot;private data&amp;quot; features can have a significant impact on performance. Please do not use if not needed.&lt;br /&gt;
&lt;br /&gt;
It is also possible to use these private args in the &amp;quot;description&amp;quot; messages, like &amp;quot;${you} have to play ${_private.count} cards&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
==== Flag to indicate a skipped state ====&lt;br /&gt;
&lt;br /&gt;
By default, The front-end will be notified of entering/leaving all states. To speed up the front-end chaining of automatically passed states, you can disable this state change notification, so the front-end doesn&#039;t trigger the preparation steps for a state that you know will be automatically skipped, and it may reduce sent args. In this case, define the &#039;&#039;&#039;_no_notify&#039;&#039;&#039; flag to true in the state args.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
function argPlayerTurn()  {&lt;br /&gt;
  $playableCardsIds = ...;&lt;br /&gt;
  return [&lt;br /&gt;
    &#039;playableCardsIds&#039; =&amp;gt; $playableCardsIds,&lt;br /&gt;
    &#039;_no_notify&#039; =&amp;gt; count(playableCardsIds) === 0,&lt;br /&gt;
  ];&lt;br /&gt;
}&lt;br /&gt;
function stPlayerTurn()  {&lt;br /&gt;
  $args = $this-&amp;gt;argPlayerTurn();&lt;br /&gt;
  if ($args[&#039;_no_notify&#039;]) {&lt;br /&gt;
    $this-&amp;gt;gamestate-&amp;gt;nextState(&#039;next&#039;);&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In this example, it might avoid a blinking message &amp;quot;You must play a card&amp;quot; (quickly replaced by the next state message) when you cannot play a card and the game automatically skips this state.&lt;br /&gt;
&lt;br /&gt;
IMPORTANT: if you use _no_notify, you must handle a redirection to another state on the st function!&lt;br /&gt;
&lt;br /&gt;
Note that if you play synced notifications during a skipped state, it will display the notifications on the previous state. For example, for an endScore state width description &amp;quot;Computing end score...&amp;quot; sending a lot of animated notifications, you should NOT use this flag so the description is visible.&lt;br /&gt;
&lt;br /&gt;
==== Translations in args ====&lt;br /&gt;
You can do the same as in notification by adding i18n parameter, i.e&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
function argPlayerTurn()  {&lt;br /&gt;
 return [&lt;br /&gt;
      &#039;i18n&#039; =&amp;gt; [&#039;terrainName&#039; ],&lt;br /&gt;
      &#039;terrainName&#039; =&amp;gt; ($this-&amp;gt;token_types[$terrain][&#039;name&#039;]), // this should be defined in material.inc.php and with clienttranslate &lt;br /&gt;
      &#039;terrain&#039; =&amp;gt; $terrain,&lt;br /&gt;
   ];&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Than you can do something like this in state:&lt;br /&gt;
  &amp;quot;descriptionmyturn&amp;quot; =&amp;gt; clienttranslate(&#039;${you} must place a house on ${terrainName}&#039;),&lt;br /&gt;
&lt;br /&gt;
See more in [[Translations]]&lt;br /&gt;
&lt;br /&gt;
=== updateGameProgression ===&lt;br /&gt;
&lt;br /&gt;
(optional)&lt;br /&gt;
&lt;br /&gt;
If you specify &amp;quot;updateGameProgression =&amp;gt; true&amp;quot; in a game state, your &amp;quot;getGameProgression&amp;quot; PHP method will be called at the beginning of this game state - and thus the game progression of the game will be updated.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;At least one&#039;&#039; of your game states (any one) must specify &amp;quot;updateGameProgression=&amp;gt;true&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
=== initialprivate ===&lt;br /&gt;
&lt;br /&gt;
(optional)&lt;br /&gt;
&lt;br /&gt;
This parameter will enable private parallel states in a multiplayer state. Parameter should be set to first private parallel state a player will be transitioned to.&lt;br /&gt;
See more details about Private parallel states [[#Private_parallel_states|here]].&lt;br /&gt;
&lt;br /&gt;
== Implementation Notes ==&lt;br /&gt;
&lt;br /&gt;
=== Private parallel states ===&lt;br /&gt;
&lt;br /&gt;
Private parallel states are useful when multiple players are active and their turn is very complex. In that case it is possible with parallel states for each player to be in a independent state. &lt;br /&gt;
&lt;br /&gt;
Lets say that players need to do three complex action one after another in multiactive state. With parallel states each player can independently be in a different state (i.e. one player still need to decide about first action while some players are deciding their second action and the fastest player is already on their third action. Normally this can be handled with two simple, but limited, approaches:&lt;br /&gt;
&lt;br /&gt;
* Moving all players to different states together - this is limiting for faster players as they need to wait other players for each separate action. The more problematic thing is that it would be hard to implement an undo feature when one player wants to change their previous action. In that case all players should be moved back to previous state which will interrupt their flow.&lt;br /&gt;
* Using client states, by changing the state in which the player is in javascript - the problem with this approach is that players will lose their progress on browser refresh (F5). Furthermore the validation logic of specific actions should be implemented on both server side and client side and we cannot have specific args for each different action, but they should be calculated only at the beginning of the first action and possibly calculated on client side after each action, which again duplicates logic on client and server.&lt;br /&gt;
&lt;br /&gt;
With private parallel states, each specific action can be implemented as a parallel state. Parallel states are defined with the type &#039;private&#039; and players are moved to those private states during one master multiactive state. Lets look at the example:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    10 =&amp;gt; [&lt;br /&gt;
        &amp;quot;name&amp;quot; =&amp;gt; &amp;quot;playerTurn&amp;quot;,&lt;br /&gt;
        &amp;quot;description&amp;quot; =&amp;gt; clienttranslate(&#039;Waiting for other players to end their turn.&#039;),&lt;br /&gt;
        &amp;quot;descriptionmyturn&amp;quot; =&amp;gt; clienttranslate(&#039;${you} must do your turn&#039;), // Won&#039;t be displayed anyway since each private state has its own description&lt;br /&gt;
        &amp;quot;type&amp;quot; =&amp;gt; &amp;quot;multipleactiveplayer&amp;quot;,&lt;br /&gt;
        &amp;quot;initialprivate&amp;quot; =&amp;gt; 50, // This makes this state a master multiactive state and enables private states, this is also a first private state&lt;br /&gt;
        &amp;quot;action&amp;quot; =&amp;gt; &amp;quot;stPlayerTurn&amp;quot;,&lt;br /&gt;
        &amp;quot;args&amp;quot; =&amp;gt; &amp;quot;argPlayerTurn&amp;quot;,&lt;br /&gt;
        &amp;quot;possibleactions&amp;quot; =&amp;gt; [&amp;quot;actChangeMind&amp;quot;], //this action is possible if player is not in any private state which usually happens when they are inactive&lt;br /&gt;
        &amp;quot;transitions&amp;quot; =&amp;gt; [&amp;quot;playersDecide&amp;quot; =&amp;gt; 11] // this is normal next transition which will happen after all players finish their turns &lt;br /&gt;
    ],&lt;br /&gt;
&lt;br /&gt;
    50 =&amp;gt; [&lt;br /&gt;
        &amp;quot;name&amp;quot; =&amp;gt; &amp;quot;chooseFirst&amp;quot;,&lt;br /&gt;
        &amp;quot;descriptionmyturn&amp;quot; =&amp;gt; clienttranslate(&#039;${you} must make your first choice&#039;), // just this parameter is needed. description is not needed as no player is inactive in this state&lt;br /&gt;
        &amp;quot;type&amp;quot; =&amp;gt; &amp;quot;private&amp;quot;, // this state is reachable only as a private state&lt;br /&gt;
        &amp;quot;args&amp;quot; =&amp;gt; &amp;quot;argChooseFirst&amp;quot;, //this method will be called with playerId as a parametar and is used to calculate arguments for this action for specific player&lt;br /&gt;
        &amp;quot;action&amp;quot; =&amp;gt; &amp;quot;stChooseFirst&amp;quot;, // this method will be called with playerId as a parameter and can be used to make some changes when player enters this private state&lt;br /&gt;
        &amp;quot;possibleactions&amp;quot; =&amp;gt; [&amp;quot;actToSecond&amp;quot;],&lt;br /&gt;
        &amp;quot;transitions&amp;quot; =&amp;gt; [&lt;br /&gt;
          &#039;chooseSecond&#039; =&amp;gt; 51, // transition to another private state&lt;br /&gt;
        ]&lt;br /&gt;
      ],&lt;br /&gt;
   &lt;br /&gt;
    51 =&amp;gt; [&lt;br /&gt;
        &amp;quot;name&amp;quot; =&amp;gt; &amp;quot;chooseSecond&amp;quot;,&lt;br /&gt;
        &amp;quot;descriptionmyturn&amp;quot; =&amp;gt; clienttranslate(&#039;${you} must make your second choice&#039;),&lt;br /&gt;
        &amp;quot;type&amp;quot; =&amp;gt; &amp;quot;private&amp;quot;,&lt;br /&gt;
        &amp;quot;args&amp;quot; =&amp;gt; &amp;quot;argChooseSecond&amp;quot;,&lt;br /&gt;
        &amp;quot;possibleactions&amp;quot; =&amp;gt; [&amp;quot;actFinish&amp;quot;, &amp;quot;actBack&amp;quot;],&lt;br /&gt;
        &amp;quot;transitions&amp;quot; =&amp;gt; [&lt;br /&gt;
          &#039;back&#039; =&amp;gt; 50,&lt;br /&gt;
        ]&lt;br /&gt;
      ],&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
When entering the master state it is usually useful to set some players as multiactive and initialize their private state:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    function stPlayerTurn() {&lt;br /&gt;
        $this-&amp;gt;gamestate-&amp;gt;setAllPlayersMultiactive();&lt;br /&gt;
        &lt;br /&gt;
        //this is needed when starting private parallel states; players will be transitioned to initialprivate state defined in master state&lt;br /&gt;
        $this-&amp;gt;gamestate-&amp;gt;initializePrivateStateForAllActivePlayers(); &lt;br /&gt;
&lt;br /&gt;
        // in some cases you can move immediately some or all players to different private states&lt;br /&gt;
        if ($someCondition) {&lt;br /&gt;
            //move all players to different state &lt;br /&gt;
            $this-&amp;gt;gamestate-&amp;gt;nextPrivateStateForAllActivePlayers(&amp;quot;chooseSecond&amp;quot;);&lt;br /&gt;
            return;&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        if ($other condition) {&lt;br /&gt;
            //move single player to different state&lt;br /&gt;
            $this-&amp;gt;gamestate-&amp;gt;nextPrivateState($specificPlayerId, &amp;quot;chooseSecond&amp;quot;);&lt;br /&gt;
            return;&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
When some action is done by a player, you can move them to the next private state:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    function actToSecond() {&lt;br /&gt;
        $this-&amp;gt;checkAction(&amp;quot;actToSecond&amp;quot;);  //the action must be defined in private state; actions defined in master state are not possible&lt;br /&gt;
        $this-&amp;gt;gamestate-&amp;gt;nextPrivateState($this-&amp;gt;getCurrentPlayerId(), &amp;quot;chooseSecond&amp;quot;); //moving current player to different state&lt;br /&gt;
    }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Please check the detailed API [[Main_game_logic:_yourgamename.game.php#Private_parallel_states|here]].&lt;br /&gt;
&lt;br /&gt;
=== Client States ===&lt;br /&gt;
Client state almost have nothing to do with server states, except they can simulate same experience without actually changing server states.&lt;br /&gt;
&lt;br /&gt;
See description here: https://en.doc.boardgamearena.com/BGA_Studio_Cookbook#Multi_Step_Interactions:_Select_Worker.2FPlace_Worker_-_Using_Client_States&lt;br /&gt;
&lt;br /&gt;
In many cases you can achive similar results by using client states vs private server states. The only caviat - when using client states during multiactive server state&lt;br /&gt;
other player will trigger state changes (multiactive player set) which will call onUpdateActionButtons. Some measures have to be taken to preserve client state in this case.&lt;br /&gt;
&lt;br /&gt;
=== Using Named Constants for States ===&lt;br /&gt;
&lt;br /&gt;
Using numeric constants is prone to errors. If you want you can declare state constants as PHP named constants. This way you can&lt;br /&gt;
use them in the states file and in game.php as well&lt;br /&gt;
&lt;br /&gt;
EXAMPLE:&lt;br /&gt;
&lt;br /&gt;
states.inc.php:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
// define contants for state ids&lt;br /&gt;
if (!defined(&#039;STATE_END_GAME&#039;)) { // ensure this block is only invoked once, since it is included multiple times&lt;br /&gt;
   define(&amp;quot;STATE_PLAYER_TURN&amp;quot;, 2);&lt;br /&gt;
   define(&amp;quot;STATE_GAME_TURN&amp;quot;, 3);&lt;br /&gt;
   define(&amp;quot;STATE_PLAYER_TURN_CUBES&amp;quot;, 4);&lt;br /&gt;
   define(&amp;quot;STATE_END_GAME&amp;quot;, 99);&lt;br /&gt;
}&lt;br /&gt;
 &lt;br /&gt;
$machinestates = array(&lt;br /&gt;
&lt;br /&gt;
   ...&lt;br /&gt;
&lt;br /&gt;
    STATE_PLAYER_TURN =&amp;gt; array(&lt;br /&gt;
    		&amp;quot;name&amp;quot; =&amp;gt; &amp;quot;playerTurn&amp;quot;,&lt;br /&gt;
    		&amp;quot;description&amp;quot; =&amp;gt; clienttranslate(&#039;${actplayer} must select an Action Space or Pass&#039;),&lt;br /&gt;
    		&amp;quot;descriptionmyturn&amp;quot; =&amp;gt; clienttranslate(&#039;${you} must select an Action Space or Pass&#039;),&lt;br /&gt;
    		&amp;quot;type&amp;quot; =&amp;gt; &amp;quot;activeplayer&amp;quot;,&lt;br /&gt;
                &amp;quot;args&amp;quot; =&amp;gt; &#039;arg_playerTurn&#039;,&lt;br /&gt;
    		&amp;quot;possibleactions&amp;quot; =&amp;gt; array( &amp;quot;actSelectWorkerAction&amp;quot;, &amp;quot;actPass&amp;quot; ),&lt;br /&gt;
    		&amp;quot;transitions&amp;quot; =&amp;gt; array( &lt;br /&gt;
    		        &amp;quot;loopback&amp;quot; =&amp;gt; STATE_PLAYER_TURN,&lt;br /&gt;
    		        &amp;quot;playCubes&amp;quot; =&amp;gt; STATE_PLAYER_TURN_CUBES,&lt;br /&gt;
    		        &amp;quot;pass&amp;quot; =&amp;gt; STATE_GAME_TURN )&lt;br /&gt;
    ),&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Example of multipleactiveplayer state ===&lt;br /&gt;
&lt;br /&gt;
This is an example of a multipleactiveplayer state:&lt;br /&gt;
&lt;br /&gt;
  2 =&amp;gt;  array (&lt;br /&gt;
    &#039;name&#039; =&amp;gt; &#039;playerTurnSetup&#039;,&lt;br /&gt;
    &#039;type&#039; =&amp;gt; &#039;multipleactiveplayer&#039;,&lt;br /&gt;
    &#039;description&#039; =&amp;gt; clienttranslate(&#039;Other players must choose one Objective&#039;),&lt;br /&gt;
    &#039;descriptionmyturn&#039; =&amp;gt; clienttranslate(&#039;${you} must choose one Objective card to keep&#039;),&lt;br /&gt;
    &#039;possibleactions&#039; =&amp;gt;     array (&#039;actPlayKeep&#039; ),&lt;br /&gt;
    &#039;transitions&#039; =&amp;gt;    array (       &#039;next&#039; =&amp;gt; 5, &#039;loopback&#039; =&amp;gt; 2, ),&lt;br /&gt;
    &#039;action&#039; =&amp;gt; &#039;st_MultiPlayerInit&#039;,&lt;br /&gt;
    &#039;args&#039; =&amp;gt; &#039;arg_playerTurnSetup&#039;,&lt;br /&gt;
  ),&lt;br /&gt;
&lt;br /&gt;
In game.php:&lt;br /&gt;
    // this will make all players multiactive just before entering the state&lt;br /&gt;
    function st_MultiPlayerInit() {&lt;br /&gt;
        $this-&amp;gt;gamestate-&amp;gt;setAllPlayersMultiactive();&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
Note: if you want exact this function its already defined in table class its called &#039;stMakeEveryoneActive&#039;&lt;br /&gt;
&lt;br /&gt;
When ending the player action, instead of a state transition, deactivate player.&lt;br /&gt;
&lt;br /&gt;
    function actPlayKeep($cardId) {&lt;br /&gt;
        $this-&amp;gt;checkAction(&#039;actPlayKeep&#039;);&lt;br /&gt;
        $player_id = $this-&amp;gt;getCurrentPlayerId(); // CURRENT!!! not active&lt;br /&gt;
        ... // some logic here&lt;br /&gt;
        $this-&amp;gt;gamestate-&amp;gt;setPlayerNonMultiactive($player_id, &#039;next&#039;); // deactivate player; if none left, transition to &#039;next&#039; state&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
=== Difference between Single active and Multi active states ===&lt;br /&gt;
In a classic &amp;quot;activePlayer&amp;quot; state:&lt;br /&gt;
&lt;br /&gt;
* You cannot change the active player DURING the state. This is to ensure that during 1 activePlayer state, only ONE player is active&lt;br /&gt;
* As a consequence, you must set the active player BEFORE entering the activePlayer state&lt;br /&gt;
* In such states on JS side onUpdateActionButtons is called before onEnteringState during game play (but after during reload, i.e. F5)&lt;br /&gt;
* Finally, during onEnteringState, on JS side, the active player is signaled as active and the information is reliable and usable.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
In a &amp;quot;multiplePlayer&amp;quot; state:&lt;br /&gt;
&lt;br /&gt;
* You can (and must) change the active players DURING the state&lt;br /&gt;
* During such a state, players can be activated/desactivated anytime during the state, giving you the maximum of possibilities.&lt;br /&gt;
* You shouldn&#039;t set active player before entering the state. But you can set it in &amp;quot;state initializer&amp;quot; php function (see example above st_MultiPlayerInit)&lt;br /&gt;
* Finally, during onEnteringState, on JS side, the active players are NOT active yet so you must use onUpdateActionButtons to perform the client side operation which depends on a player active/inactive status.&lt;br /&gt;
&lt;br /&gt;
Note: in some off cases other players can perform special actions even if they are not active, see example https://en.doc.boardgamearena.com/BGA_Studio_Cookbook#Out-of-turn_actions%3A_Un-pass. Do not abuse this technique!&lt;br /&gt;
&lt;br /&gt;
=== Designing states ===&lt;br /&gt;
&lt;br /&gt;
As a general rule you state machine should resemble &amp;quot;round/turn overview&amp;quot; from the game rule-book. Normally if book say its player turn and player can do multiple things during their turn it is still only&lt;br /&gt;
one player state (plus a game to switch player), not muliple states.&lt;br /&gt;
&lt;br /&gt;
In a classic game (i.e. chess), there is only active player at any time, so it is simple playerTurn/gameTurn sequence and you only need 2 states.&lt;br /&gt;
&lt;br /&gt;
[[File:Simplestates.png]]&lt;br /&gt;
&lt;br /&gt;
In complex euro game there can be multiple rounds, and each round have phases which can be distinctly unique, i.e. in first phase everybody draws card and discard (multi-player), then player have one turn each (single-active), then another is resolution of actions from players and some of them may become active again, then there is round upkeep/reset. This would require one multi-player state for phase 1, pair of states for phase2 (singel-active + game), pair of states for phase3 and finally round-end/unkeep game state.&lt;br /&gt;
&lt;br /&gt;
For pair of active player/game states you can make player state first, which transitions to game state, or the other way around, you start with game state which transition to active player state, its loop in any case but depends on how you want to do &amp;quot;phase&amp;quot; initiazations.&lt;br /&gt;
&lt;br /&gt;
[[File:Eurogamestates.png]]&lt;br /&gt;
&lt;br /&gt;
=== Complete examples ===&lt;br /&gt;
&lt;br /&gt;
Example of simple game where player take turns&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
if ( !defined(&#039;STATE_END_GAME&#039;)) { // guard since this included multiple times&lt;br /&gt;
    define(&amp;quot;STATE_PLAYER_TURN&amp;quot;, 2);&lt;br /&gt;
    define(&amp;quot;STATE_GAME_TURN_NEXT_PLAYER&amp;quot;, 3);&lt;br /&gt;
    define(&amp;quot;STATE_PLAYER_GAME_END&amp;quot;, 4);&lt;br /&gt;
    define(&amp;quot;STATE_END_GAME&amp;quot;, 99);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
$machinestates = [    &lt;br /&gt;
        1 =&amp;gt; [ // The initial state. Please do not modify.&lt;br /&gt;
               &amp;quot;name&amp;quot; =&amp;gt; &amp;quot;gameSetup&amp;quot;,&lt;br /&gt;
               &amp;quot;description&amp;quot; =&amp;gt; &amp;quot;&amp;quot;,&lt;br /&gt;
               &amp;quot;type&amp;quot; =&amp;gt; &amp;quot;manager&amp;quot;,&lt;br /&gt;
               &amp;quot;action&amp;quot; =&amp;gt; &amp;quot;stGameSetup&amp;quot;,&lt;br /&gt;
               &amp;quot;transitions&amp;quot; =&amp;gt; [ &amp;quot;&amp;quot; =&amp;gt; STATE_PLAYER_TURN ] ],&lt;br /&gt;
        // Game states &lt;br /&gt;
        STATE_PLAYER_TURN =&amp;gt; [ // main active player state &lt;br /&gt;
                &amp;quot;name&amp;quot; =&amp;gt; &amp;quot;playerTurn&amp;quot;,&lt;br /&gt;
                &amp;quot;description&amp;quot; =&amp;gt; clienttranslate(&#039;${actplayer} must do something or pass&#039;),&lt;br /&gt;
                &amp;quot;descriptionmyturn&amp;quot; =&amp;gt; clienttranslate(&#039;${you} must do something or pass&#039;),&lt;br /&gt;
                &amp;quot;type&amp;quot; =&amp;gt; &amp;quot;activeplayer&amp;quot;,&lt;br /&gt;
                &amp;quot;args&amp;quot; =&amp;gt; &amp;quot;arg_playerTurn&amp;quot;,&lt;br /&gt;
                &amp;quot;possibleactions&amp;quot; =&amp;gt; [ &amp;quot;actDSomething&amp;quot;,&amp;quot;actPass&amp;quot; ],&lt;br /&gt;
                &amp;quot;transitions&amp;quot; =&amp;gt; [ &amp;quot;next&amp;quot; =&amp;gt; STATE_GAME_TURN_NEXT_PLAYER,&amp;quot;last&amp;quot; =&amp;gt; STATE_PLAYER_GAME_END ] // &lt;br /&gt;
        ],&lt;br /&gt;
        STATE_GAME_TURN_NEXT_PLAYER =&amp;gt; [ // next player state&lt;br /&gt;
                &amp;quot;name&amp;quot; =&amp;gt; &amp;quot;gameTurnNextPlayer&amp;quot;,&lt;br /&gt;
                &amp;quot;description&amp;quot; =&amp;gt; clienttranslate(&#039;Upkeep...&#039;),&lt;br /&gt;
                &amp;quot;type&amp;quot; =&amp;gt; &amp;quot;game&amp;quot;, //&lt;br /&gt;
                &amp;quot;action&amp;quot; =&amp;gt; &amp;quot;st_gameTurnNextPlayer&amp;quot;, //&lt;br /&gt;
                &amp;quot;updateGameProgression&amp;quot; =&amp;gt; true,&lt;br /&gt;
                &amp;quot;transitions&amp;quot; =&amp;gt; [ &amp;quot;next&amp;quot; =&amp;gt; STATE_PLAYER_TURN,&amp;quot;loopback&amp;quot; =&amp;gt; STATE_GAME_TURN_NEXT_PLAYER,&lt;br /&gt;
                        &amp;quot;last&amp;quot; =&amp;gt; STATE_PLAYER_GAME_END ], // TODO replace with STATE_END_GAME, its there to use undo/restore during dev&lt;br /&gt;
        ],&lt;br /&gt;
    &lt;br /&gt;
        STATE_PLAYER_GAME_END =&amp;gt; [ // active player state for debugging end of game&lt;br /&gt;
                &amp;quot;name&amp;quot; =&amp;gt; &amp;quot;playerGameEnd&amp;quot;,&lt;br /&gt;
                &amp;quot;description&amp;quot; =&amp;gt; clienttranslate(&#039;${actplayer} Game Over&#039;),&lt;br /&gt;
                &amp;quot;descriptionmyturn&amp;quot; =&amp;gt; clienttranslate(&#039;${you} Game Over&#039;),&lt;br /&gt;
                &amp;quot;type&amp;quot; =&amp;gt; &amp;quot;activeplayer&amp;quot;,&lt;br /&gt;
                &amp;quot;args&amp;quot; =&amp;gt; &amp;quot;arg_playerTurn&amp;quot;,&lt;br /&gt;
                &amp;quot;possibleactions&amp;quot; =&amp;gt; [&amp;quot;actEndGame&amp;quot;],&lt;br /&gt;
                &amp;quot;transitions&amp;quot; =&amp;gt; [&amp;quot;next&amp;quot; =&amp;gt; STATE_END_GAME,&amp;quot;loopback&amp;quot; =&amp;gt; STATE_PLAYER_GAME_END ] // &lt;br /&gt;
        ],&lt;br /&gt;
        // End of Game states &lt;br /&gt;
        // Final state.&lt;br /&gt;
        // Please do not modify (and do not overload action/args methods).&lt;br /&gt;
        STATE_END_GAME =&amp;gt; [&lt;br /&gt;
                &amp;quot;name&amp;quot; =&amp;gt; &amp;quot;gameEnd&amp;quot;,&lt;br /&gt;
                &amp;quot;description&amp;quot; =&amp;gt; clienttranslate(&amp;quot;End of game&amp;quot;),&amp;quot;type&amp;quot; =&amp;gt; &amp;quot;manager&amp;quot;,&lt;br /&gt;
                &amp;quot;action&amp;quot; =&amp;gt; &amp;quot;stGameEnd&amp;quot;,&lt;br /&gt;
                &amp;quot;args&amp;quot; =&amp;gt; &amp;quot;argGameEnd&amp;quot; ] &lt;br /&gt;
&lt;br /&gt;
];&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Category:Studio]]&lt;/div&gt;</summary>
		<author><name>Sguzzer Gunayer</name></author>
	</entry>
	<entry>
		<id>https://en.doc.boardgamearena.com/index.php?title=Options_and_preferences:_gameoptions.json,_gamepreferences.json&amp;diff=22491</id>
		<title>Options and preferences: gameoptions.json, gamepreferences.json</title>
		<link rel="alternate" type="text/html" href="https://en.doc.boardgamearena.com/index.php?title=Options_and_preferences:_gameoptions.json,_gamepreferences.json&amp;diff=22491"/>
		<updated>2024-09-07T09:42:47Z</updated>

		<summary type="html">&lt;p&gt;Sguzzer Gunayer: /* Migration */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Studio_Framework_Navigation}}&lt;br /&gt;
&lt;br /&gt;
In &amp;lt;code&amp;gt;gameoptions.json&amp;lt;/code&amp;gt;, you can define your game options (i.e. game variants).&lt;br /&gt;
&lt;br /&gt;
In &amp;lt;code&amp;gt;gamepreferences.json&amp;lt;/code&amp;gt;, you can define user preferences.&lt;br /&gt;
   &lt;br /&gt;
Note: If your game has no variants or preferences, you don&#039;t have to modify these files.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;IMPORTANT:&#039;&#039;&#039; after edits to these files, you have to go to the control panel and press &amp;quot;Reload game options configuration&amp;quot; on Studio for your changes &#039;&#039;&#039;to take effect&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
Make sure you understand difference between options and preferences:&lt;br /&gt;
* Game options - something usually in the rule book defined as &amp;quot;variant&amp;quot; (except for player count, which is automatically handled). For example, whether to include &#039;&#039;The River&#039;&#039; in Carcassonne.&lt;br /&gt;
* User preferences - personal choices of each player only visible to that specific player - i.e. layout, whether or not to prompt for action, whether or not auto-opt in in some actions, etc.&lt;br /&gt;
&lt;br /&gt;
__TOC__&lt;br /&gt;
&lt;br /&gt;
== Game Options ==&lt;br /&gt;
&lt;br /&gt;
Game options are selected by the table creator and usually correspond to game variants, for example if the game includes expansions or certain special rules.&lt;br /&gt;
&lt;br /&gt;
These variants are defined in &amp;lt;code&amp;gt;gameoptions.json&amp;lt;/code&amp;gt; as an object:  &lt;br /&gt;
&lt;br /&gt;
  {&lt;br /&gt;
     &amp;quot;100&amp;quot;: { &amp;quot;name&amp;quot;: &amp;quot;Game Setup&amp;quot;, ... },&lt;br /&gt;
     &amp;quot;101&amp;quot;: { &amp;quot;name&amp;quot;: &amp;quot;Draft&amp;quot;, ... }&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
Each key corresponds to the option id, and each value is that option definition, which is described below.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note:&#039;&#039;&#039; the file must be valid [https://www.json.org/ JSON]. That is, trailing commas and comments are not allowed. However you can use still standard json hack to add a field like &amp;quot;$comment&amp;quot;: &amp;quot;Here we go&amp;quot;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note 2:&#039;&#039;&#039; the key in json file must be a string type, even its correspond to a number in other places (such as php, or other references in same json).&lt;br /&gt;
&lt;br /&gt;
All options defined in this file should have a corresponding &amp;quot;game state label&amp;quot; with the same ID (see &amp;quot;initGameStateLabels&amp;quot; in yourgame.game.php)&lt;br /&gt;
&lt;br /&gt;
             self::initGameStateLabels ([&lt;br /&gt;
                        ...&lt;br /&gt;
                        &amp;quot;my_game_variant&amp;quot; =&amp;gt; 100,&lt;br /&gt;
              ]);&lt;br /&gt;
&lt;br /&gt;
Numbers have to be exactly from 100 to 199 (there can be gaps).&lt;br /&gt;
&lt;br /&gt;
That is how you access them during runtime (by name):&lt;br /&gt;
&lt;br /&gt;
    public function isSecondVariant() {&lt;br /&gt;
        return $this-&amp;gt;getGameStateValue(&#039;my_game_variant&#039;) == 2;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
Or this (by numberic id)&lt;br /&gt;
    $this-&amp;gt;gamestate-&amp;gt;table_globals[100]&lt;br /&gt;
To access json data (the metadata only) can use&lt;br /&gt;
   $game_options = $this-&amp;gt;getTableOptions();&lt;br /&gt;
=== Details of game options format ===&lt;br /&gt;
&lt;br /&gt;
The following are the values of the option definition object:&lt;br /&gt;
* &#039;&#039;&#039;name&#039;&#039;&#039; - &#039;&#039;&#039;mandatory&#039;&#039;&#039;. The name of the option visible for table creator. This is automatically marked for translation.&lt;br /&gt;
* &#039;&#039;&#039;values&#039;&#039;&#039; - &#039;&#039;&#039;mandatory&#039;&#039;&#039;. The map representing possible values of this option. The key of the map is possible value of this option, its a number but has to be string in json. The value is an object descring it.&lt;br /&gt;
** &#039;&#039;&#039;name&#039;&#039;&#039; - &#039;&#039;&#039;mandatory&#039;&#039;&#039;. String representation of the numeric value visible to table creator. This is automatically marked for translation.&lt;br /&gt;
** &#039;&#039;&#039;description&#039;&#039;&#039; - String description of this value to use when the name of the option is not self-explanatory. Displayed at the table under the option when this value is selected. Note: if there is no description, this should be omitted.&lt;br /&gt;
** &#039;&#039;&#039;tmdisplay&#039;&#039;&#039; - String representation of the option visible in the table description in the lobby. Usually if a variant values are On and Off (default), the tmdisplay would be same as description name when On, and nothing (empty string) when Off. (&#039;&#039;&#039;Warning&#039;&#039;&#039;: due to some caching, a change in tmdisplay may not be effective immediately in the studio, even after forcing a reload of options.) &#039;&#039;&#039;Pro Tip:&#039;&#039;&#039; You can use this as a pre-game communication by adding fake options that just do nothing in the game but make it easier to find other player wanted the same game configuration (see the crew deep sea for example).&lt;br /&gt;
** &#039;&#039;&#039;nobeginner&#039;&#039;&#039; - Set to true if not recommended for beginners&lt;br /&gt;
** &#039;&#039;&#039;firstgameonly&#039;&#039;&#039; - Set to true if this option is recommended only for the first game (discovery option)&lt;br /&gt;
** &#039;&#039;&#039;beta&#039;&#039;&#039; - Set to true to indicate that this option is in &amp;quot;beta&amp;quot; development stage (there will be a warning for players starting the game)&lt;br /&gt;
** &#039;&#039;&#039;alpha&#039;&#039;&#039; - Set to true to indicate that this option is in &amp;quot;alpha&amp;quot; development stage (there will be a warning, and starting the game will be allowed only in training mode except for the developer)&lt;br /&gt;
** &#039;&#039;&#039;premium&#039;&#039;&#039; - Option can be only used by premium members&lt;br /&gt;
* &#039;&#039;&#039;default&#039;&#039;&#039; - indicates the default value to use for this option (optional, if not present the first value listed is the default)&lt;br /&gt;
* &#039;&#039;&#039;displaycondition&#039;&#039;&#039; - (array of conditions) - checks the conditions before displaying the option for selection. All (or any) conditions must be true for the option to be displayed. All or any depends on value of displayconditionoperand&lt;br /&gt;
Supported display condition types:&lt;br /&gt;
** &#039;&#039;minplayers&#039;&#039; condition ensures at least this many players (Note: if your game works with a disjoint interval of player counts, you can supply an array of valid counts instead of a single value)&lt;br /&gt;
** &#039;&#039;maxplayers&#039;&#039; condition ensures at most this many players&lt;br /&gt;
** &#039;&#039;otheroption&#039;&#039; condition ensures another option is set to given values. &lt;br /&gt;
** &#039;&#039;otheroptionisnot&#039;&#039; condition ensure another option is NOT set to this given values&lt;br /&gt;
* &#039;&#039;&#039;displayconditionoperand&#039;&#039;&#039; - can be &#039;and&#039; (this is the default) or &#039;or&#039;. Allows to change the behaviour to display the option if one of the conditions is true instead of all of them.&lt;br /&gt;
* &#039;&#039;&#039;startcondition&#039;&#039;&#039; - (map from value to conditions array) - checks the conditions (on options VALUES) before starting the game. All conditions must be true for the game to start, otherwise players will get a red error message when attempting to begin the game. &lt;br /&gt;
Supported start condition types:&lt;br /&gt;
** &#039;&#039;minplayers&#039;&#039; condition ensures at least this many players (an array of values is not supported here)&lt;br /&gt;
** &#039;&#039;maxplayers&#039;&#039; condition ensures at most this many players&lt;br /&gt;
** &#039;&#039;otheroption&#039;&#039; conditions ensure another option is set to this given values. That works the same as in &#039;&#039;&#039;displaycondition&#039;&#039;&#039;.&lt;br /&gt;
** &#039;&#039;otheroptionisnot&#039;&#039; conditions ensure another option is NOT set to this given value.  That works the same as in &#039;&#039;&#039;displaycondition&#039;&#039;&#039;.&lt;br /&gt;
*: For all these condition types, a &#039;&#039;gamestartonly&#039;&#039; boolean option can be added, if you have options that are exclusive. Setting this boolean to &#039;&#039;true&#039;&#039; will defer the evaluation of the startcondition to the game creation, instead of preventing the player to select options that are exclusive at all. See [[#gamestartonly|below]] for an example. &amp;lt;span style=&amp;quot;background: #FFCDD2; color: #B71C1C; padding: 2px;&amp;quot;&amp;gt;But this should never be used -- see the warning below&amp;lt;/span&amp;gt;&lt;br /&gt;
* &#039;&#039;&#039;notdisplayedmessage&#039;&#039;&#039; - if option is not suppose to be visible because of displaycondition but this is set, the text will be visible instead of combo drop down&lt;br /&gt;
* &#039;&#039;&#039;level&#039;&#039;&#039; - what kind of option it is: &#039;&#039;base&#039;&#039;, &#039;&#039;major&#039;&#039;, or &#039;&#039;additional&#039;&#039;. See [[#level|below]] for more informations.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Common (reserved) options for all tables (reserved range 200-299):&lt;br /&gt;
*201 (const GAMESTATE_RATING_MODE) - ELO OFF (aka Training mode), &lt;br /&gt;
**0 = Normal&lt;br /&gt;
**1 = Training&lt;br /&gt;
**2 = Arena&lt;br /&gt;
*200 (const GAMESTATE_CLOCK_MODE) - game speed profile&lt;br /&gt;
**[0, 1, 2] - realtime (technically &amp;lt;10 realtime but you cannot define range in php)&lt;br /&gt;
**values &amp;gt;=10 - turn based (currently 10..21)&lt;br /&gt;
**Note there are two similar values, 9 = realtime &amp;quot;no time limit with friends only&amp;quot; vs. 20 = turn-based &amp;quot;no time limit with friends only&amp;quot;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Example:&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
  &amp;quot;100&amp;quot;: {&lt;br /&gt;
    &amp;quot;name&amp;quot;: &amp;quot;Game Variant&amp;quot;,&lt;br /&gt;
    &amp;quot;values&amp;quot;: {&lt;br /&gt;
      &amp;quot;1&amp;quot;: {&lt;br /&gt;
        &amp;quot;name&amp;quot;: &amp;quot;Learning&amp;quot;,&lt;br /&gt;
        &amp;quot;firstgameonly&amp;quot;: true,&lt;br /&gt;
        &amp;quot;tmdisplay&amp;quot;: &amp;quot;Learning&amp;quot;&lt;br /&gt;
      },&lt;br /&gt;
      &amp;quot;2&amp;quot;: {&lt;br /&gt;
        &amp;quot;name&amp;quot;: &amp;quot;Base&amp;quot;,&lt;br /&gt;
      },&lt;br /&gt;
      &amp;quot;3&amp;quot;: {&lt;br /&gt;
        &amp;quot;name&amp;quot;: &amp;quot;Extended&amp;quot;,&lt;br /&gt;
        &amp;quot;nobeginner&amp;quot;: true,&lt;br /&gt;
        &amp;quot;beta&amp;quot;: true,&lt;br /&gt;
        &amp;quot;tmdisplay&amp;quot;: &amp;quot;Extended&amp;quot;&lt;br /&gt;
      }&lt;br /&gt;
    },&lt;br /&gt;
    &amp;quot;default&amp;quot;: 2&lt;br /&gt;
  },&lt;br /&gt;
  &amp;quot;101&amp;quot;: {&lt;br /&gt;
    &amp;quot;name&amp;quot;: &amp;quot;Draft variant&amp;quot;,&lt;br /&gt;
    &amp;quot;values&amp;quot;: {&lt;br /&gt;
      &amp;quot;1&amp;quot;: {&lt;br /&gt;
        &amp;quot;name&amp;quot;: &amp;quot;No draft&amp;quot;&lt;br /&gt;
      },&lt;br /&gt;
      &amp;quot;2&amp;quot;: {&lt;br /&gt;
        &amp;quot;name&amp;quot;: &amp;quot;Draft&amp;quot;,&lt;br /&gt;
        &amp;quot;tmdisplay&amp;quot;: &amp;quot;Draft&amp;quot;,&lt;br /&gt;
        &amp;quot;premium&amp;quot;: true,&lt;br /&gt;
        &amp;quot;nobeginner&amp;quot;: true&lt;br /&gt;
      }&lt;br /&gt;
    },&lt;br /&gt;
    &amp;quot;displaycondition&amp;quot;: [&lt;br /&gt;
      {&lt;br /&gt;
        &amp;quot;type&amp;quot;: &amp;quot;otheroption&amp;quot;,&lt;br /&gt;
        &amp;quot;id&amp;quot;: 100,&lt;br /&gt;
        &amp;quot;value&amp;quot;: [ 2, 3 ]&lt;br /&gt;
      },&lt;br /&gt;
      {&lt;br /&gt;
        &amp;quot;type&amp;quot;: &amp;quot;otheroption&amp;quot;,&lt;br /&gt;
        &amp;quot;id&amp;quot;: 201,&lt;br /&gt;
        &amp;quot;value&amp;quot;: 1&lt;br /&gt;
      }&lt;br /&gt;
    ],&lt;br /&gt;
    &amp;quot;startcondition&amp;quot;: {&lt;br /&gt;
      &amp;quot;1&amp;quot;: [],&lt;br /&gt;
      &amp;quot;2&amp;quot;: [&lt;br /&gt;
        {&lt;br /&gt;
          &amp;quot;type&amp;quot;: &amp;quot;maxplayers&amp;quot;,&lt;br /&gt;
          &amp;quot;value&amp;quot;: 3,&lt;br /&gt;
          &amp;quot;message&amp;quot;: &amp;quot;Draft option is available for 3 players maximum.&amp;quot;&lt;br /&gt;
        }&lt;br /&gt;
      ]&lt;br /&gt;
    }&lt;br /&gt;
  },&lt;br /&gt;
  &amp;quot;102&amp;quot;: {&lt;br /&gt;
    &amp;quot;name&amp;quot;: &amp;quot;Takeovers&amp;quot;,&lt;br /&gt;
    &amp;quot;values&amp;quot;: {&lt;br /&gt;
      &amp;quot;2&amp;quot;: {&lt;br /&gt;
        &amp;quot;name&amp;quot;: &amp;quot;No takeover&amp;quot;&lt;br /&gt;
      },&lt;br /&gt;
      &amp;quot;1&amp;quot;: {&lt;br /&gt;
        &amp;quot;name&amp;quot;: &amp;quot;Allow takeovers&amp;quot;,&lt;br /&gt;
        &amp;quot;tmdisplay&amp;quot;: &amp;quot;Takeovers&amp;quot;,&lt;br /&gt;
        &amp;quot;premium&amp;quot;: true,&lt;br /&gt;
        &amp;quot;nobeginner&amp;quot;: true&lt;br /&gt;
      }&lt;br /&gt;
    },&lt;br /&gt;
    &amp;quot;displaycondition&amp;quot;: [&lt;br /&gt;
      {&lt;br /&gt;
        &amp;quot;type&amp;quot;: &amp;quot;otheroption&amp;quot;,&lt;br /&gt;
        &amp;quot;id&amp;quot;: 100,&lt;br /&gt;
        &amp;quot;value&amp;quot;: [ 3 ]&lt;br /&gt;
      }&lt;br /&gt;
    ],&lt;br /&gt;
    &amp;quot;startcondition&amp;quot;: {&lt;br /&gt;
      &amp;quot;2&amp;quot;: [],&lt;br /&gt;
      &amp;quot;1&amp;quot;: [&lt;br /&gt;
        {&lt;br /&gt;
          &amp;quot;type&amp;quot;: &amp;quot;maxplayers&amp;quot;,&lt;br /&gt;
          &amp;quot;value&amp;quot;: 2,&lt;br /&gt;
          &amp;quot;message&amp;quot;: &amp;quot;Rebel vs Imperium Takeover Scenario is available for 2 players only.&amp;quot;&lt;br /&gt;
        }&lt;br /&gt;
      ]&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Example of option that condition on ELO off:&#039;&#039;&#039;&lt;br /&gt;
 {&lt;br /&gt;
   &amp;quot;100&amp;quot;: {&lt;br /&gt;
     &amp;quot;name&amp;quot;: &amp;quot;Learning Game (No Research)&amp;quot;,&lt;br /&gt;
     &amp;quot;values&amp;quot;: {&lt;br /&gt;
       &amp;quot;1&amp;quot;: {&lt;br /&gt;
         &amp;quot;name&amp;quot;: &amp;quot;Off&amp;quot;,&lt;br /&gt;
         &amp;quot;tmdisplay&amp;quot;: &amp;quot;&amp;quot;&lt;br /&gt;
       },&lt;br /&gt;
       &amp;quot;2&amp;quot;: {&lt;br /&gt;
         &amp;quot;name&amp;quot;: &amp;quot;On&amp;quot;,&lt;br /&gt;
         &amp;quot;tmdisplay&amp;quot;: &amp;quot;Learning Game&amp;quot;&lt;br /&gt;
       }&lt;br /&gt;
     },&lt;br /&gt;
     &amp;quot;startcondition&amp;quot;: {&lt;br /&gt;
       &amp;quot;2&amp;quot;: {&lt;br /&gt;
         &amp;quot;type&amp;quot;: &amp;quot;otheroption&amp;quot;,&lt;br /&gt;
         &amp;quot;id&amp;quot;: 201,&lt;br /&gt;
         &amp;quot;value&amp;quot;: 1,&lt;br /&gt;
         &amp;quot;message&amp;quot;: &amp;quot;Learning variant available only in friendly mode&amp;quot;&lt;br /&gt;
       }&lt;br /&gt;
     }&lt;br /&gt;
   }&lt;br /&gt;
 }&lt;br /&gt;
&#039;&#039;&#039;Example of condition that is only available for REALTIME game mode:&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;quot;displaycondition&amp;quot;: [&lt;br /&gt;
    { &amp;quot;type&amp;quot;: &amp;quot;otheroption&amp;quot;, &amp;quot;id&amp;quot;: 200, &amp;quot;value&amp;quot;: [0, 1, 2] }&lt;br /&gt;
],&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Example of using condition on your own option:&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
  &amp;quot;102&amp;quot;: {&lt;br /&gt;
    &amp;quot;name&amp;quot;: &amp;quot;Scenarios&amp;quot;,&lt;br /&gt;
    &amp;quot;values&amp;quot;: {&lt;br /&gt;
      &amp;quot;1&amp;quot;: {&lt;br /&gt;
        &amp;quot;name&amp;quot;: &amp;quot;Off&amp;quot;,&lt;br /&gt;
        &amp;quot;nobeginner&amp;quot;: false&lt;br /&gt;
      },&lt;br /&gt;
      &amp;quot;2&amp;quot;: {&lt;br /&gt;
        &amp;quot;name&amp;quot;: &amp;quot;On&amp;quot;,&lt;br /&gt;
        &amp;quot;tmdisplay&amp;quot;: &amp;quot;Scenarios&amp;quot;,&lt;br /&gt;
        &amp;quot;nobeginner&amp;quot;: true&lt;br /&gt;
      }&lt;br /&gt;
    },&lt;br /&gt;
    &amp;quot;displaycondition&amp;quot;: [&lt;br /&gt;
      {&lt;br /&gt;
        &amp;quot;type&amp;quot;: &amp;quot;otheroptionisnot&amp;quot;,&lt;br /&gt;
        &amp;quot;id&amp;quot;: 100,&lt;br /&gt;
        &amp;quot;value&amp;quot;: 1&lt;br /&gt;
      }&lt;br /&gt;
    ],&lt;br /&gt;
    &amp;quot;notdisplayedmessage&amp;quot;: &amp;quot;Scenarios variant is not available if Learning variant is chosen&amp;quot;&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Example of handling solo vs multiplayer options:&#039;&#039;&#039;&amp;lt;pre&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
  &amp;quot;100&amp;quot;: {&lt;br /&gt;
    &amp;quot;name&amp;quot;: &amp;quot;Board setup&amp;quot;,&lt;br /&gt;
    &amp;quot;values&amp;quot;: {&lt;br /&gt;
      &amp;quot;1&amp;quot;: {&lt;br /&gt;
        &amp;quot;name&amp;quot;: &amp;quot;Mirror setup&amp;quot;,&lt;br /&gt;
        &amp;quot;description&amp;quot;: &amp;quot;The starting player shuffles their 6 Farm Cards and randomly lays a card face up in each of the round spaces of their Fruit Island Board. The other players then lay their cards in exactly the same way, copying the order of the starting player.&amp;quot;,&lt;br /&gt;
        &amp;quot;tmdisplay&amp;quot;: &amp;quot;Mirror setup&amp;quot;&lt;br /&gt;
      },&lt;br /&gt;
      &amp;quot;2&amp;quot;: {&lt;br /&gt;
        &amp;quot;name&amp;quot;: &amp;quot;Random setup&amp;quot;,&lt;br /&gt;
        &amp;quot;description&amp;quot;: &amp;quot;Instead of every player copying the same card configuration as the starting player, every player shuffles their Farm Cards and lays down the cards randomly on their Fruit Island Board.&amp;quot;,&lt;br /&gt;
        &amp;quot;tmdisplay&amp;quot;: &amp;quot;Random setup&amp;quot;&lt;br /&gt;
      }&lt;br /&gt;
    },&lt;br /&gt;
    &amp;quot;displaycondition&amp;quot;: [&lt;br /&gt;
      {&lt;br /&gt;
        &amp;quot;type&amp;quot;: &amp;quot;minplayers&amp;quot;,&lt;br /&gt;
        &amp;quot;value&amp;quot;: [&lt;br /&gt;
          2,&lt;br /&gt;
          3,&lt;br /&gt;
          4&lt;br /&gt;
        ]&lt;br /&gt;
      }&lt;br /&gt;
    ]&lt;br /&gt;
  },&lt;br /&gt;
  &amp;quot;102&amp;quot;: {&lt;br /&gt;
    &amp;quot;name&amp;quot;: &amp;quot;Solo difficulty&amp;quot;,&lt;br /&gt;
    &amp;quot;values&amp;quot;: [&lt;br /&gt;
      {&lt;br /&gt;
        &amp;quot;name&amp;quot;: &amp;quot;Banana-apprentice&amp;quot;,&lt;br /&gt;
        &amp;quot;description&amp;quot;: &amp;quot;Do not remove any seed before starting the game.&amp;quot;,&lt;br /&gt;
        &amp;quot;tmdisplay&amp;quot;: &amp;quot;Banana-apprentice&amp;quot;&lt;br /&gt;
      },&lt;br /&gt;
      {&lt;br /&gt;
        &amp;quot;name&amp;quot;: &amp;quot;Pear to the Throne&amp;quot;,&lt;br /&gt;
        &amp;quot;description&amp;quot;: &amp;quot;Remove 1 seed before starting the game.&amp;quot;,&lt;br /&gt;
        &amp;quot;tmdisplay&amp;quot;: &amp;quot;Pear to the Throne&amp;quot;&lt;br /&gt;
      }&lt;br /&gt;
    ],&lt;br /&gt;
    &amp;quot;displaycondition&amp;quot;: [&lt;br /&gt;
      {&lt;br /&gt;
        &amp;quot;type&amp;quot;: &amp;quot;maxplayers&amp;quot;,&lt;br /&gt;
        &amp;quot;value&amp;quot;: 1&lt;br /&gt;
      }&lt;br /&gt;
    ]&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== displaycondition vs startcondition ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;displaycondition&amp;lt;/code&amp;gt; should be used when an option should not be present in the list under certain conditions.&lt;br /&gt;
&lt;br /&gt;
For example, displaying the option which is consistent with the player count.&lt;br /&gt;
&lt;br /&gt;
* 2 player maps: A B C D &lt;br /&gt;
* 3 player maps: E F G H&lt;br /&gt;
* 4 player maps: I J K L&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;startcondition&amp;lt;/code&amp;gt; should be used when a specific combination of option values is invalid, but the option itself still makes sense to show.&lt;br /&gt;
&lt;br /&gt;
For example:&lt;br /&gt;
&lt;br /&gt;
* Player 1 faction: A, B, C, D, E, F, G&lt;br /&gt;
* Player 2 faction: A, B, C, D, E, F, G&lt;br /&gt;
* startcondition: both players can&#039;t be the same faction&lt;br /&gt;
&lt;br /&gt;
These options should both be displayed at all times, but there are some invalid configurations.&lt;br /&gt;
&lt;br /&gt;
The other difference is displaycondition affect option itself, while startcondition affect specific values selected&lt;br /&gt;
&lt;br /&gt;
==== gamestartonly ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;padding: 1em; background: #FFCDD2; color: #B71C1C&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;b&amp;gt;WARNING:&amp;lt;/b&amp;gt; [https://studio.boardgamearena.com/bug?id=104 See studio bug #104]. You should &amp;lt;b&amp;gt;NEVER&amp;lt;/b&amp;gt; use &amp;lt;code&amp;gt;gamestartonly&amp;lt;/code&amp;gt;! Otherwise, you allow players to (unknowingly!) create a turn-based table with impossible options that can never start. Players receive no indication that the option combination they selected is invalid until the last player joins the table (hours or days later) and the game attempts to auto-start. The table won&#039;t start because of the &amp;lt;code&amp;gt;startcondition&amp;lt;/code&amp;gt;, and the table options cannot be changed because it&#039;s a turn-based table, so the table must be abandoned. This is a horrible user experience. Please don&#039;t subject players to this.&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
On the table configuration page, it won&#039;t let you select a combination which is invalid according to &amp;lt;code&amp;gt;startcondition&amp;lt;/code&amp;gt;. Doing so will show a red warning, and will revert the option to the previous value. This means you could end up in a situation where you can&#039;t easily change between certain options (requiring you to set or unset options in a specific order).&lt;br /&gt;
&lt;br /&gt;
The consequence of the &amp;lt;code&amp;gt;gamestartonly&amp;lt;/code&amp;gt; flag is that the player _can_ select an invalid combination. However, when clicking &amp;quot;Start&amp;quot;, an invalid combination will produce an error.&lt;br /&gt;
&lt;br /&gt;
Probably the easiest way to see what the difference is is with an example.&lt;br /&gt;
&lt;br /&gt;
With a _Clans of Caledonia_ table:&lt;br /&gt;
* set to training mode&lt;br /&gt;
* set player count to 1&lt;br /&gt;
* try setting &amp;quot;Clan Auction&amp;quot; to one of the &amp;quot;On&amp;quot; options&lt;br /&gt;
* try starting the game, there&#039;s an error! Ie. &amp;lt;code&amp;gt;&amp;quot;gamestartonly&amp;quot; =&amp;gt; true&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Then, with a _Sushi Go Party!_ table:&lt;br /&gt;
* set number of players to 7&lt;br /&gt;
* try setting &amp;quot;Sushi Go! / Sushi Go Party!&amp;quot; to &amp;quot;Sushi Go!&amp;quot;&lt;br /&gt;
* you can&#039;t set the option! Ie. &amp;lt;code&amp;gt;&amp;quot;gamestartonly&amp;quot; =&amp;gt; false&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In code:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
  &amp;quot;100&amp;quot;: {&lt;br /&gt;
    &amp;quot;name&amp;quot;: &amp;quot;Option name&amp;quot;,&lt;br /&gt;
    &amp;quot;values&amp;quot;: [],&lt;br /&gt;
    &amp;quot;startcondition&amp;quot;: {&lt;br /&gt;
      &amp;quot;1&amp;quot;: [&lt;br /&gt;
        {&lt;br /&gt;
          &amp;quot;type&amp;quot;: &amp;quot;maxplayers&amp;quot;,&lt;br /&gt;
          &amp;quot;value&amp;quot;: 2,&lt;br /&gt;
          &amp;quot;message&amp;quot;: &amp;quot;This option is available for 2 players only.&amp;quot;,&lt;br /&gt;
          &amp;quot;gamestartonly&amp;quot;: true&lt;br /&gt;
        }&lt;br /&gt;
      ]&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== level ====&lt;br /&gt;
Note: at this moment this only have impact in fancy lobby mode, presentation of level or checkboxes are not avaiable via normal table creation ui (such as in studio, or when you click Play button in control panel)&amp;lt;pre&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
    &amp;quot;100&amp;quot;: {&lt;br /&gt;
        &amp;quot;name&amp;quot;: &amp;quot;Option name&amp;quot;,&lt;br /&gt;
        &amp;quot;values&amp;quot;: [...],&lt;br /&gt;
        &amp;quot;level&amp;quot;: &amp;quot;major&amp;quot;&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;base&#039;&#039;&#039; is the default value (you don&#039;t need to specify it).&lt;br /&gt;
* &#039;&#039;&#039;major&#039;&#039;&#039; denotes a major option, which will always be displayed on top, and with a specific UI.&lt;br /&gt;
* &#039;&#039;&#039;additional&#039;&#039;&#039; means this option will not be displayed by default, to unclutter the option panel.&lt;br /&gt;
&lt;br /&gt;
About major options:&lt;br /&gt;
* a game can only have &#039;&#039;&#039;1 major option&#039;&#039;&#039;, and of course, it must be a important game changer.&lt;br /&gt;
* the pictures will default to the standard Game Box, and can be set independently for each value, from the [[Game metadata manager]] (in the &amp;quot;Major Variants&amp;quot; section). Note: this cannot be tested from Studio as there is not studio-only Game metadata manager, to see Major Variants option - the game has to be deployed at least as alpha.&lt;br /&gt;
* the major option can have more than 2 values (there will then be an arrow to slide to the other values, carousel-like)&lt;br /&gt;
* the naming of major variant values should be concise and the values should have descriptive text (not just &amp;quot;enabled&amp;quot; or &amp;quot;disabled&amp;quot;)&lt;br /&gt;
** 👍 Option name &amp;quot;Expansion&amp;quot;, option values &amp;quot;Base game&amp;quot;, &amp;quot;Bigger is Better&amp;quot; =&amp;gt; Displayed as &#039;&#039;&amp;quot;Expansion: Base game&amp;quot;&#039;&#039; or &#039;&#039;&amp;quot;Expansion: Bigger is Better&amp;quot;&#039;&#039;&lt;br /&gt;
** 👎 Option name &amp;quot;Bigger is Better&amp;quot;, option values &amp;quot;Enabled&amp;quot;, &amp;quot;Disabled =&amp;gt; Displayed as &#039;&#039;&amp;quot;Bigger is Better: Enabled&amp;quot;&#039;&#039; or &#039;&#039;&amp;quot;Bigger is Better: Disabled&amp;quot;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
About additional options:&lt;br /&gt;
* please set each option that concerns small details in this category: advanced players will find this option anyway, and it will simplify the interface of the page of your game.&lt;br /&gt;
&lt;br /&gt;
[[File:Option-levels.png|800px|Option levels]]&lt;br /&gt;
&lt;br /&gt;
==== option presentation ====&lt;br /&gt;
&lt;br /&gt;
An option WILL be displayed as a &#039;&#039;&#039;Checkbox&#039;&#039;&#039; instead of a selector if certain conditions are met:&lt;br /&gt;
&lt;br /&gt;
* option has only &#039;&#039;&#039;2 values&#039;&#039;&#039;&lt;br /&gt;
* values are either (case insensitive):&lt;br /&gt;
** &#039;&#039;yes&#039;&#039; and &#039;&#039;no&#039;&#039;&lt;br /&gt;
** &#039;&#039;on&#039;&#039; and &#039;&#039;off&#039;&#039;&lt;br /&gt;
** &#039;&#039;enabled&#039;&#039; and &#039;&#039;disabled&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
The &amp;quot;default&amp;quot; value still has to be specified, and can be &amp;quot;on&amp;quot; or &amp;quot;off&amp;quot; (it&#039;s actually just a difference in display).&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[File:Option-display.png|800px|Example of checkbox display]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== User Preferences ==&lt;br /&gt;
&lt;br /&gt;
User preferences is something cosmetic about the game interface which however can create user wars, so you can satisfy all users&lt;br /&gt;
by giving them individual preferences. You should use this only if it significantly improves the interface for a large proportion of users.&lt;br /&gt;
These preferences appear in the three-line hamburger menu in the top corner of the bga menu (and also at the bottom on the page in the Options tab).  &lt;br /&gt;
&amp;quot;Display game logs&amp;quot; and &amp;quot;Display tooltips&amp;quot; are baked-in by default, but you can extend this list as below. &lt;br /&gt;
&lt;br /&gt;
The preference json slightly resembles options, but these are conceptually different. The numbers comes from diffrent space and do not correspond or conflict with options,&lt;br /&gt;
i.e. preference 100 has nothing to do with option 100. You can use range 100-199 with gaps.&lt;br /&gt;
&lt;br /&gt;
[[File:century_preferences_menu.PNG|400px|The user preferences menu for the game Century]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;&lt;br /&gt;
&#039;&#039;These preferences are a good place to put accessibility options - as Century did for its Colorblind Support.&#039;&#039;&lt;br /&gt;
&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
  &amp;quot;100&amp;quot;: {&lt;br /&gt;
    &amp;quot;name&amp;quot;: &amp;quot;Colorblind Support&amp;quot;,&lt;br /&gt;
    &amp;quot;needReload&amp;quot;: true,&lt;br /&gt;
    &amp;quot;values&amp;quot;: {&lt;br /&gt;
      &amp;quot;1&amp;quot;: {&lt;br /&gt;
        &amp;quot;name&amp;quot;: &amp;quot;None&amp;quot;,&lt;br /&gt;
        &amp;quot;cssPref&amp;quot;: &amp;quot;colorblind_off&amp;quot;&lt;br /&gt;
      },&lt;br /&gt;
      &amp;quot;2&amp;quot;: {&lt;br /&gt;
        &amp;quot;name&amp;quot;: &amp;quot;Numbers&amp;quot;,&lt;br /&gt;
        &amp;quot;cssPref&amp;quot;: &amp;quot;colorblind_on&amp;quot;&lt;br /&gt;
      },&lt;br /&gt;
      &amp;quot;3&amp;quot;: {&lt;br /&gt;
        &amp;quot;name&amp;quot;: &amp;quot;Shapes&amp;quot;,&lt;br /&gt;
        &amp;quot;cssPref&amp;quot;: &amp;quot;colorblind_shapes&amp;quot;&lt;br /&gt;
      }&lt;br /&gt;
    },&lt;br /&gt;
    &amp;quot;default&amp;quot;: 1&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
There is two ways to check/apply this. In javascript&lt;br /&gt;
&lt;br /&gt;
  if (this.getGameUserPreference(100) == 2) ...&lt;br /&gt;
&lt;br /&gt;
This checks if preferences 100 has selected value 2.&lt;br /&gt;
&lt;br /&gt;
Second, if cssPref is specified, it will be applied to the &#039;&#039;&#039;&amp;lt;html&amp;gt;&#039;&#039;&#039; tag. So you can use different css styling for the preference. Note: you also need to set needReload to true for that class change to be effective.&lt;br /&gt;
&lt;br /&gt;
As user you have to select them from the Gear menu when game is started. On studio only dev0 account will have it actually working (bug?).&lt;br /&gt;
&lt;br /&gt;
The following are the parameters of preferences description array:&lt;br /&gt;
* &#039;&#039;&#039;name&#039;&#039;&#039; - &#039;&#039;&#039;mandatory&#039;&#039;&#039;. The name of the preference. This string is marked for translation.&lt;br /&gt;
* &#039;&#039;&#039;needReload&#039;&#039;&#039; - If set to true, the game interface will auto-reload after a change of the preference.&lt;br /&gt;
* &#039;&#039;&#039;values&#039;&#039;&#039; - &#039;&#039;&#039;mandatory&#039;&#039;&#039;. The map of values with additional parameters per value.&lt;br /&gt;
** &#039;&#039;&#039;name&#039;&#039;&#039; - &#039;&#039;&#039;mandatory&#039;&#039;&#039;. String representation of the numeric value.  This string is marked for translation.&lt;br /&gt;
** &#039;&#039;&#039;cssPref&#039;&#039;&#039; - CSS class to add to the &#039;&#039;&#039;&amp;lt;html&amp;gt;&#039;&#039;&#039; tag. Currently it is added or removed only after a reload (see needReload).&lt;br /&gt;
* &#039;&#039;&#039;default&#039;&#039;&#039; - Indicates the default value to use for this preference (optional, if not present the first value listed is the default).&lt;br /&gt;
&lt;br /&gt;
=== Listening for preference changes and updating preference from code ===&lt;br /&gt;
The BGA framework offers read/write and callback for user preference changes. See [[Game interface logic: yourgamename.js#User preferences]]&lt;br /&gt;
&lt;br /&gt;
=== Accessing User Preferences on the server ===&lt;br /&gt;
PHP has a variable called $this-&amp;gt;player_preferences.&lt;br /&gt;
This contains a table of player preferences, ONLY accessible in setupNewGame().&lt;br /&gt;
You can use this to populate a table that you manage yourself.&lt;br /&gt;
You have to update the table when a player changes preference (and you have to hook up a listener and initiate an AJAX call out-of-turn).&lt;br /&gt;
Check the code of Agricola for details but this should work:&lt;br /&gt;
&lt;br /&gt;
; In dbmodel.sql&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
CREATE TABLE IF NOT EXISTS `user_preferences` (&lt;br /&gt;
  `player_id` int(10) NOT NULL,&lt;br /&gt;
  `pref_id` int(10) NOT NULL,&lt;br /&gt;
  `pref_value` int(10) NOT NULL,&lt;br /&gt;
  PRIMARY KEY (`player_id`, `pref_id`)&lt;br /&gt;
) ENGINE=InnoDB DEFAULT CHARSET=utf8;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
; In ggg.game.php&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
protected function setupNewGame($players, $options = array())&lt;br /&gt;
{&lt;br /&gt;
// TODO: Save $this-&amp;gt;player_preferences: key is player_id, value is array with pref_id as key and pref_value as value&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Warning: &amp;lt;code&amp;gt;$this-&amp;gt;player_preferences[$player_id]&amp;lt;/code&amp;gt; can be null if the player has not set any player preferences.&lt;br /&gt;
&lt;br /&gt;
Note: to access json values you can call:&lt;br /&gt;
   $game_preferences = $this-&amp;gt;getTablePreferences();&lt;br /&gt;
&lt;br /&gt;
Warning: if you use bga undo system make sure this table is not restored from undo state, as this likely independed from it&lt;br /&gt;
&lt;br /&gt;
; In ggg.js&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
// use code for initPreferencesObserver from above example&lt;br /&gt;
&lt;br /&gt;
onGameUserPreferenceChanged(prefId, prefValue) {&lt;br /&gt;
    if (prefId === 101 /*TODO: You probably want to send only some preferences*/) {&lt;br /&gt;
        // TODO: Code your own action in ggg.action.php and send it prefId and prefValue&lt;br /&gt;
        //       The on the server side you can save it all in the user_preferences&lt;br /&gt;
        //       table you created above.&lt;br /&gt;
    }&lt;br /&gt;
},&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Translations ==&lt;br /&gt;
Note that any name or description values in these JSON files are automatically added to the translation system.&lt;br /&gt;
&lt;br /&gt;
== Migration ==&lt;br /&gt;
Previously, options and preferences were specified in a single &amp;lt;code&amp;gt;gameoptions.inc.php&amp;lt;/code&amp;gt; file.&lt;br /&gt;
&lt;br /&gt;
BGA has switched to a JSON format to make parsing easier on the server-side, and to avoid a reliance on PHP for static config.&lt;br /&gt;
&lt;br /&gt;
The PHP format will continue to work for &#039;&#039;existing&#039;&#039; games, and although preferred, there is no need to migrate unless you want to. However, newly created games must use the new format.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note&#039;&#039;&#039;: once a game has been committed with a &amp;lt;code&amp;gt;gameoptions.json&amp;lt;/code&amp;gt; file, however, it is not possible to go back without admin intervention.&lt;br /&gt;
&lt;br /&gt;
If you want to migrate:&lt;br /&gt;
&lt;br /&gt;
Simple method:&lt;br /&gt;
* Go to studio and press Reload game options configuration&lt;br /&gt;
* It will dump json on the log window - you can take this, format it and save into 2 files (if you have both). For gamepreference.json remove option &amp;quot;200&amp;quot; - this is default common option, it should not be in your file.&lt;br /&gt;
&lt;br /&gt;
Manual method:&lt;br /&gt;
* Remove all calls to &amp;lt;code&amp;gt;totranslate()&amp;lt;/code&amp;gt;, and replace with the plain string&lt;br /&gt;
* Remove any references to BGA&#039;s PHP constants, such as GAMESTATE_RATING_MODE, and replace with the plain value (in this case, 201)&lt;br /&gt;
* You can populate &amp;lt;code&amp;gt;gameinfos.json&amp;lt;/code&amp;gt; with the result of &amp;lt;code&amp;gt;json_encode($game_options, JSON_PRETTY_PRINT)&amp;lt;/code&amp;gt;&lt;br /&gt;
* You can populate &amp;lt;code&amp;gt;gamepreferences.json&amp;lt;/code&amp;gt; with the result of &amp;lt;code&amp;gt;json_encode($game_preferences, JSON_PRETTY_PRINT)&amp;lt;/code&amp;gt;&lt;br /&gt;
* If you include gameoptions.inc.php directly, to read the values, then replace those calls with &amp;lt;code&amp;gt;$this-&amp;gt;getTableOptions()&amp;lt;/code&amp;gt; or &amp;lt;code&amp;gt;$this-&amp;gt;getTablePreferences()&amp;lt;/code&amp;gt; as appropriate which return arrays parsed from the JSON files&lt;br /&gt;
This message was posted to the developer Discord channel:&amp;lt;blockquote&amp;gt;&#039;&#039;&#039;Game options change (Optional!)&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;gameoptions.inc.php&amp;lt;/code&amp;gt; is now considered legacy, and &amp;lt;code&amp;gt;gameoptions.json&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;gamepreferences.json&amp;lt;/code&amp;gt; are recommended for new projects:&lt;br /&gt;
&lt;br /&gt;
* The wiki and the template project have been updated: [[Options and preferences: gameoptions.json, gamepreferences.json#User Preferences|https://en.doc.boardgamearena.com/Options_and_preferences:_gameoptions.json,_gamepreferences.json]]&lt;br /&gt;
* Any questions/problems can come to me, or can be asked here.&lt;br /&gt;
* The format of the json files matches the format of the old php files&lt;br /&gt;
&lt;br /&gt;
We realise there are some drawbacks (sorry!):&lt;br /&gt;
&lt;br /&gt;
* No comments in the JSON file, meaning you have to check the wiki for examples&lt;br /&gt;
* No PHP constants in the JSON file, meaning magic numbers&lt;br /&gt;
&lt;br /&gt;
However, we hope it&#039;s good for BGA because:&lt;br /&gt;
&lt;br /&gt;
* Simpler to parse (for robots and humans)&lt;br /&gt;
* Easier to check for errors (we could perhaps use an XSLT one day)&lt;br /&gt;
* No need to run game-specific PHP code on the metasite&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;NOTE&#039;&#039;&#039;: Switching is totally optional, and the legacy files will still work for existing projects, and for those who know about them. &amp;lt;/blockquote&amp;gt;&lt;br /&gt;
[[Category:Studio]]&lt;/div&gt;</summary>
		<author><name>Sguzzer Gunayer</name></author>
	</entry>
	<entry>
		<id>https://en.doc.boardgamearena.com/index.php?title=Options_and_preferences:_gameoptions.json,_gamepreferences.json&amp;diff=22490</id>
		<title>Options and preferences: gameoptions.json, gamepreferences.json</title>
		<link rel="alternate" type="text/html" href="https://en.doc.boardgamearena.com/index.php?title=Options_and_preferences:_gameoptions.json,_gamepreferences.json&amp;diff=22490"/>
		<updated>2024-09-07T09:28:11Z</updated>

		<summary type="html">&lt;p&gt;Sguzzer Gunayer: /* User Preferences */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Studio_Framework_Navigation}}&lt;br /&gt;
&lt;br /&gt;
In &amp;lt;code&amp;gt;gameoptions.json&amp;lt;/code&amp;gt;, you can define your game options (i.e. game variants).&lt;br /&gt;
&lt;br /&gt;
In &amp;lt;code&amp;gt;gamepreferences.json&amp;lt;/code&amp;gt;, you can define user preferences.&lt;br /&gt;
   &lt;br /&gt;
Note: If your game has no variants or preferences, you don&#039;t have to modify these files.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;IMPORTANT:&#039;&#039;&#039; after edits to these files, you have to go to the control panel and press &amp;quot;Reload game options configuration&amp;quot; on Studio for your changes &#039;&#039;&#039;to take effect&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
Make sure you understand difference between options and preferences:&lt;br /&gt;
* Game options - something usually in the rule book defined as &amp;quot;variant&amp;quot; (except for player count, which is automatically handled). For example, whether to include &#039;&#039;The River&#039;&#039; in Carcassonne.&lt;br /&gt;
* User preferences - personal choices of each player only visible to that specific player - i.e. layout, whether or not to prompt for action, whether or not auto-opt in in some actions, etc.&lt;br /&gt;
&lt;br /&gt;
__TOC__&lt;br /&gt;
&lt;br /&gt;
== Game Options ==&lt;br /&gt;
&lt;br /&gt;
Game options are selected by the table creator and usually correspond to game variants, for example if the game includes expansions or certain special rules.&lt;br /&gt;
&lt;br /&gt;
These variants are defined in &amp;lt;code&amp;gt;gameoptions.json&amp;lt;/code&amp;gt; as an object:  &lt;br /&gt;
&lt;br /&gt;
  {&lt;br /&gt;
     &amp;quot;100&amp;quot;: { &amp;quot;name&amp;quot;: &amp;quot;Game Setup&amp;quot;, ... },&lt;br /&gt;
     &amp;quot;101&amp;quot;: { &amp;quot;name&amp;quot;: &amp;quot;Draft&amp;quot;, ... }&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
Each key corresponds to the option id, and each value is that option definition, which is described below.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note:&#039;&#039;&#039; the file must be valid [https://www.json.org/ JSON]. That is, trailing commas and comments are not allowed. However you can use still standard json hack to add a field like &amp;quot;$comment&amp;quot;: &amp;quot;Here we go&amp;quot;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note 2:&#039;&#039;&#039; the key in json file must be a string type, even its correspond to a number in other places (such as php, or other references in same json).&lt;br /&gt;
&lt;br /&gt;
All options defined in this file should have a corresponding &amp;quot;game state label&amp;quot; with the same ID (see &amp;quot;initGameStateLabels&amp;quot; in yourgame.game.php)&lt;br /&gt;
&lt;br /&gt;
             self::initGameStateLabels ([&lt;br /&gt;
                        ...&lt;br /&gt;
                        &amp;quot;my_game_variant&amp;quot; =&amp;gt; 100,&lt;br /&gt;
              ]);&lt;br /&gt;
&lt;br /&gt;
Numbers have to be exactly from 100 to 199 (there can be gaps).&lt;br /&gt;
&lt;br /&gt;
That is how you access them during runtime (by name):&lt;br /&gt;
&lt;br /&gt;
    public function isSecondVariant() {&lt;br /&gt;
        return $this-&amp;gt;getGameStateValue(&#039;my_game_variant&#039;) == 2;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
Or this (by numberic id)&lt;br /&gt;
    $this-&amp;gt;gamestate-&amp;gt;table_globals[100]&lt;br /&gt;
To access json data (the metadata only) can use&lt;br /&gt;
   $game_options = $this-&amp;gt;getTableOptions();&lt;br /&gt;
=== Details of game options format ===&lt;br /&gt;
&lt;br /&gt;
The following are the values of the option definition object:&lt;br /&gt;
* &#039;&#039;&#039;name&#039;&#039;&#039; - &#039;&#039;&#039;mandatory&#039;&#039;&#039;. The name of the option visible for table creator. This is automatically marked for translation.&lt;br /&gt;
* &#039;&#039;&#039;values&#039;&#039;&#039; - &#039;&#039;&#039;mandatory&#039;&#039;&#039;. The map representing possible values of this option. The key of the map is possible value of this option, its a number but has to be string in json. The value is an object descring it.&lt;br /&gt;
** &#039;&#039;&#039;name&#039;&#039;&#039; - &#039;&#039;&#039;mandatory&#039;&#039;&#039;. String representation of the numeric value visible to table creator. This is automatically marked for translation.&lt;br /&gt;
** &#039;&#039;&#039;description&#039;&#039;&#039; - String description of this value to use when the name of the option is not self-explanatory. Displayed at the table under the option when this value is selected. Note: if there is no description, this should be omitted.&lt;br /&gt;
** &#039;&#039;&#039;tmdisplay&#039;&#039;&#039; - String representation of the option visible in the table description in the lobby. Usually if a variant values are On and Off (default), the tmdisplay would be same as description name when On, and nothing (empty string) when Off. (&#039;&#039;&#039;Warning&#039;&#039;&#039;: due to some caching, a change in tmdisplay may not be effective immediately in the studio, even after forcing a reload of options.) &#039;&#039;&#039;Pro Tip:&#039;&#039;&#039; You can use this as a pre-game communication by adding fake options that just do nothing in the game but make it easier to find other player wanted the same game configuration (see the crew deep sea for example).&lt;br /&gt;
** &#039;&#039;&#039;nobeginner&#039;&#039;&#039; - Set to true if not recommended for beginners&lt;br /&gt;
** &#039;&#039;&#039;firstgameonly&#039;&#039;&#039; - Set to true if this option is recommended only for the first game (discovery option)&lt;br /&gt;
** &#039;&#039;&#039;beta&#039;&#039;&#039; - Set to true to indicate that this option is in &amp;quot;beta&amp;quot; development stage (there will be a warning for players starting the game)&lt;br /&gt;
** &#039;&#039;&#039;alpha&#039;&#039;&#039; - Set to true to indicate that this option is in &amp;quot;alpha&amp;quot; development stage (there will be a warning, and starting the game will be allowed only in training mode except for the developer)&lt;br /&gt;
** &#039;&#039;&#039;premium&#039;&#039;&#039; - Option can be only used by premium members&lt;br /&gt;
* &#039;&#039;&#039;default&#039;&#039;&#039; - indicates the default value to use for this option (optional, if not present the first value listed is the default)&lt;br /&gt;
* &#039;&#039;&#039;displaycondition&#039;&#039;&#039; - (array of conditions) - checks the conditions before displaying the option for selection. All (or any) conditions must be true for the option to be displayed. All or any depends on value of displayconditionoperand&lt;br /&gt;
Supported display condition types:&lt;br /&gt;
** &#039;&#039;minplayers&#039;&#039; condition ensures at least this many players (Note: if your game works with a disjoint interval of player counts, you can supply an array of valid counts instead of a single value)&lt;br /&gt;
** &#039;&#039;maxplayers&#039;&#039; condition ensures at most this many players&lt;br /&gt;
** &#039;&#039;otheroption&#039;&#039; condition ensures another option is set to given values. &lt;br /&gt;
** &#039;&#039;otheroptionisnot&#039;&#039; condition ensure another option is NOT set to this given values&lt;br /&gt;
* &#039;&#039;&#039;displayconditionoperand&#039;&#039;&#039; - can be &#039;and&#039; (this is the default) or &#039;or&#039;. Allows to change the behaviour to display the option if one of the conditions is true instead of all of them.&lt;br /&gt;
* &#039;&#039;&#039;startcondition&#039;&#039;&#039; - (map from value to conditions array) - checks the conditions (on options VALUES) before starting the game. All conditions must be true for the game to start, otherwise players will get a red error message when attempting to begin the game. &lt;br /&gt;
Supported start condition types:&lt;br /&gt;
** &#039;&#039;minplayers&#039;&#039; condition ensures at least this many players (an array of values is not supported here)&lt;br /&gt;
** &#039;&#039;maxplayers&#039;&#039; condition ensures at most this many players&lt;br /&gt;
** &#039;&#039;otheroption&#039;&#039; conditions ensure another option is set to this given values. That works the same as in &#039;&#039;&#039;displaycondition&#039;&#039;&#039;.&lt;br /&gt;
** &#039;&#039;otheroptionisnot&#039;&#039; conditions ensure another option is NOT set to this given value.  That works the same as in &#039;&#039;&#039;displaycondition&#039;&#039;&#039;.&lt;br /&gt;
*: For all these condition types, a &#039;&#039;gamestartonly&#039;&#039; boolean option can be added, if you have options that are exclusive. Setting this boolean to &#039;&#039;true&#039;&#039; will defer the evaluation of the startcondition to the game creation, instead of preventing the player to select options that are exclusive at all. See [[#gamestartonly|below]] for an example. &amp;lt;span style=&amp;quot;background: #FFCDD2; color: #B71C1C; padding: 2px;&amp;quot;&amp;gt;But this should never be used -- see the warning below&amp;lt;/span&amp;gt;&lt;br /&gt;
* &#039;&#039;&#039;notdisplayedmessage&#039;&#039;&#039; - if option is not suppose to be visible because of displaycondition but this is set, the text will be visible instead of combo drop down&lt;br /&gt;
* &#039;&#039;&#039;level&#039;&#039;&#039; - what kind of option it is: &#039;&#039;base&#039;&#039;, &#039;&#039;major&#039;&#039;, or &#039;&#039;additional&#039;&#039;. See [[#level|below]] for more informations.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Common (reserved) options for all tables (reserved range 200-299):&lt;br /&gt;
*201 (const GAMESTATE_RATING_MODE) - ELO OFF (aka Training mode), &lt;br /&gt;
**0 = Normal&lt;br /&gt;
**1 = Training&lt;br /&gt;
**2 = Arena&lt;br /&gt;
*200 (const GAMESTATE_CLOCK_MODE) - game speed profile&lt;br /&gt;
**[0, 1, 2] - realtime (technically &amp;lt;10 realtime but you cannot define range in php)&lt;br /&gt;
**values &amp;gt;=10 - turn based (currently 10..21)&lt;br /&gt;
**Note there are two similar values, 9 = realtime &amp;quot;no time limit with friends only&amp;quot; vs. 20 = turn-based &amp;quot;no time limit with friends only&amp;quot;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Example:&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
  &amp;quot;100&amp;quot;: {&lt;br /&gt;
    &amp;quot;name&amp;quot;: &amp;quot;Game Variant&amp;quot;,&lt;br /&gt;
    &amp;quot;values&amp;quot;: {&lt;br /&gt;
      &amp;quot;1&amp;quot;: {&lt;br /&gt;
        &amp;quot;name&amp;quot;: &amp;quot;Learning&amp;quot;,&lt;br /&gt;
        &amp;quot;firstgameonly&amp;quot;: true,&lt;br /&gt;
        &amp;quot;tmdisplay&amp;quot;: &amp;quot;Learning&amp;quot;&lt;br /&gt;
      },&lt;br /&gt;
      &amp;quot;2&amp;quot;: {&lt;br /&gt;
        &amp;quot;name&amp;quot;: &amp;quot;Base&amp;quot;,&lt;br /&gt;
      },&lt;br /&gt;
      &amp;quot;3&amp;quot;: {&lt;br /&gt;
        &amp;quot;name&amp;quot;: &amp;quot;Extended&amp;quot;,&lt;br /&gt;
        &amp;quot;nobeginner&amp;quot;: true,&lt;br /&gt;
        &amp;quot;beta&amp;quot;: true,&lt;br /&gt;
        &amp;quot;tmdisplay&amp;quot;: &amp;quot;Extended&amp;quot;&lt;br /&gt;
      }&lt;br /&gt;
    },&lt;br /&gt;
    &amp;quot;default&amp;quot;: 2&lt;br /&gt;
  },&lt;br /&gt;
  &amp;quot;101&amp;quot;: {&lt;br /&gt;
    &amp;quot;name&amp;quot;: &amp;quot;Draft variant&amp;quot;,&lt;br /&gt;
    &amp;quot;values&amp;quot;: {&lt;br /&gt;
      &amp;quot;1&amp;quot;: {&lt;br /&gt;
        &amp;quot;name&amp;quot;: &amp;quot;No draft&amp;quot;&lt;br /&gt;
      },&lt;br /&gt;
      &amp;quot;2&amp;quot;: {&lt;br /&gt;
        &amp;quot;name&amp;quot;: &amp;quot;Draft&amp;quot;,&lt;br /&gt;
        &amp;quot;tmdisplay&amp;quot;: &amp;quot;Draft&amp;quot;,&lt;br /&gt;
        &amp;quot;premium&amp;quot;: true,&lt;br /&gt;
        &amp;quot;nobeginner&amp;quot;: true&lt;br /&gt;
      }&lt;br /&gt;
    },&lt;br /&gt;
    &amp;quot;displaycondition&amp;quot;: [&lt;br /&gt;
      {&lt;br /&gt;
        &amp;quot;type&amp;quot;: &amp;quot;otheroption&amp;quot;,&lt;br /&gt;
        &amp;quot;id&amp;quot;: 100,&lt;br /&gt;
        &amp;quot;value&amp;quot;: [ 2, 3 ]&lt;br /&gt;
      },&lt;br /&gt;
      {&lt;br /&gt;
        &amp;quot;type&amp;quot;: &amp;quot;otheroption&amp;quot;,&lt;br /&gt;
        &amp;quot;id&amp;quot;: 201,&lt;br /&gt;
        &amp;quot;value&amp;quot;: 1&lt;br /&gt;
      }&lt;br /&gt;
    ],&lt;br /&gt;
    &amp;quot;startcondition&amp;quot;: {&lt;br /&gt;
      &amp;quot;1&amp;quot;: [],&lt;br /&gt;
      &amp;quot;2&amp;quot;: [&lt;br /&gt;
        {&lt;br /&gt;
          &amp;quot;type&amp;quot;: &amp;quot;maxplayers&amp;quot;,&lt;br /&gt;
          &amp;quot;value&amp;quot;: 3,&lt;br /&gt;
          &amp;quot;message&amp;quot;: &amp;quot;Draft option is available for 3 players maximum.&amp;quot;&lt;br /&gt;
        }&lt;br /&gt;
      ]&lt;br /&gt;
    }&lt;br /&gt;
  },&lt;br /&gt;
  &amp;quot;102&amp;quot;: {&lt;br /&gt;
    &amp;quot;name&amp;quot;: &amp;quot;Takeovers&amp;quot;,&lt;br /&gt;
    &amp;quot;values&amp;quot;: {&lt;br /&gt;
      &amp;quot;2&amp;quot;: {&lt;br /&gt;
        &amp;quot;name&amp;quot;: &amp;quot;No takeover&amp;quot;&lt;br /&gt;
      },&lt;br /&gt;
      &amp;quot;1&amp;quot;: {&lt;br /&gt;
        &amp;quot;name&amp;quot;: &amp;quot;Allow takeovers&amp;quot;,&lt;br /&gt;
        &amp;quot;tmdisplay&amp;quot;: &amp;quot;Takeovers&amp;quot;,&lt;br /&gt;
        &amp;quot;premium&amp;quot;: true,&lt;br /&gt;
        &amp;quot;nobeginner&amp;quot;: true&lt;br /&gt;
      }&lt;br /&gt;
    },&lt;br /&gt;
    &amp;quot;displaycondition&amp;quot;: [&lt;br /&gt;
      {&lt;br /&gt;
        &amp;quot;type&amp;quot;: &amp;quot;otheroption&amp;quot;,&lt;br /&gt;
        &amp;quot;id&amp;quot;: 100,&lt;br /&gt;
        &amp;quot;value&amp;quot;: [ 3 ]&lt;br /&gt;
      }&lt;br /&gt;
    ],&lt;br /&gt;
    &amp;quot;startcondition&amp;quot;: {&lt;br /&gt;
      &amp;quot;2&amp;quot;: [],&lt;br /&gt;
      &amp;quot;1&amp;quot;: [&lt;br /&gt;
        {&lt;br /&gt;
          &amp;quot;type&amp;quot;: &amp;quot;maxplayers&amp;quot;,&lt;br /&gt;
          &amp;quot;value&amp;quot;: 2,&lt;br /&gt;
          &amp;quot;message&amp;quot;: &amp;quot;Rebel vs Imperium Takeover Scenario is available for 2 players only.&amp;quot;&lt;br /&gt;
        }&lt;br /&gt;
      ]&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Example of option that condition on ELO off:&#039;&#039;&#039;&lt;br /&gt;
 {&lt;br /&gt;
   &amp;quot;100&amp;quot;: {&lt;br /&gt;
     &amp;quot;name&amp;quot;: &amp;quot;Learning Game (No Research)&amp;quot;,&lt;br /&gt;
     &amp;quot;values&amp;quot;: {&lt;br /&gt;
       &amp;quot;1&amp;quot;: {&lt;br /&gt;
         &amp;quot;name&amp;quot;: &amp;quot;Off&amp;quot;,&lt;br /&gt;
         &amp;quot;tmdisplay&amp;quot;: &amp;quot;&amp;quot;&lt;br /&gt;
       },&lt;br /&gt;
       &amp;quot;2&amp;quot;: {&lt;br /&gt;
         &amp;quot;name&amp;quot;: &amp;quot;On&amp;quot;,&lt;br /&gt;
         &amp;quot;tmdisplay&amp;quot;: &amp;quot;Learning Game&amp;quot;&lt;br /&gt;
       }&lt;br /&gt;
     },&lt;br /&gt;
     &amp;quot;startcondition&amp;quot;: {&lt;br /&gt;
       &amp;quot;2&amp;quot;: {&lt;br /&gt;
         &amp;quot;type&amp;quot;: &amp;quot;otheroption&amp;quot;,&lt;br /&gt;
         &amp;quot;id&amp;quot;: 201,&lt;br /&gt;
         &amp;quot;value&amp;quot;: 1,&lt;br /&gt;
         &amp;quot;message&amp;quot;: &amp;quot;Learning variant available only in friendly mode&amp;quot;&lt;br /&gt;
       }&lt;br /&gt;
     }&lt;br /&gt;
   }&lt;br /&gt;
 }&lt;br /&gt;
&#039;&#039;&#039;Example of condition that is only available for REALTIME game mode:&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;quot;displaycondition&amp;quot;: [&lt;br /&gt;
    { &amp;quot;type&amp;quot;: &amp;quot;otheroption&amp;quot;, &amp;quot;id&amp;quot;: 200, &amp;quot;value&amp;quot;: [0, 1, 2] }&lt;br /&gt;
],&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Example of using condition on your own option:&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
  &amp;quot;102&amp;quot;: {&lt;br /&gt;
    &amp;quot;name&amp;quot;: &amp;quot;Scenarios&amp;quot;,&lt;br /&gt;
    &amp;quot;values&amp;quot;: {&lt;br /&gt;
      &amp;quot;1&amp;quot;: {&lt;br /&gt;
        &amp;quot;name&amp;quot;: &amp;quot;Off&amp;quot;,&lt;br /&gt;
        &amp;quot;nobeginner&amp;quot;: false&lt;br /&gt;
      },&lt;br /&gt;
      &amp;quot;2&amp;quot;: {&lt;br /&gt;
        &amp;quot;name&amp;quot;: &amp;quot;On&amp;quot;,&lt;br /&gt;
        &amp;quot;tmdisplay&amp;quot;: &amp;quot;Scenarios&amp;quot;,&lt;br /&gt;
        &amp;quot;nobeginner&amp;quot;: true&lt;br /&gt;
      }&lt;br /&gt;
    },&lt;br /&gt;
    &amp;quot;displaycondition&amp;quot;: [&lt;br /&gt;
      {&lt;br /&gt;
        &amp;quot;type&amp;quot;: &amp;quot;otheroptionisnot&amp;quot;,&lt;br /&gt;
        &amp;quot;id&amp;quot;: 100,&lt;br /&gt;
        &amp;quot;value&amp;quot;: 1&lt;br /&gt;
      }&lt;br /&gt;
    ],&lt;br /&gt;
    &amp;quot;notdisplayedmessage&amp;quot;: &amp;quot;Scenarios variant is not available if Learning variant is chosen&amp;quot;&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Example of handling solo vs multiplayer options:&#039;&#039;&#039;&amp;lt;pre&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
  &amp;quot;100&amp;quot;: {&lt;br /&gt;
    &amp;quot;name&amp;quot;: &amp;quot;Board setup&amp;quot;,&lt;br /&gt;
    &amp;quot;values&amp;quot;: {&lt;br /&gt;
      &amp;quot;1&amp;quot;: {&lt;br /&gt;
        &amp;quot;name&amp;quot;: &amp;quot;Mirror setup&amp;quot;,&lt;br /&gt;
        &amp;quot;description&amp;quot;: &amp;quot;The starting player shuffles their 6 Farm Cards and randomly lays a card face up in each of the round spaces of their Fruit Island Board. The other players then lay their cards in exactly the same way, copying the order of the starting player.&amp;quot;,&lt;br /&gt;
        &amp;quot;tmdisplay&amp;quot;: &amp;quot;Mirror setup&amp;quot;&lt;br /&gt;
      },&lt;br /&gt;
      &amp;quot;2&amp;quot;: {&lt;br /&gt;
        &amp;quot;name&amp;quot;: &amp;quot;Random setup&amp;quot;,&lt;br /&gt;
        &amp;quot;description&amp;quot;: &amp;quot;Instead of every player copying the same card configuration as the starting player, every player shuffles their Farm Cards and lays down the cards randomly on their Fruit Island Board.&amp;quot;,&lt;br /&gt;
        &amp;quot;tmdisplay&amp;quot;: &amp;quot;Random setup&amp;quot;&lt;br /&gt;
      }&lt;br /&gt;
    },&lt;br /&gt;
    &amp;quot;displaycondition&amp;quot;: [&lt;br /&gt;
      {&lt;br /&gt;
        &amp;quot;type&amp;quot;: &amp;quot;minplayers&amp;quot;,&lt;br /&gt;
        &amp;quot;value&amp;quot;: [&lt;br /&gt;
          2,&lt;br /&gt;
          3,&lt;br /&gt;
          4&lt;br /&gt;
        ]&lt;br /&gt;
      }&lt;br /&gt;
    ]&lt;br /&gt;
  },&lt;br /&gt;
  &amp;quot;102&amp;quot;: {&lt;br /&gt;
    &amp;quot;name&amp;quot;: &amp;quot;Solo difficulty&amp;quot;,&lt;br /&gt;
    &amp;quot;values&amp;quot;: [&lt;br /&gt;
      {&lt;br /&gt;
        &amp;quot;name&amp;quot;: &amp;quot;Banana-apprentice&amp;quot;,&lt;br /&gt;
        &amp;quot;description&amp;quot;: &amp;quot;Do not remove any seed before starting the game.&amp;quot;,&lt;br /&gt;
        &amp;quot;tmdisplay&amp;quot;: &amp;quot;Banana-apprentice&amp;quot;&lt;br /&gt;
      },&lt;br /&gt;
      {&lt;br /&gt;
        &amp;quot;name&amp;quot;: &amp;quot;Pear to the Throne&amp;quot;,&lt;br /&gt;
        &amp;quot;description&amp;quot;: &amp;quot;Remove 1 seed before starting the game.&amp;quot;,&lt;br /&gt;
        &amp;quot;tmdisplay&amp;quot;: &amp;quot;Pear to the Throne&amp;quot;&lt;br /&gt;
      }&lt;br /&gt;
    ],&lt;br /&gt;
    &amp;quot;displaycondition&amp;quot;: [&lt;br /&gt;
      {&lt;br /&gt;
        &amp;quot;type&amp;quot;: &amp;quot;maxplayers&amp;quot;,&lt;br /&gt;
        &amp;quot;value&amp;quot;: 1&lt;br /&gt;
      }&lt;br /&gt;
    ]&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== displaycondition vs startcondition ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;displaycondition&amp;lt;/code&amp;gt; should be used when an option should not be present in the list under certain conditions.&lt;br /&gt;
&lt;br /&gt;
For example, displaying the option which is consistent with the player count.&lt;br /&gt;
&lt;br /&gt;
* 2 player maps: A B C D &lt;br /&gt;
* 3 player maps: E F G H&lt;br /&gt;
* 4 player maps: I J K L&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;startcondition&amp;lt;/code&amp;gt; should be used when a specific combination of option values is invalid, but the option itself still makes sense to show.&lt;br /&gt;
&lt;br /&gt;
For example:&lt;br /&gt;
&lt;br /&gt;
* Player 1 faction: A, B, C, D, E, F, G&lt;br /&gt;
* Player 2 faction: A, B, C, D, E, F, G&lt;br /&gt;
* startcondition: both players can&#039;t be the same faction&lt;br /&gt;
&lt;br /&gt;
These options should both be displayed at all times, but there are some invalid configurations.&lt;br /&gt;
&lt;br /&gt;
The other difference is displaycondition affect option itself, while startcondition affect specific values selected&lt;br /&gt;
&lt;br /&gt;
==== gamestartonly ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;padding: 1em; background: #FFCDD2; color: #B71C1C&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;b&amp;gt;WARNING:&amp;lt;/b&amp;gt; [https://studio.boardgamearena.com/bug?id=104 See studio bug #104]. You should &amp;lt;b&amp;gt;NEVER&amp;lt;/b&amp;gt; use &amp;lt;code&amp;gt;gamestartonly&amp;lt;/code&amp;gt;! Otherwise, you allow players to (unknowingly!) create a turn-based table with impossible options that can never start. Players receive no indication that the option combination they selected is invalid until the last player joins the table (hours or days later) and the game attempts to auto-start. The table won&#039;t start because of the &amp;lt;code&amp;gt;startcondition&amp;lt;/code&amp;gt;, and the table options cannot be changed because it&#039;s a turn-based table, so the table must be abandoned. This is a horrible user experience. Please don&#039;t subject players to this.&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
On the table configuration page, it won&#039;t let you select a combination which is invalid according to &amp;lt;code&amp;gt;startcondition&amp;lt;/code&amp;gt;. Doing so will show a red warning, and will revert the option to the previous value. This means you could end up in a situation where you can&#039;t easily change between certain options (requiring you to set or unset options in a specific order).&lt;br /&gt;
&lt;br /&gt;
The consequence of the &amp;lt;code&amp;gt;gamestartonly&amp;lt;/code&amp;gt; flag is that the player _can_ select an invalid combination. However, when clicking &amp;quot;Start&amp;quot;, an invalid combination will produce an error.&lt;br /&gt;
&lt;br /&gt;
Probably the easiest way to see what the difference is is with an example.&lt;br /&gt;
&lt;br /&gt;
With a _Clans of Caledonia_ table:&lt;br /&gt;
* set to training mode&lt;br /&gt;
* set player count to 1&lt;br /&gt;
* try setting &amp;quot;Clan Auction&amp;quot; to one of the &amp;quot;On&amp;quot; options&lt;br /&gt;
* try starting the game, there&#039;s an error! Ie. &amp;lt;code&amp;gt;&amp;quot;gamestartonly&amp;quot; =&amp;gt; true&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Then, with a _Sushi Go Party!_ table:&lt;br /&gt;
* set number of players to 7&lt;br /&gt;
* try setting &amp;quot;Sushi Go! / Sushi Go Party!&amp;quot; to &amp;quot;Sushi Go!&amp;quot;&lt;br /&gt;
* you can&#039;t set the option! Ie. &amp;lt;code&amp;gt;&amp;quot;gamestartonly&amp;quot; =&amp;gt; false&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In code:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
  &amp;quot;100&amp;quot;: {&lt;br /&gt;
    &amp;quot;name&amp;quot;: &amp;quot;Option name&amp;quot;,&lt;br /&gt;
    &amp;quot;values&amp;quot;: [],&lt;br /&gt;
    &amp;quot;startcondition&amp;quot;: {&lt;br /&gt;
      &amp;quot;1&amp;quot;: [&lt;br /&gt;
        {&lt;br /&gt;
          &amp;quot;type&amp;quot;: &amp;quot;maxplayers&amp;quot;,&lt;br /&gt;
          &amp;quot;value&amp;quot;: 2,&lt;br /&gt;
          &amp;quot;message&amp;quot;: &amp;quot;This option is available for 2 players only.&amp;quot;,&lt;br /&gt;
          &amp;quot;gamestartonly&amp;quot;: true&lt;br /&gt;
        }&lt;br /&gt;
      ]&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== level ====&lt;br /&gt;
Note: at this moment this only have impact in fancy lobby mode, presentation of level or checkboxes are not avaiable via normal table creation ui (such as in studio, or when you click Play button in control panel)&amp;lt;pre&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
    &amp;quot;100&amp;quot;: {&lt;br /&gt;
        &amp;quot;name&amp;quot;: &amp;quot;Option name&amp;quot;,&lt;br /&gt;
        &amp;quot;values&amp;quot;: [...],&lt;br /&gt;
        &amp;quot;level&amp;quot;: &amp;quot;major&amp;quot;&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;base&#039;&#039;&#039; is the default value (you don&#039;t need to specify it).&lt;br /&gt;
* &#039;&#039;&#039;major&#039;&#039;&#039; denotes a major option, which will always be displayed on top, and with a specific UI.&lt;br /&gt;
* &#039;&#039;&#039;additional&#039;&#039;&#039; means this option will not be displayed by default, to unclutter the option panel.&lt;br /&gt;
&lt;br /&gt;
About major options:&lt;br /&gt;
* a game can only have &#039;&#039;&#039;1 major option&#039;&#039;&#039;, and of course, it must be a important game changer.&lt;br /&gt;
* the pictures will default to the standard Game Box, and can be set independently for each value, from the [[Game metadata manager]] (in the &amp;quot;Major Variants&amp;quot; section). Note: this cannot be tested from Studio as there is not studio-only Game metadata manager, to see Major Variants option - the game has to be deployed at least as alpha.&lt;br /&gt;
* the major option can have more than 2 values (there will then be an arrow to slide to the other values, carousel-like)&lt;br /&gt;
* the naming of major variant values should be concise and the values should have descriptive text (not just &amp;quot;enabled&amp;quot; or &amp;quot;disabled&amp;quot;)&lt;br /&gt;
** 👍 Option name &amp;quot;Expansion&amp;quot;, option values &amp;quot;Base game&amp;quot;, &amp;quot;Bigger is Better&amp;quot; =&amp;gt; Displayed as &#039;&#039;&amp;quot;Expansion: Base game&amp;quot;&#039;&#039; or &#039;&#039;&amp;quot;Expansion: Bigger is Better&amp;quot;&#039;&#039;&lt;br /&gt;
** 👎 Option name &amp;quot;Bigger is Better&amp;quot;, option values &amp;quot;Enabled&amp;quot;, &amp;quot;Disabled =&amp;gt; Displayed as &#039;&#039;&amp;quot;Bigger is Better: Enabled&amp;quot;&#039;&#039; or &#039;&#039;&amp;quot;Bigger is Better: Disabled&amp;quot;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
About additional options:&lt;br /&gt;
* please set each option that concerns small details in this category: advanced players will find this option anyway, and it will simplify the interface of the page of your game.&lt;br /&gt;
&lt;br /&gt;
[[File:Option-levels.png|800px|Option levels]]&lt;br /&gt;
&lt;br /&gt;
==== option presentation ====&lt;br /&gt;
&lt;br /&gt;
An option WILL be displayed as a &#039;&#039;&#039;Checkbox&#039;&#039;&#039; instead of a selector if certain conditions are met:&lt;br /&gt;
&lt;br /&gt;
* option has only &#039;&#039;&#039;2 values&#039;&#039;&#039;&lt;br /&gt;
* values are either (case insensitive):&lt;br /&gt;
** &#039;&#039;yes&#039;&#039; and &#039;&#039;no&#039;&#039;&lt;br /&gt;
** &#039;&#039;on&#039;&#039; and &#039;&#039;off&#039;&#039;&lt;br /&gt;
** &#039;&#039;enabled&#039;&#039; and &#039;&#039;disabled&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
The &amp;quot;default&amp;quot; value still has to be specified, and can be &amp;quot;on&amp;quot; or &amp;quot;off&amp;quot; (it&#039;s actually just a difference in display).&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[File:Option-display.png|800px|Example of checkbox display]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== User Preferences ==&lt;br /&gt;
&lt;br /&gt;
User preferences is something cosmetic about the game interface which however can create user wars, so you can satisfy all users&lt;br /&gt;
by giving them individual preferences. You should use this only if it significantly improves the interface for a large proportion of users.&lt;br /&gt;
These preferences appear in the three-line hamburger menu in the top corner of the bga menu (and also at the bottom on the page in the Options tab).  &lt;br /&gt;
&amp;quot;Display game logs&amp;quot; and &amp;quot;Display tooltips&amp;quot; are baked-in by default, but you can extend this list as below. &lt;br /&gt;
&lt;br /&gt;
The preference json slightly resembles options, but these are conceptually different. The numbers comes from diffrent space and do not correspond or conflict with options,&lt;br /&gt;
i.e. preference 100 has nothing to do with option 100. You can use range 100-199 with gaps.&lt;br /&gt;
&lt;br /&gt;
[[File:century_preferences_menu.PNG|400px|The user preferences menu for the game Century]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;&lt;br /&gt;
&#039;&#039;These preferences are a good place to put accessibility options - as Century did for its Colorblind Support.&#039;&#039;&lt;br /&gt;
&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
  &amp;quot;100&amp;quot;: {&lt;br /&gt;
    &amp;quot;name&amp;quot;: &amp;quot;Colorblind Support&amp;quot;,&lt;br /&gt;
    &amp;quot;needReload&amp;quot;: true,&lt;br /&gt;
    &amp;quot;values&amp;quot;: {&lt;br /&gt;
      &amp;quot;1&amp;quot;: {&lt;br /&gt;
        &amp;quot;name&amp;quot;: &amp;quot;None&amp;quot;,&lt;br /&gt;
        &amp;quot;cssPref&amp;quot;: &amp;quot;colorblind_off&amp;quot;&lt;br /&gt;
      },&lt;br /&gt;
      &amp;quot;2&amp;quot;: {&lt;br /&gt;
        &amp;quot;name&amp;quot;: &amp;quot;Numbers&amp;quot;,&lt;br /&gt;
        &amp;quot;cssPref&amp;quot;: &amp;quot;colorblind_on&amp;quot;&lt;br /&gt;
      },&lt;br /&gt;
      &amp;quot;3&amp;quot;: {&lt;br /&gt;
        &amp;quot;name&amp;quot;: &amp;quot;Shapes&amp;quot;,&lt;br /&gt;
        &amp;quot;cssPref&amp;quot;: &amp;quot;colorblind_shapes&amp;quot;&lt;br /&gt;
      }&lt;br /&gt;
    },&lt;br /&gt;
    &amp;quot;default&amp;quot;: 1&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
There is two ways to check/apply this. In javascript&lt;br /&gt;
&lt;br /&gt;
  if (this.getGameUserPreference(100) == 2) ...&lt;br /&gt;
&lt;br /&gt;
This checks if preferences 100 has selected value 2.&lt;br /&gt;
&lt;br /&gt;
Second, if cssPref is specified, it will be applied to the &#039;&#039;&#039;&amp;lt;html&amp;gt;&#039;&#039;&#039; tag. So you can use different css styling for the preference. Note: you also need to set needReload to true for that class change to be effective.&lt;br /&gt;
&lt;br /&gt;
As user you have to select them from the Gear menu when game is started. On studio only dev0 account will have it actually working (bug?).&lt;br /&gt;
&lt;br /&gt;
The following are the parameters of preferences description array:&lt;br /&gt;
* &#039;&#039;&#039;name&#039;&#039;&#039; - &#039;&#039;&#039;mandatory&#039;&#039;&#039;. The name of the preference. This string is marked for translation.&lt;br /&gt;
* &#039;&#039;&#039;needReload&#039;&#039;&#039; - If set to true, the game interface will auto-reload after a change of the preference.&lt;br /&gt;
* &#039;&#039;&#039;values&#039;&#039;&#039; - &#039;&#039;&#039;mandatory&#039;&#039;&#039;. The map of values with additional parameters per value.&lt;br /&gt;
** &#039;&#039;&#039;name&#039;&#039;&#039; - &#039;&#039;&#039;mandatory&#039;&#039;&#039;. String representation of the numeric value.  This string is marked for translation.&lt;br /&gt;
** &#039;&#039;&#039;cssPref&#039;&#039;&#039; - CSS class to add to the &#039;&#039;&#039;&amp;lt;html&amp;gt;&#039;&#039;&#039; tag. Currently it is added or removed only after a reload (see needReload).&lt;br /&gt;
* &#039;&#039;&#039;default&#039;&#039;&#039; - Indicates the default value to use for this preference (optional, if not present the first value listed is the default).&lt;br /&gt;
&lt;br /&gt;
=== Listening for preference changes and updating preference from code ===&lt;br /&gt;
The BGA framework offers read/write and callback for user preference changes. See [[Game interface logic: yourgamename.js#User preferences]]&lt;br /&gt;
&lt;br /&gt;
=== Accessing User Preferences on the server ===&lt;br /&gt;
PHP has a variable called $this-&amp;gt;player_preferences.&lt;br /&gt;
This contains a table of player preferences, ONLY accessible in setupNewGame().&lt;br /&gt;
You can use this to populate a table that you manage yourself.&lt;br /&gt;
You have to update the table when a player changes preference (and you have to hook up a listener and initiate an AJAX call out-of-turn).&lt;br /&gt;
Check the code of Agricola for details but this should work:&lt;br /&gt;
&lt;br /&gt;
; In dbmodel.sql&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
CREATE TABLE IF NOT EXISTS `user_preferences` (&lt;br /&gt;
  `player_id` int(10) NOT NULL,&lt;br /&gt;
  `pref_id` int(10) NOT NULL,&lt;br /&gt;
  `pref_value` int(10) NOT NULL,&lt;br /&gt;
  PRIMARY KEY (`player_id`, `pref_id`)&lt;br /&gt;
) ENGINE=InnoDB DEFAULT CHARSET=utf8;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
; In ggg.game.php&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
protected function setupNewGame($players, $options = array())&lt;br /&gt;
{&lt;br /&gt;
// TODO: Save $this-&amp;gt;player_preferences: key is player_id, value is array with pref_id as key and pref_value as value&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Warning: &amp;lt;code&amp;gt;$this-&amp;gt;player_preferences[$player_id]&amp;lt;/code&amp;gt; can be null if the player has not set any player preferences.&lt;br /&gt;
&lt;br /&gt;
Note: to access json values you can call:&lt;br /&gt;
   $game_preferences = $this-&amp;gt;getTablePreferences();&lt;br /&gt;
&lt;br /&gt;
Warning: if you use bga undo system make sure this table is not restored from undo state, as this likely independed from it&lt;br /&gt;
&lt;br /&gt;
; In ggg.js&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
// use code for initPreferencesObserver from above example&lt;br /&gt;
&lt;br /&gt;
onGameUserPreferenceChanged(prefId, prefValue) {&lt;br /&gt;
    if (prefId === 101 /*TODO: You probably want to send only some preferences*/) {&lt;br /&gt;
        // TODO: Code your own action in ggg.action.php and send it prefId and prefValue&lt;br /&gt;
        //       The on the server side you can save it all in the user_preferences&lt;br /&gt;
        //       table you created above.&lt;br /&gt;
    }&lt;br /&gt;
},&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Translations ==&lt;br /&gt;
Note that any name or description values in these JSON files are automatically added to the translation system.&lt;br /&gt;
&lt;br /&gt;
== Migration ==&lt;br /&gt;
Previously, options and preferences were specified in a single &amp;lt;code&amp;gt;gameoptions.inc.php&amp;lt;/code&amp;gt; file.&lt;br /&gt;
&lt;br /&gt;
BGA has switched to a JSON format to make parsing easier on the server-side, and to avoid a reliance on PHP for static config.&lt;br /&gt;
&lt;br /&gt;
The PHP format will continue to work for &#039;&#039;existing&#039;&#039; games, and although preferred, there is no need to migrate unless you want to. However, newly created games must use the new format.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note&#039;&#039;&#039;: once a game has been committed with a &amp;lt;code&amp;gt;gameoptions.json&amp;lt;/code&amp;gt; file, however, it is not possible to go back without admin intervention.&lt;br /&gt;
&lt;br /&gt;
If you want to migrate:&lt;br /&gt;
&lt;br /&gt;
Simple method:&lt;br /&gt;
* Go to studio and press Reload game options configuration&lt;br /&gt;
* It will dump json on the log window - you can take this, format it and save into 2 files (if you have both). For gamepreference.json remove option &amp;quot;200&amp;quot; - this is default common option, it should not be in your file.&lt;br /&gt;
&lt;br /&gt;
Manual method:&lt;br /&gt;
* Remove all calls to &amp;lt;code&amp;gt;totranslate()&amp;lt;/code&amp;gt;, and replace with the plain string&lt;br /&gt;
* Remove any references to BGA&#039;s PHP constants, such as GAMESTATE_RATING_MODE, and replace with the plain value (in this case, 201)&lt;br /&gt;
* You can populate &amp;lt;code&amp;gt;gameinfos.json&amp;lt;/code&amp;gt; with the result of &amp;lt;code&amp;gt;json_encode($game_options, JSON_PRETTY_PRINT)&amp;lt;/code&amp;gt;&lt;br /&gt;
* You can populate &amp;lt;code&amp;gt;gamepreferences.json&amp;lt;/code&amp;gt; with the result of &amp;lt;code&amp;gt;json_encode($game_preferences, JSON_PRETTY_PRINT)&amp;lt;/code&amp;gt;&lt;br /&gt;
* If you include gameoptions.inc.php directly, to read the values, then replace those calls with &amp;lt;code&amp;gt;$this-&amp;gt;getTableOptions()&amp;lt;/code&amp;gt; or &amp;lt;code&amp;gt;$this-&amp;gt;getTablePreferences()&amp;lt;/code&amp;gt; as appropriate which return arrays parsed from the JSON files&lt;br /&gt;
This message was posted to the developer Discord channel:&amp;lt;blockquote&amp;gt;&#039;&#039;&#039;Game options change (Optional!)&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;gameoptions.inc.php&amp;lt;/code&amp;gt; is now considered legacy, and &amp;lt;code&amp;gt;gameoptions.json&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;gamepreferences.json&amp;lt;/code&amp;gt; are recommended for new projects:&lt;br /&gt;
&lt;br /&gt;
* The wiki and the template project have been updated: [[/en.doc.boardgamearena.com/Options and preferences: gameoptions.json, gamepreferences.json|https://en.doc.boardgamearena.com/Options_and_preferences:_gameoptions.json,_gamepreferences.json]]&lt;br /&gt;
* Any questions/problems can come to me, or can be asked here.&lt;br /&gt;
* The format of the json files matches the format of the old php files&lt;br /&gt;
&lt;br /&gt;
We realise there are some drawbacks (sorry!):&lt;br /&gt;
&lt;br /&gt;
* No comments in the JSON file, meaning you have to check the wiki for examples&lt;br /&gt;
* No PHP constants in the JSON file, meaning magic numbers&lt;br /&gt;
&lt;br /&gt;
However, we hope it&#039;s good for BGA because:&lt;br /&gt;
&lt;br /&gt;
* Simpler to parse (for robots and humans)&lt;br /&gt;
* Easier to check for errors (we could perhaps use an XSLT one day)&lt;br /&gt;
* No need to run game-specific PHP code on the metasite&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;NOTE&#039;&#039;&#039;: Switching is totally optional, and the legacy files will still work for existing projects, and for those who know about them. &amp;lt;/blockquote&amp;gt;&lt;br /&gt;
[[Category:Studio]]&lt;/div&gt;</summary>
		<author><name>Sguzzer Gunayer</name></author>
	</entry>
	<entry>
		<id>https://en.doc.boardgamearena.com/index.php?title=Options_and_preferences:_gameoptions.json,_gamepreferences.json&amp;diff=22489</id>
		<title>Options and preferences: gameoptions.json, gamepreferences.json</title>
		<link rel="alternate" type="text/html" href="https://en.doc.boardgamearena.com/index.php?title=Options_and_preferences:_gameoptions.json,_gamepreferences.json&amp;diff=22489"/>
		<updated>2024-09-07T09:26:26Z</updated>

		<summary type="html">&lt;p&gt;Sguzzer Gunayer: /* User Preferences */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Studio_Framework_Navigation}}&lt;br /&gt;
&lt;br /&gt;
In &amp;lt;code&amp;gt;gameoptions.json&amp;lt;/code&amp;gt;, you can define your game options (i.e. game variants).&lt;br /&gt;
&lt;br /&gt;
In &amp;lt;code&amp;gt;gamepreferences.json&amp;lt;/code&amp;gt;, you can define user preferences.&lt;br /&gt;
   &lt;br /&gt;
Note: If your game has no variants or preferences, you don&#039;t have to modify these files.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;IMPORTANT:&#039;&#039;&#039; after edits to these files, you have to go to the control panel and press &amp;quot;Reload game options configuration&amp;quot; on Studio for your changes &#039;&#039;&#039;to take effect&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
Make sure you understand difference between options and preferences:&lt;br /&gt;
* Game options - something usually in the rule book defined as &amp;quot;variant&amp;quot; (except for player count, which is automatically handled). For example, whether to include &#039;&#039;The River&#039;&#039; in Carcassonne.&lt;br /&gt;
* User preferences - personal choices of each player only visible to that specific player - i.e. layout, whether or not to prompt for action, whether or not auto-opt in in some actions, etc.&lt;br /&gt;
&lt;br /&gt;
__TOC__&lt;br /&gt;
&lt;br /&gt;
== Game Options ==&lt;br /&gt;
&lt;br /&gt;
Game options are selected by the table creator and usually correspond to game variants, for example if the game includes expansions or certain special rules.&lt;br /&gt;
&lt;br /&gt;
These variants are defined in &amp;lt;code&amp;gt;gameoptions.json&amp;lt;/code&amp;gt; as an object:  &lt;br /&gt;
&lt;br /&gt;
  {&lt;br /&gt;
     &amp;quot;100&amp;quot;: { &amp;quot;name&amp;quot;: &amp;quot;Game Setup&amp;quot;, ... },&lt;br /&gt;
     &amp;quot;101&amp;quot;: { &amp;quot;name&amp;quot;: &amp;quot;Draft&amp;quot;, ... }&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
Each key corresponds to the option id, and each value is that option definition, which is described below.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note:&#039;&#039;&#039; the file must be valid [https://www.json.org/ JSON]. That is, trailing commas and comments are not allowed. However you can use still standard json hack to add a field like &amp;quot;$comment&amp;quot;: &amp;quot;Here we go&amp;quot;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note 2:&#039;&#039;&#039; the key in json file must be a string type, even its correspond to a number in other places (such as php, or other references in same json).&lt;br /&gt;
&lt;br /&gt;
All options defined in this file should have a corresponding &amp;quot;game state label&amp;quot; with the same ID (see &amp;quot;initGameStateLabels&amp;quot; in yourgame.game.php)&lt;br /&gt;
&lt;br /&gt;
             self::initGameStateLabels ([&lt;br /&gt;
                        ...&lt;br /&gt;
                        &amp;quot;my_game_variant&amp;quot; =&amp;gt; 100,&lt;br /&gt;
              ]);&lt;br /&gt;
&lt;br /&gt;
Numbers have to be exactly from 100 to 199 (there can be gaps).&lt;br /&gt;
&lt;br /&gt;
That is how you access them during runtime (by name):&lt;br /&gt;
&lt;br /&gt;
    public function isSecondVariant() {&lt;br /&gt;
        return $this-&amp;gt;getGameStateValue(&#039;my_game_variant&#039;) == 2;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
Or this (by numberic id)&lt;br /&gt;
    $this-&amp;gt;gamestate-&amp;gt;table_globals[100]&lt;br /&gt;
To access json data (the metadata only) can use&lt;br /&gt;
   $game_options = $this-&amp;gt;getTableOptions();&lt;br /&gt;
=== Details of game options format ===&lt;br /&gt;
&lt;br /&gt;
The following are the values of the option definition object:&lt;br /&gt;
* &#039;&#039;&#039;name&#039;&#039;&#039; - &#039;&#039;&#039;mandatory&#039;&#039;&#039;. The name of the option visible for table creator. This is automatically marked for translation.&lt;br /&gt;
* &#039;&#039;&#039;values&#039;&#039;&#039; - &#039;&#039;&#039;mandatory&#039;&#039;&#039;. The map representing possible values of this option. The key of the map is possible value of this option, its a number but has to be string in json. The value is an object descring it.&lt;br /&gt;
** &#039;&#039;&#039;name&#039;&#039;&#039; - &#039;&#039;&#039;mandatory&#039;&#039;&#039;. String representation of the numeric value visible to table creator. This is automatically marked for translation.&lt;br /&gt;
** &#039;&#039;&#039;description&#039;&#039;&#039; - String description of this value to use when the name of the option is not self-explanatory. Displayed at the table under the option when this value is selected. Note: if there is no description, this should be omitted.&lt;br /&gt;
** &#039;&#039;&#039;tmdisplay&#039;&#039;&#039; - String representation of the option visible in the table description in the lobby. Usually if a variant values are On and Off (default), the tmdisplay would be same as description name when On, and nothing (empty string) when Off. (&#039;&#039;&#039;Warning&#039;&#039;&#039;: due to some caching, a change in tmdisplay may not be effective immediately in the studio, even after forcing a reload of options.) &#039;&#039;&#039;Pro Tip:&#039;&#039;&#039; You can use this as a pre-game communication by adding fake options that just do nothing in the game but make it easier to find other player wanted the same game configuration (see the crew deep sea for example).&lt;br /&gt;
** &#039;&#039;&#039;nobeginner&#039;&#039;&#039; - Set to true if not recommended for beginners&lt;br /&gt;
** &#039;&#039;&#039;firstgameonly&#039;&#039;&#039; - Set to true if this option is recommended only for the first game (discovery option)&lt;br /&gt;
** &#039;&#039;&#039;beta&#039;&#039;&#039; - Set to true to indicate that this option is in &amp;quot;beta&amp;quot; development stage (there will be a warning for players starting the game)&lt;br /&gt;
** &#039;&#039;&#039;alpha&#039;&#039;&#039; - Set to true to indicate that this option is in &amp;quot;alpha&amp;quot; development stage (there will be a warning, and starting the game will be allowed only in training mode except for the developer)&lt;br /&gt;
** &#039;&#039;&#039;premium&#039;&#039;&#039; - Option can be only used by premium members&lt;br /&gt;
* &#039;&#039;&#039;default&#039;&#039;&#039; - indicates the default value to use for this option (optional, if not present the first value listed is the default)&lt;br /&gt;
* &#039;&#039;&#039;displaycondition&#039;&#039;&#039; - (array of conditions) - checks the conditions before displaying the option for selection. All (or any) conditions must be true for the option to be displayed. All or any depends on value of displayconditionoperand&lt;br /&gt;
Supported display condition types:&lt;br /&gt;
** &#039;&#039;minplayers&#039;&#039; condition ensures at least this many players (Note: if your game works with a disjoint interval of player counts, you can supply an array of valid counts instead of a single value)&lt;br /&gt;
** &#039;&#039;maxplayers&#039;&#039; condition ensures at most this many players&lt;br /&gt;
** &#039;&#039;otheroption&#039;&#039; condition ensures another option is set to given values. &lt;br /&gt;
** &#039;&#039;otheroptionisnot&#039;&#039; condition ensure another option is NOT set to this given values&lt;br /&gt;
* &#039;&#039;&#039;displayconditionoperand&#039;&#039;&#039; - can be &#039;and&#039; (this is the default) or &#039;or&#039;. Allows to change the behaviour to display the option if one of the conditions is true instead of all of them.&lt;br /&gt;
* &#039;&#039;&#039;startcondition&#039;&#039;&#039; - (map from value to conditions array) - checks the conditions (on options VALUES) before starting the game. All conditions must be true for the game to start, otherwise players will get a red error message when attempting to begin the game. &lt;br /&gt;
Supported start condition types:&lt;br /&gt;
** &#039;&#039;minplayers&#039;&#039; condition ensures at least this many players (an array of values is not supported here)&lt;br /&gt;
** &#039;&#039;maxplayers&#039;&#039; condition ensures at most this many players&lt;br /&gt;
** &#039;&#039;otheroption&#039;&#039; conditions ensure another option is set to this given values. That works the same as in &#039;&#039;&#039;displaycondition&#039;&#039;&#039;.&lt;br /&gt;
** &#039;&#039;otheroptionisnot&#039;&#039; conditions ensure another option is NOT set to this given value.  That works the same as in &#039;&#039;&#039;displaycondition&#039;&#039;&#039;.&lt;br /&gt;
*: For all these condition types, a &#039;&#039;gamestartonly&#039;&#039; boolean option can be added, if you have options that are exclusive. Setting this boolean to &#039;&#039;true&#039;&#039; will defer the evaluation of the startcondition to the game creation, instead of preventing the player to select options that are exclusive at all. See [[#gamestartonly|below]] for an example. &amp;lt;span style=&amp;quot;background: #FFCDD2; color: #B71C1C; padding: 2px;&amp;quot;&amp;gt;But this should never be used -- see the warning below&amp;lt;/span&amp;gt;&lt;br /&gt;
* &#039;&#039;&#039;notdisplayedmessage&#039;&#039;&#039; - if option is not suppose to be visible because of displaycondition but this is set, the text will be visible instead of combo drop down&lt;br /&gt;
* &#039;&#039;&#039;level&#039;&#039;&#039; - what kind of option it is: &#039;&#039;base&#039;&#039;, &#039;&#039;major&#039;&#039;, or &#039;&#039;additional&#039;&#039;. See [[#level|below]] for more informations.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Common (reserved) options for all tables (reserved range 200-299):&lt;br /&gt;
*201 (const GAMESTATE_RATING_MODE) - ELO OFF (aka Training mode), &lt;br /&gt;
**0 = Normal&lt;br /&gt;
**1 = Training&lt;br /&gt;
**2 = Arena&lt;br /&gt;
*200 (const GAMESTATE_CLOCK_MODE) - game speed profile&lt;br /&gt;
**[0, 1, 2] - realtime (technically &amp;lt;10 realtime but you cannot define range in php)&lt;br /&gt;
**values &amp;gt;=10 - turn based (currently 10..21)&lt;br /&gt;
**Note there are two similar values, 9 = realtime &amp;quot;no time limit with friends only&amp;quot; vs. 20 = turn-based &amp;quot;no time limit with friends only&amp;quot;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Example:&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
  &amp;quot;100&amp;quot;: {&lt;br /&gt;
    &amp;quot;name&amp;quot;: &amp;quot;Game Variant&amp;quot;,&lt;br /&gt;
    &amp;quot;values&amp;quot;: {&lt;br /&gt;
      &amp;quot;1&amp;quot;: {&lt;br /&gt;
        &amp;quot;name&amp;quot;: &amp;quot;Learning&amp;quot;,&lt;br /&gt;
        &amp;quot;firstgameonly&amp;quot;: true,&lt;br /&gt;
        &amp;quot;tmdisplay&amp;quot;: &amp;quot;Learning&amp;quot;&lt;br /&gt;
      },&lt;br /&gt;
      &amp;quot;2&amp;quot;: {&lt;br /&gt;
        &amp;quot;name&amp;quot;: &amp;quot;Base&amp;quot;,&lt;br /&gt;
      },&lt;br /&gt;
      &amp;quot;3&amp;quot;: {&lt;br /&gt;
        &amp;quot;name&amp;quot;: &amp;quot;Extended&amp;quot;,&lt;br /&gt;
        &amp;quot;nobeginner&amp;quot;: true,&lt;br /&gt;
        &amp;quot;beta&amp;quot;: true,&lt;br /&gt;
        &amp;quot;tmdisplay&amp;quot;: &amp;quot;Extended&amp;quot;&lt;br /&gt;
      }&lt;br /&gt;
    },&lt;br /&gt;
    &amp;quot;default&amp;quot;: 2&lt;br /&gt;
  },&lt;br /&gt;
  &amp;quot;101&amp;quot;: {&lt;br /&gt;
    &amp;quot;name&amp;quot;: &amp;quot;Draft variant&amp;quot;,&lt;br /&gt;
    &amp;quot;values&amp;quot;: {&lt;br /&gt;
      &amp;quot;1&amp;quot;: {&lt;br /&gt;
        &amp;quot;name&amp;quot;: &amp;quot;No draft&amp;quot;&lt;br /&gt;
      },&lt;br /&gt;
      &amp;quot;2&amp;quot;: {&lt;br /&gt;
        &amp;quot;name&amp;quot;: &amp;quot;Draft&amp;quot;,&lt;br /&gt;
        &amp;quot;tmdisplay&amp;quot;: &amp;quot;Draft&amp;quot;,&lt;br /&gt;
        &amp;quot;premium&amp;quot;: true,&lt;br /&gt;
        &amp;quot;nobeginner&amp;quot;: true&lt;br /&gt;
      }&lt;br /&gt;
    },&lt;br /&gt;
    &amp;quot;displaycondition&amp;quot;: [&lt;br /&gt;
      {&lt;br /&gt;
        &amp;quot;type&amp;quot;: &amp;quot;otheroption&amp;quot;,&lt;br /&gt;
        &amp;quot;id&amp;quot;: 100,&lt;br /&gt;
        &amp;quot;value&amp;quot;: [ 2, 3 ]&lt;br /&gt;
      },&lt;br /&gt;
      {&lt;br /&gt;
        &amp;quot;type&amp;quot;: &amp;quot;otheroption&amp;quot;,&lt;br /&gt;
        &amp;quot;id&amp;quot;: 201,&lt;br /&gt;
        &amp;quot;value&amp;quot;: 1&lt;br /&gt;
      }&lt;br /&gt;
    ],&lt;br /&gt;
    &amp;quot;startcondition&amp;quot;: {&lt;br /&gt;
      &amp;quot;1&amp;quot;: [],&lt;br /&gt;
      &amp;quot;2&amp;quot;: [&lt;br /&gt;
        {&lt;br /&gt;
          &amp;quot;type&amp;quot;: &amp;quot;maxplayers&amp;quot;,&lt;br /&gt;
          &amp;quot;value&amp;quot;: 3,&lt;br /&gt;
          &amp;quot;message&amp;quot;: &amp;quot;Draft option is available for 3 players maximum.&amp;quot;&lt;br /&gt;
        }&lt;br /&gt;
      ]&lt;br /&gt;
    }&lt;br /&gt;
  },&lt;br /&gt;
  &amp;quot;102&amp;quot;: {&lt;br /&gt;
    &amp;quot;name&amp;quot;: &amp;quot;Takeovers&amp;quot;,&lt;br /&gt;
    &amp;quot;values&amp;quot;: {&lt;br /&gt;
      &amp;quot;2&amp;quot;: {&lt;br /&gt;
        &amp;quot;name&amp;quot;: &amp;quot;No takeover&amp;quot;&lt;br /&gt;
      },&lt;br /&gt;
      &amp;quot;1&amp;quot;: {&lt;br /&gt;
        &amp;quot;name&amp;quot;: &amp;quot;Allow takeovers&amp;quot;,&lt;br /&gt;
        &amp;quot;tmdisplay&amp;quot;: &amp;quot;Takeovers&amp;quot;,&lt;br /&gt;
        &amp;quot;premium&amp;quot;: true,&lt;br /&gt;
        &amp;quot;nobeginner&amp;quot;: true&lt;br /&gt;
      }&lt;br /&gt;
    },&lt;br /&gt;
    &amp;quot;displaycondition&amp;quot;: [&lt;br /&gt;
      {&lt;br /&gt;
        &amp;quot;type&amp;quot;: &amp;quot;otheroption&amp;quot;,&lt;br /&gt;
        &amp;quot;id&amp;quot;: 100,&lt;br /&gt;
        &amp;quot;value&amp;quot;: [ 3 ]&lt;br /&gt;
      }&lt;br /&gt;
    ],&lt;br /&gt;
    &amp;quot;startcondition&amp;quot;: {&lt;br /&gt;
      &amp;quot;2&amp;quot;: [],&lt;br /&gt;
      &amp;quot;1&amp;quot;: [&lt;br /&gt;
        {&lt;br /&gt;
          &amp;quot;type&amp;quot;: &amp;quot;maxplayers&amp;quot;,&lt;br /&gt;
          &amp;quot;value&amp;quot;: 2,&lt;br /&gt;
          &amp;quot;message&amp;quot;: &amp;quot;Rebel vs Imperium Takeover Scenario is available for 2 players only.&amp;quot;&lt;br /&gt;
        }&lt;br /&gt;
      ]&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Example of option that condition on ELO off:&#039;&#039;&#039;&lt;br /&gt;
 {&lt;br /&gt;
   &amp;quot;100&amp;quot;: {&lt;br /&gt;
     &amp;quot;name&amp;quot;: &amp;quot;Learning Game (No Research)&amp;quot;,&lt;br /&gt;
     &amp;quot;values&amp;quot;: {&lt;br /&gt;
       &amp;quot;1&amp;quot;: {&lt;br /&gt;
         &amp;quot;name&amp;quot;: &amp;quot;Off&amp;quot;,&lt;br /&gt;
         &amp;quot;tmdisplay&amp;quot;: &amp;quot;&amp;quot;&lt;br /&gt;
       },&lt;br /&gt;
       &amp;quot;2&amp;quot;: {&lt;br /&gt;
         &amp;quot;name&amp;quot;: &amp;quot;On&amp;quot;,&lt;br /&gt;
         &amp;quot;tmdisplay&amp;quot;: &amp;quot;Learning Game&amp;quot;&lt;br /&gt;
       }&lt;br /&gt;
     },&lt;br /&gt;
     &amp;quot;startcondition&amp;quot;: {&lt;br /&gt;
       &amp;quot;2&amp;quot;: {&lt;br /&gt;
         &amp;quot;type&amp;quot;: &amp;quot;otheroption&amp;quot;,&lt;br /&gt;
         &amp;quot;id&amp;quot;: 201,&lt;br /&gt;
         &amp;quot;value&amp;quot;: 1,&lt;br /&gt;
         &amp;quot;message&amp;quot;: &amp;quot;Learning variant available only in friendly mode&amp;quot;&lt;br /&gt;
       }&lt;br /&gt;
     }&lt;br /&gt;
   }&lt;br /&gt;
 }&lt;br /&gt;
&#039;&#039;&#039;Example of condition that is only available for REALTIME game mode:&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;quot;displaycondition&amp;quot;: [&lt;br /&gt;
    { &amp;quot;type&amp;quot;: &amp;quot;otheroption&amp;quot;, &amp;quot;id&amp;quot;: 200, &amp;quot;value&amp;quot;: [0, 1, 2] }&lt;br /&gt;
],&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Example of using condition on your own option:&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
  &amp;quot;102&amp;quot;: {&lt;br /&gt;
    &amp;quot;name&amp;quot;: &amp;quot;Scenarios&amp;quot;,&lt;br /&gt;
    &amp;quot;values&amp;quot;: {&lt;br /&gt;
      &amp;quot;1&amp;quot;: {&lt;br /&gt;
        &amp;quot;name&amp;quot;: &amp;quot;Off&amp;quot;,&lt;br /&gt;
        &amp;quot;nobeginner&amp;quot;: false&lt;br /&gt;
      },&lt;br /&gt;
      &amp;quot;2&amp;quot;: {&lt;br /&gt;
        &amp;quot;name&amp;quot;: &amp;quot;On&amp;quot;,&lt;br /&gt;
        &amp;quot;tmdisplay&amp;quot;: &amp;quot;Scenarios&amp;quot;,&lt;br /&gt;
        &amp;quot;nobeginner&amp;quot;: true&lt;br /&gt;
      }&lt;br /&gt;
    },&lt;br /&gt;
    &amp;quot;displaycondition&amp;quot;: [&lt;br /&gt;
      {&lt;br /&gt;
        &amp;quot;type&amp;quot;: &amp;quot;otheroptionisnot&amp;quot;,&lt;br /&gt;
        &amp;quot;id&amp;quot;: 100,&lt;br /&gt;
        &amp;quot;value&amp;quot;: 1&lt;br /&gt;
      }&lt;br /&gt;
    ],&lt;br /&gt;
    &amp;quot;notdisplayedmessage&amp;quot;: &amp;quot;Scenarios variant is not available if Learning variant is chosen&amp;quot;&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Example of handling solo vs multiplayer options:&#039;&#039;&#039;&amp;lt;pre&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
  &amp;quot;100&amp;quot;: {&lt;br /&gt;
    &amp;quot;name&amp;quot;: &amp;quot;Board setup&amp;quot;,&lt;br /&gt;
    &amp;quot;values&amp;quot;: {&lt;br /&gt;
      &amp;quot;1&amp;quot;: {&lt;br /&gt;
        &amp;quot;name&amp;quot;: &amp;quot;Mirror setup&amp;quot;,&lt;br /&gt;
        &amp;quot;description&amp;quot;: &amp;quot;The starting player shuffles their 6 Farm Cards and randomly lays a card face up in each of the round spaces of their Fruit Island Board. The other players then lay their cards in exactly the same way, copying the order of the starting player.&amp;quot;,&lt;br /&gt;
        &amp;quot;tmdisplay&amp;quot;: &amp;quot;Mirror setup&amp;quot;&lt;br /&gt;
      },&lt;br /&gt;
      &amp;quot;2&amp;quot;: {&lt;br /&gt;
        &amp;quot;name&amp;quot;: &amp;quot;Random setup&amp;quot;,&lt;br /&gt;
        &amp;quot;description&amp;quot;: &amp;quot;Instead of every player copying the same card configuration as the starting player, every player shuffles their Farm Cards and lays down the cards randomly on their Fruit Island Board.&amp;quot;,&lt;br /&gt;
        &amp;quot;tmdisplay&amp;quot;: &amp;quot;Random setup&amp;quot;&lt;br /&gt;
      }&lt;br /&gt;
    },&lt;br /&gt;
    &amp;quot;displaycondition&amp;quot;: [&lt;br /&gt;
      {&lt;br /&gt;
        &amp;quot;type&amp;quot;: &amp;quot;minplayers&amp;quot;,&lt;br /&gt;
        &amp;quot;value&amp;quot;: [&lt;br /&gt;
          2,&lt;br /&gt;
          3,&lt;br /&gt;
          4&lt;br /&gt;
        ]&lt;br /&gt;
      }&lt;br /&gt;
    ]&lt;br /&gt;
  },&lt;br /&gt;
  &amp;quot;102&amp;quot;: {&lt;br /&gt;
    &amp;quot;name&amp;quot;: &amp;quot;Solo difficulty&amp;quot;,&lt;br /&gt;
    &amp;quot;values&amp;quot;: [&lt;br /&gt;
      {&lt;br /&gt;
        &amp;quot;name&amp;quot;: &amp;quot;Banana-apprentice&amp;quot;,&lt;br /&gt;
        &amp;quot;description&amp;quot;: &amp;quot;Do not remove any seed before starting the game.&amp;quot;,&lt;br /&gt;
        &amp;quot;tmdisplay&amp;quot;: &amp;quot;Banana-apprentice&amp;quot;&lt;br /&gt;
      },&lt;br /&gt;
      {&lt;br /&gt;
        &amp;quot;name&amp;quot;: &amp;quot;Pear to the Throne&amp;quot;,&lt;br /&gt;
        &amp;quot;description&amp;quot;: &amp;quot;Remove 1 seed before starting the game.&amp;quot;,&lt;br /&gt;
        &amp;quot;tmdisplay&amp;quot;: &amp;quot;Pear to the Throne&amp;quot;&lt;br /&gt;
      }&lt;br /&gt;
    ],&lt;br /&gt;
    &amp;quot;displaycondition&amp;quot;: [&lt;br /&gt;
      {&lt;br /&gt;
        &amp;quot;type&amp;quot;: &amp;quot;maxplayers&amp;quot;,&lt;br /&gt;
        &amp;quot;value&amp;quot;: 1&lt;br /&gt;
      }&lt;br /&gt;
    ]&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== displaycondition vs startcondition ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;displaycondition&amp;lt;/code&amp;gt; should be used when an option should not be present in the list under certain conditions.&lt;br /&gt;
&lt;br /&gt;
For example, displaying the option which is consistent with the player count.&lt;br /&gt;
&lt;br /&gt;
* 2 player maps: A B C D &lt;br /&gt;
* 3 player maps: E F G H&lt;br /&gt;
* 4 player maps: I J K L&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;startcondition&amp;lt;/code&amp;gt; should be used when a specific combination of option values is invalid, but the option itself still makes sense to show.&lt;br /&gt;
&lt;br /&gt;
For example:&lt;br /&gt;
&lt;br /&gt;
* Player 1 faction: A, B, C, D, E, F, G&lt;br /&gt;
* Player 2 faction: A, B, C, D, E, F, G&lt;br /&gt;
* startcondition: both players can&#039;t be the same faction&lt;br /&gt;
&lt;br /&gt;
These options should both be displayed at all times, but there are some invalid configurations.&lt;br /&gt;
&lt;br /&gt;
The other difference is displaycondition affect option itself, while startcondition affect specific values selected&lt;br /&gt;
&lt;br /&gt;
==== gamestartonly ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;padding: 1em; background: #FFCDD2; color: #B71C1C&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;b&amp;gt;WARNING:&amp;lt;/b&amp;gt; [https://studio.boardgamearena.com/bug?id=104 See studio bug #104]. You should &amp;lt;b&amp;gt;NEVER&amp;lt;/b&amp;gt; use &amp;lt;code&amp;gt;gamestartonly&amp;lt;/code&amp;gt;! Otherwise, you allow players to (unknowingly!) create a turn-based table with impossible options that can never start. Players receive no indication that the option combination they selected is invalid until the last player joins the table (hours or days later) and the game attempts to auto-start. The table won&#039;t start because of the &amp;lt;code&amp;gt;startcondition&amp;lt;/code&amp;gt;, and the table options cannot be changed because it&#039;s a turn-based table, so the table must be abandoned. This is a horrible user experience. Please don&#039;t subject players to this.&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
On the table configuration page, it won&#039;t let you select a combination which is invalid according to &amp;lt;code&amp;gt;startcondition&amp;lt;/code&amp;gt;. Doing so will show a red warning, and will revert the option to the previous value. This means you could end up in a situation where you can&#039;t easily change between certain options (requiring you to set or unset options in a specific order).&lt;br /&gt;
&lt;br /&gt;
The consequence of the &amp;lt;code&amp;gt;gamestartonly&amp;lt;/code&amp;gt; flag is that the player _can_ select an invalid combination. However, when clicking &amp;quot;Start&amp;quot;, an invalid combination will produce an error.&lt;br /&gt;
&lt;br /&gt;
Probably the easiest way to see what the difference is is with an example.&lt;br /&gt;
&lt;br /&gt;
With a _Clans of Caledonia_ table:&lt;br /&gt;
* set to training mode&lt;br /&gt;
* set player count to 1&lt;br /&gt;
* try setting &amp;quot;Clan Auction&amp;quot; to one of the &amp;quot;On&amp;quot; options&lt;br /&gt;
* try starting the game, there&#039;s an error! Ie. &amp;lt;code&amp;gt;&amp;quot;gamestartonly&amp;quot; =&amp;gt; true&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Then, with a _Sushi Go Party!_ table:&lt;br /&gt;
* set number of players to 7&lt;br /&gt;
* try setting &amp;quot;Sushi Go! / Sushi Go Party!&amp;quot; to &amp;quot;Sushi Go!&amp;quot;&lt;br /&gt;
* you can&#039;t set the option! Ie. &amp;lt;code&amp;gt;&amp;quot;gamestartonly&amp;quot; =&amp;gt; false&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In code:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
  &amp;quot;100&amp;quot;: {&lt;br /&gt;
    &amp;quot;name&amp;quot;: &amp;quot;Option name&amp;quot;,&lt;br /&gt;
    &amp;quot;values&amp;quot;: [],&lt;br /&gt;
    &amp;quot;startcondition&amp;quot;: {&lt;br /&gt;
      &amp;quot;1&amp;quot;: [&lt;br /&gt;
        {&lt;br /&gt;
          &amp;quot;type&amp;quot;: &amp;quot;maxplayers&amp;quot;,&lt;br /&gt;
          &amp;quot;value&amp;quot;: 2,&lt;br /&gt;
          &amp;quot;message&amp;quot;: &amp;quot;This option is available for 2 players only.&amp;quot;,&lt;br /&gt;
          &amp;quot;gamestartonly&amp;quot;: true&lt;br /&gt;
        }&lt;br /&gt;
      ]&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== level ====&lt;br /&gt;
Note: at this moment this only have impact in fancy lobby mode, presentation of level or checkboxes are not avaiable via normal table creation ui (such as in studio, or when you click Play button in control panel)&amp;lt;pre&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
    &amp;quot;100&amp;quot;: {&lt;br /&gt;
        &amp;quot;name&amp;quot;: &amp;quot;Option name&amp;quot;,&lt;br /&gt;
        &amp;quot;values&amp;quot;: [...],&lt;br /&gt;
        &amp;quot;level&amp;quot;: &amp;quot;major&amp;quot;&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;base&#039;&#039;&#039; is the default value (you don&#039;t need to specify it).&lt;br /&gt;
* &#039;&#039;&#039;major&#039;&#039;&#039; denotes a major option, which will always be displayed on top, and with a specific UI.&lt;br /&gt;
* &#039;&#039;&#039;additional&#039;&#039;&#039; means this option will not be displayed by default, to unclutter the option panel.&lt;br /&gt;
&lt;br /&gt;
About major options:&lt;br /&gt;
* a game can only have &#039;&#039;&#039;1 major option&#039;&#039;&#039;, and of course, it must be a important game changer.&lt;br /&gt;
* the pictures will default to the standard Game Box, and can be set independently for each value, from the [[Game metadata manager]] (in the &amp;quot;Major Variants&amp;quot; section). Note: this cannot be tested from Studio as there is not studio-only Game metadata manager, to see Major Variants option - the game has to be deployed at least as alpha.&lt;br /&gt;
* the major option can have more than 2 values (there will then be an arrow to slide to the other values, carousel-like)&lt;br /&gt;
* the naming of major variant values should be concise and the values should have descriptive text (not just &amp;quot;enabled&amp;quot; or &amp;quot;disabled&amp;quot;)&lt;br /&gt;
** 👍 Option name &amp;quot;Expansion&amp;quot;, option values &amp;quot;Base game&amp;quot;, &amp;quot;Bigger is Better&amp;quot; =&amp;gt; Displayed as &#039;&#039;&amp;quot;Expansion: Base game&amp;quot;&#039;&#039; or &#039;&#039;&amp;quot;Expansion: Bigger is Better&amp;quot;&#039;&#039;&lt;br /&gt;
** 👎 Option name &amp;quot;Bigger is Better&amp;quot;, option values &amp;quot;Enabled&amp;quot;, &amp;quot;Disabled =&amp;gt; Displayed as &#039;&#039;&amp;quot;Bigger is Better: Enabled&amp;quot;&#039;&#039; or &#039;&#039;&amp;quot;Bigger is Better: Disabled&amp;quot;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
About additional options:&lt;br /&gt;
* please set each option that concerns small details in this category: advanced players will find this option anyway, and it will simplify the interface of the page of your game.&lt;br /&gt;
&lt;br /&gt;
[[File:Option-levels.png|800px|Option levels]]&lt;br /&gt;
&lt;br /&gt;
==== option presentation ====&lt;br /&gt;
&lt;br /&gt;
An option WILL be displayed as a &#039;&#039;&#039;Checkbox&#039;&#039;&#039; instead of a selector if certain conditions are met:&lt;br /&gt;
&lt;br /&gt;
* option has only &#039;&#039;&#039;2 values&#039;&#039;&#039;&lt;br /&gt;
* values are either (case insensitive):&lt;br /&gt;
** &#039;&#039;yes&#039;&#039; and &#039;&#039;no&#039;&#039;&lt;br /&gt;
** &#039;&#039;on&#039;&#039; and &#039;&#039;off&#039;&#039;&lt;br /&gt;
** &#039;&#039;enabled&#039;&#039; and &#039;&#039;disabled&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
The &amp;quot;default&amp;quot; value still has to be specified, and can be &amp;quot;on&amp;quot; or &amp;quot;off&amp;quot; (it&#039;s actually just a difference in display).&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[File:Option-display.png|800px|Example of checkbox display]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== User Preferences ==&lt;br /&gt;
&lt;br /&gt;
User preferences is something cosmetic about the game interface which however can create user wars, so you can satisfy all users&lt;br /&gt;
by giving them individual preferences. You should use this only if it significantly improves the interface for a large proportion of users.&lt;br /&gt;
These preferences appear in the three-line hamburger menu in the top corner of the bga menu (and also at the bottom on the page in the Options tab).  &lt;br /&gt;
&amp;quot;Display game logs&amp;quot; and &amp;quot;Display tooltips&amp;quot; are baked-in by default, but you can extend this list as below. &lt;br /&gt;
&lt;br /&gt;
The preference json slightly resembles options, but these are conceptually different. The numbers comes from diffrent space and do not correspond or conflict with options,&lt;br /&gt;
i.e. preference 100 has nothing to do with option 100. You can use range 100-199 with gaps.&lt;br /&gt;
&lt;br /&gt;
[[File:century_preferences_menu.PNG|400px|The user preferences menu for the game Century]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;&lt;br /&gt;
&#039;&#039;These preferences are a good place to put accessibility options - as Century did for its Colorblind Support.&#039;&#039;&lt;br /&gt;
&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
  &amp;quot;100&amp;quot;: {&lt;br /&gt;
    &amp;quot;name&amp;quot;: &amp;quot;Colorblind Support&amp;quot;,&lt;br /&gt;
    &amp;quot;needReload&amp;quot;: true,&lt;br /&gt;
    &amp;quot;values&amp;quot;: {&lt;br /&gt;
      &amp;quot;1&amp;quot;: {&lt;br /&gt;
        &amp;quot;name&amp;quot;: &amp;quot;None&amp;quot;,&lt;br /&gt;
        &amp;quot;cssPref&amp;quot;: &amp;quot;colorblind_off&amp;quot;&lt;br /&gt;
      },&lt;br /&gt;
      &amp;quot;2&amp;quot;: {&lt;br /&gt;
        &amp;quot;name&amp;quot;: &amp;quot;Numbers&amp;quot;,&lt;br /&gt;
        &amp;quot;cssPref&amp;quot;: &amp;quot;colorblind_on&amp;quot;&lt;br /&gt;
      },&lt;br /&gt;
      &amp;quot;3&amp;quot;: {&lt;br /&gt;
        &amp;quot;name&amp;quot;: &amp;quot;Shapes&amp;quot;,&lt;br /&gt;
        &amp;quot;cssPref&amp;quot;: &amp;quot;colorblind_shapes&amp;quot;&lt;br /&gt;
      }&lt;br /&gt;
    },&lt;br /&gt;
    &amp;quot;default&amp;quot;: 1&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
There is two ways to check/apply this. In javascript&lt;br /&gt;
&lt;br /&gt;
  if (this.getGameUserPreference(100) == 2) ...&lt;br /&gt;
&lt;br /&gt;
This checks if preferences 100 has selected value 2.&lt;br /&gt;
&lt;br /&gt;
Second, if cssPref specified it will be applied to the &#039;&#039;&#039;&amp;lt;html&amp;gt;&#039;&#039;&#039; tag. So you can use different css styling for the preference. Note: you also need to set needReload to true for that class change to be effective.&lt;br /&gt;
&lt;br /&gt;
As user you have to select them from the Gear menu when game is started. On studio only dev0 account will have it actually working (bug?).&lt;br /&gt;
&lt;br /&gt;
The following are the parameters of preferences description array:&lt;br /&gt;
* &#039;&#039;&#039;name&#039;&#039;&#039; - &#039;&#039;&#039;mandatory&#039;&#039;&#039;. The name of the preference. This string is marked for translation.&lt;br /&gt;
* &#039;&#039;&#039;needReload&#039;&#039;&#039; - If set to true, the game interface will auto-reload after a change of the preference.&lt;br /&gt;
* &#039;&#039;&#039;values&#039;&#039;&#039; - &#039;&#039;&#039;mandatory&#039;&#039;&#039;. The map of values with additional parameters per value.&lt;br /&gt;
** &#039;&#039;&#039;name&#039;&#039;&#039; - &#039;&#039;&#039;mandatory&#039;&#039;&#039;. String representation of the numeric value.  This string is marked for translation.&lt;br /&gt;
** &#039;&#039;&#039;cssPref&#039;&#039;&#039; - CSS class to add to the &#039;&#039;&#039;&amp;lt;html&amp;gt;&#039;&#039;&#039; tag. Currently it is added or removed only after a reload (see needReload).&lt;br /&gt;
* &#039;&#039;&#039;default&#039;&#039;&#039; - Indicates the default value to use for this preference (optional, if not present the first value listed is the default).&lt;br /&gt;
&lt;br /&gt;
=== Listening for preference changes and updating preference from code ===&lt;br /&gt;
The BGA framework offers read/write and callback for user preference changes. See [[Game interface logic: yourgamename.js#User preferences]]&lt;br /&gt;
&lt;br /&gt;
=== Accessing User Preferences on the server ===&lt;br /&gt;
PHP has a variable called $this-&amp;gt;player_preferences.&lt;br /&gt;
This contains a table of player preferences, ONLY accessible in setupNewGame().&lt;br /&gt;
You can use this to populate a table that you manage yourself.&lt;br /&gt;
You have to update the table when a player changes preference (and you have to hook up a listener and initiate an AJAX call out-of-turn).&lt;br /&gt;
Check the code of Agricola for details but this should work:&lt;br /&gt;
&lt;br /&gt;
; In dbmodel.sql&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
CREATE TABLE IF NOT EXISTS `user_preferences` (&lt;br /&gt;
  `player_id` int(10) NOT NULL,&lt;br /&gt;
  `pref_id` int(10) NOT NULL,&lt;br /&gt;
  `pref_value` int(10) NOT NULL,&lt;br /&gt;
  PRIMARY KEY (`player_id`, `pref_id`)&lt;br /&gt;
) ENGINE=InnoDB DEFAULT CHARSET=utf8;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
; In ggg.game.php&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
protected function setupNewGame($players, $options = array())&lt;br /&gt;
{&lt;br /&gt;
// TODO: Save $this-&amp;gt;player_preferences: key is player_id, value is array with pref_id as key and pref_value as value&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Warning: &amp;lt;code&amp;gt;$this-&amp;gt;player_preferences[$player_id]&amp;lt;/code&amp;gt; can be null if the player has not set any player preferences.&lt;br /&gt;
&lt;br /&gt;
Note: to access json values you can call:&lt;br /&gt;
   $game_preferences = $this-&amp;gt;getTablePreferences();&lt;br /&gt;
&lt;br /&gt;
Warning: if you use bga undo system make sure this table is not restored from undo state, as this likely independed from it&lt;br /&gt;
&lt;br /&gt;
; In ggg.js&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
// use code for initPreferencesObserver from above example&lt;br /&gt;
&lt;br /&gt;
onGameUserPreferenceChanged(prefId, prefValue) {&lt;br /&gt;
    if (prefId === 101 /*TODO: You probably want to send only some preferences*/) {&lt;br /&gt;
        // TODO: Code your own action in ggg.action.php and send it prefId and prefValue&lt;br /&gt;
        //       The on the server side you can save it all in the user_preferences&lt;br /&gt;
        //       table you created above.&lt;br /&gt;
    }&lt;br /&gt;
},&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Translations ==&lt;br /&gt;
Note that any name or description values in these JSON files are automatically added to the translation system.&lt;br /&gt;
&lt;br /&gt;
== Migration ==&lt;br /&gt;
Previously, options and preferences were specified in a single &amp;lt;code&amp;gt;gameoptions.inc.php&amp;lt;/code&amp;gt; file.&lt;br /&gt;
&lt;br /&gt;
BGA has switched to a JSON format to make parsing easier on the server-side, and to avoid a reliance on PHP for static config.&lt;br /&gt;
&lt;br /&gt;
The PHP format will continue to work for &#039;&#039;existing&#039;&#039; games, and although preferred, there is no need to migrate unless you want to. However, newly created games must use the new format.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note&#039;&#039;&#039;: once a game has been committed with a &amp;lt;code&amp;gt;gameoptions.json&amp;lt;/code&amp;gt; file, however, it is not possible to go back without admin intervention.&lt;br /&gt;
&lt;br /&gt;
If you want to migrate:&lt;br /&gt;
&lt;br /&gt;
Simple method:&lt;br /&gt;
* Go to studio and press Reload game options configuration&lt;br /&gt;
* It will dump json on the log window - you can take this, format it and save into 2 files (if you have both). For gamepreference.json remove option &amp;quot;200&amp;quot; - this is default common option, it should not be in your file.&lt;br /&gt;
&lt;br /&gt;
Manual method:&lt;br /&gt;
* Remove all calls to &amp;lt;code&amp;gt;totranslate()&amp;lt;/code&amp;gt;, and replace with the plain string&lt;br /&gt;
* Remove any references to BGA&#039;s PHP constants, such as GAMESTATE_RATING_MODE, and replace with the plain value (in this case, 201)&lt;br /&gt;
* You can populate &amp;lt;code&amp;gt;gameinfos.json&amp;lt;/code&amp;gt; with the result of &amp;lt;code&amp;gt;json_encode($game_options, JSON_PRETTY_PRINT)&amp;lt;/code&amp;gt;&lt;br /&gt;
* You can populate &amp;lt;code&amp;gt;gamepreferences.json&amp;lt;/code&amp;gt; with the result of &amp;lt;code&amp;gt;json_encode($game_preferences, JSON_PRETTY_PRINT)&amp;lt;/code&amp;gt;&lt;br /&gt;
* If you include gameoptions.inc.php directly, to read the values, then replace those calls with &amp;lt;code&amp;gt;$this-&amp;gt;getTableOptions()&amp;lt;/code&amp;gt; or &amp;lt;code&amp;gt;$this-&amp;gt;getTablePreferences()&amp;lt;/code&amp;gt; as appropriate which return arrays parsed from the JSON files&lt;br /&gt;
This message was posted to the developer Discord channel:&amp;lt;blockquote&amp;gt;&#039;&#039;&#039;Game options change (Optional!)&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;gameoptions.inc.php&amp;lt;/code&amp;gt; is now considered legacy, and &amp;lt;code&amp;gt;gameoptions.json&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;gamepreferences.json&amp;lt;/code&amp;gt; are recommended for new projects:&lt;br /&gt;
&lt;br /&gt;
* The wiki and the template project have been updated: [[/en.doc.boardgamearena.com/Options and preferences: gameoptions.json, gamepreferences.json|https://en.doc.boardgamearena.com/Options_and_preferences:_gameoptions.json,_gamepreferences.json]]&lt;br /&gt;
* Any questions/problems can come to me, or can be asked here.&lt;br /&gt;
* The format of the json files matches the format of the old php files&lt;br /&gt;
&lt;br /&gt;
We realise there are some drawbacks (sorry!):&lt;br /&gt;
&lt;br /&gt;
* No comments in the JSON file, meaning you have to check the wiki for examples&lt;br /&gt;
* No PHP constants in the JSON file, meaning magic numbers&lt;br /&gt;
&lt;br /&gt;
However, we hope it&#039;s good for BGA because:&lt;br /&gt;
&lt;br /&gt;
* Simpler to parse (for robots and humans)&lt;br /&gt;
* Easier to check for errors (we could perhaps use an XSLT one day)&lt;br /&gt;
* No need to run game-specific PHP code on the metasite&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;NOTE&#039;&#039;&#039;: Switching is totally optional, and the legacy files will still work for existing projects, and for those who know about them. &amp;lt;/blockquote&amp;gt;&lt;br /&gt;
[[Category:Studio]]&lt;/div&gt;</summary>
		<author><name>Sguzzer Gunayer</name></author>
	</entry>
	<entry>
		<id>https://en.doc.boardgamearena.com/index.php?title=Options_and_preferences:_gameoptions.json,_gamepreferences.json&amp;diff=22488</id>
		<title>Options and preferences: gameoptions.json, gamepreferences.json</title>
		<link rel="alternate" type="text/html" href="https://en.doc.boardgamearena.com/index.php?title=Options_and_preferences:_gameoptions.json,_gamepreferences.json&amp;diff=22488"/>
		<updated>2024-09-07T09:22:11Z</updated>

		<summary type="html">&lt;p&gt;Sguzzer Gunayer: /* displaycondition vs startcondition */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Studio_Framework_Navigation}}&lt;br /&gt;
&lt;br /&gt;
In &amp;lt;code&amp;gt;gameoptions.json&amp;lt;/code&amp;gt;, you can define your game options (i.e. game variants).&lt;br /&gt;
&lt;br /&gt;
In &amp;lt;code&amp;gt;gamepreferences.json&amp;lt;/code&amp;gt;, you can define user preferences.&lt;br /&gt;
   &lt;br /&gt;
Note: If your game has no variants or preferences, you don&#039;t have to modify these files.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;IMPORTANT:&#039;&#039;&#039; after edits to these files, you have to go to the control panel and press &amp;quot;Reload game options configuration&amp;quot; on Studio for your changes &#039;&#039;&#039;to take effect&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
Make sure you understand difference between options and preferences:&lt;br /&gt;
* Game options - something usually in the rule book defined as &amp;quot;variant&amp;quot; (except for player count, which is automatically handled). For example, whether to include &#039;&#039;The River&#039;&#039; in Carcassonne.&lt;br /&gt;
* User preferences - personal choices of each player only visible to that specific player - i.e. layout, whether or not to prompt for action, whether or not auto-opt in in some actions, etc.&lt;br /&gt;
&lt;br /&gt;
__TOC__&lt;br /&gt;
&lt;br /&gt;
== Game Options ==&lt;br /&gt;
&lt;br /&gt;
Game options are selected by the table creator and usually correspond to game variants, for example if the game includes expansions or certain special rules.&lt;br /&gt;
&lt;br /&gt;
These variants are defined in &amp;lt;code&amp;gt;gameoptions.json&amp;lt;/code&amp;gt; as an object:  &lt;br /&gt;
&lt;br /&gt;
  {&lt;br /&gt;
     &amp;quot;100&amp;quot;: { &amp;quot;name&amp;quot;: &amp;quot;Game Setup&amp;quot;, ... },&lt;br /&gt;
     &amp;quot;101&amp;quot;: { &amp;quot;name&amp;quot;: &amp;quot;Draft&amp;quot;, ... }&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
Each key corresponds to the option id, and each value is that option definition, which is described below.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note:&#039;&#039;&#039; the file must be valid [https://www.json.org/ JSON]. That is, trailing commas and comments are not allowed. However you can use still standard json hack to add a field like &amp;quot;$comment&amp;quot;: &amp;quot;Here we go&amp;quot;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note 2:&#039;&#039;&#039; the key in json file must be a string type, even its correspond to a number in other places (such as php, or other references in same json).&lt;br /&gt;
&lt;br /&gt;
All options defined in this file should have a corresponding &amp;quot;game state label&amp;quot; with the same ID (see &amp;quot;initGameStateLabels&amp;quot; in yourgame.game.php)&lt;br /&gt;
&lt;br /&gt;
             self::initGameStateLabels ([&lt;br /&gt;
                        ...&lt;br /&gt;
                        &amp;quot;my_game_variant&amp;quot; =&amp;gt; 100,&lt;br /&gt;
              ]);&lt;br /&gt;
&lt;br /&gt;
Numbers have to be exactly from 100 to 199 (there can be gaps).&lt;br /&gt;
&lt;br /&gt;
That is how you access them during runtime (by name):&lt;br /&gt;
&lt;br /&gt;
    public function isSecondVariant() {&lt;br /&gt;
        return $this-&amp;gt;getGameStateValue(&#039;my_game_variant&#039;) == 2;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
Or this (by numberic id)&lt;br /&gt;
    $this-&amp;gt;gamestate-&amp;gt;table_globals[100]&lt;br /&gt;
To access json data (the metadata only) can use&lt;br /&gt;
   $game_options = $this-&amp;gt;getTableOptions();&lt;br /&gt;
=== Details of game options format ===&lt;br /&gt;
&lt;br /&gt;
The following are the values of the option definition object:&lt;br /&gt;
* &#039;&#039;&#039;name&#039;&#039;&#039; - &#039;&#039;&#039;mandatory&#039;&#039;&#039;. The name of the option visible for table creator. This is automatically marked for translation.&lt;br /&gt;
* &#039;&#039;&#039;values&#039;&#039;&#039; - &#039;&#039;&#039;mandatory&#039;&#039;&#039;. The map representing possible values of this option. The key of the map is possible value of this option, its a number but has to be string in json. The value is an object descring it.&lt;br /&gt;
** &#039;&#039;&#039;name&#039;&#039;&#039; - &#039;&#039;&#039;mandatory&#039;&#039;&#039;. String representation of the numeric value visible to table creator. This is automatically marked for translation.&lt;br /&gt;
** &#039;&#039;&#039;description&#039;&#039;&#039; - String description of this value to use when the name of the option is not self-explanatory. Displayed at the table under the option when this value is selected. Note: if there is no description, this should be omitted.&lt;br /&gt;
** &#039;&#039;&#039;tmdisplay&#039;&#039;&#039; - String representation of the option visible in the table description in the lobby. Usually if a variant values are On and Off (default), the tmdisplay would be same as description name when On, and nothing (empty string) when Off. (&#039;&#039;&#039;Warning&#039;&#039;&#039;: due to some caching, a change in tmdisplay may not be effective immediately in the studio, even after forcing a reload of options.) &#039;&#039;&#039;Pro Tip:&#039;&#039;&#039; You can use this as a pre-game communication by adding fake options that just do nothing in the game but make it easier to find other player wanted the same game configuration (see the crew deep sea for example).&lt;br /&gt;
** &#039;&#039;&#039;nobeginner&#039;&#039;&#039; - Set to true if not recommended for beginners&lt;br /&gt;
** &#039;&#039;&#039;firstgameonly&#039;&#039;&#039; - Set to true if this option is recommended only for the first game (discovery option)&lt;br /&gt;
** &#039;&#039;&#039;beta&#039;&#039;&#039; - Set to true to indicate that this option is in &amp;quot;beta&amp;quot; development stage (there will be a warning for players starting the game)&lt;br /&gt;
** &#039;&#039;&#039;alpha&#039;&#039;&#039; - Set to true to indicate that this option is in &amp;quot;alpha&amp;quot; development stage (there will be a warning, and starting the game will be allowed only in training mode except for the developer)&lt;br /&gt;
** &#039;&#039;&#039;premium&#039;&#039;&#039; - Option can be only used by premium members&lt;br /&gt;
* &#039;&#039;&#039;default&#039;&#039;&#039; - indicates the default value to use for this option (optional, if not present the first value listed is the default)&lt;br /&gt;
* &#039;&#039;&#039;displaycondition&#039;&#039;&#039; - (array of conditions) - checks the conditions before displaying the option for selection. All (or any) conditions must be true for the option to be displayed. All or any depends on value of displayconditionoperand&lt;br /&gt;
Supported display condition types:&lt;br /&gt;
** &#039;&#039;minplayers&#039;&#039; condition ensures at least this many players (Note: if your game works with a disjoint interval of player counts, you can supply an array of valid counts instead of a single value)&lt;br /&gt;
** &#039;&#039;maxplayers&#039;&#039; condition ensures at most this many players&lt;br /&gt;
** &#039;&#039;otheroption&#039;&#039; condition ensures another option is set to given values. &lt;br /&gt;
** &#039;&#039;otheroptionisnot&#039;&#039; condition ensure another option is NOT set to this given values&lt;br /&gt;
* &#039;&#039;&#039;displayconditionoperand&#039;&#039;&#039; - can be &#039;and&#039; (this is the default) or &#039;or&#039;. Allows to change the behaviour to display the option if one of the conditions is true instead of all of them.&lt;br /&gt;
* &#039;&#039;&#039;startcondition&#039;&#039;&#039; - (map from value to conditions array) - checks the conditions (on options VALUES) before starting the game. All conditions must be true for the game to start, otherwise players will get a red error message when attempting to begin the game. &lt;br /&gt;
Supported start condition types:&lt;br /&gt;
** &#039;&#039;minplayers&#039;&#039; condition ensures at least this many players (an array of values is not supported here)&lt;br /&gt;
** &#039;&#039;maxplayers&#039;&#039; condition ensures at most this many players&lt;br /&gt;
** &#039;&#039;otheroption&#039;&#039; conditions ensure another option is set to this given values. That works the same as in &#039;&#039;&#039;displaycondition&#039;&#039;&#039;.&lt;br /&gt;
** &#039;&#039;otheroptionisnot&#039;&#039; conditions ensure another option is NOT set to this given value.  That works the same as in &#039;&#039;&#039;displaycondition&#039;&#039;&#039;.&lt;br /&gt;
*: For all these condition types, a &#039;&#039;gamestartonly&#039;&#039; boolean option can be added, if you have options that are exclusive. Setting this boolean to &#039;&#039;true&#039;&#039; will defer the evaluation of the startcondition to the game creation, instead of preventing the player to select options that are exclusive at all. See [[#gamestartonly|below]] for an example. &amp;lt;span style=&amp;quot;background: #FFCDD2; color: #B71C1C; padding: 2px;&amp;quot;&amp;gt;But this should never be used -- see the warning below&amp;lt;/span&amp;gt;&lt;br /&gt;
* &#039;&#039;&#039;notdisplayedmessage&#039;&#039;&#039; - if option is not suppose to be visible because of displaycondition but this is set, the text will be visible instead of combo drop down&lt;br /&gt;
* &#039;&#039;&#039;level&#039;&#039;&#039; - what kind of option it is: &#039;&#039;base&#039;&#039;, &#039;&#039;major&#039;&#039;, or &#039;&#039;additional&#039;&#039;. See [[#level|below]] for more informations.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Common (reserved) options for all tables (reserved range 200-299):&lt;br /&gt;
*201 (const GAMESTATE_RATING_MODE) - ELO OFF (aka Training mode), &lt;br /&gt;
**0 = Normal&lt;br /&gt;
**1 = Training&lt;br /&gt;
**2 = Arena&lt;br /&gt;
*200 (const GAMESTATE_CLOCK_MODE) - game speed profile&lt;br /&gt;
**[0, 1, 2] - realtime (technically &amp;lt;10 realtime but you cannot define range in php)&lt;br /&gt;
**values &amp;gt;=10 - turn based (currently 10..21)&lt;br /&gt;
**Note there are two similar values, 9 = realtime &amp;quot;no time limit with friends only&amp;quot; vs. 20 = turn-based &amp;quot;no time limit with friends only&amp;quot;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Example:&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
  &amp;quot;100&amp;quot;: {&lt;br /&gt;
    &amp;quot;name&amp;quot;: &amp;quot;Game Variant&amp;quot;,&lt;br /&gt;
    &amp;quot;values&amp;quot;: {&lt;br /&gt;
      &amp;quot;1&amp;quot;: {&lt;br /&gt;
        &amp;quot;name&amp;quot;: &amp;quot;Learning&amp;quot;,&lt;br /&gt;
        &amp;quot;firstgameonly&amp;quot;: true,&lt;br /&gt;
        &amp;quot;tmdisplay&amp;quot;: &amp;quot;Learning&amp;quot;&lt;br /&gt;
      },&lt;br /&gt;
      &amp;quot;2&amp;quot;: {&lt;br /&gt;
        &amp;quot;name&amp;quot;: &amp;quot;Base&amp;quot;,&lt;br /&gt;
      },&lt;br /&gt;
      &amp;quot;3&amp;quot;: {&lt;br /&gt;
        &amp;quot;name&amp;quot;: &amp;quot;Extended&amp;quot;,&lt;br /&gt;
        &amp;quot;nobeginner&amp;quot;: true,&lt;br /&gt;
        &amp;quot;beta&amp;quot;: true,&lt;br /&gt;
        &amp;quot;tmdisplay&amp;quot;: &amp;quot;Extended&amp;quot;&lt;br /&gt;
      }&lt;br /&gt;
    },&lt;br /&gt;
    &amp;quot;default&amp;quot;: 2&lt;br /&gt;
  },&lt;br /&gt;
  &amp;quot;101&amp;quot;: {&lt;br /&gt;
    &amp;quot;name&amp;quot;: &amp;quot;Draft variant&amp;quot;,&lt;br /&gt;
    &amp;quot;values&amp;quot;: {&lt;br /&gt;
      &amp;quot;1&amp;quot;: {&lt;br /&gt;
        &amp;quot;name&amp;quot;: &amp;quot;No draft&amp;quot;&lt;br /&gt;
      },&lt;br /&gt;
      &amp;quot;2&amp;quot;: {&lt;br /&gt;
        &amp;quot;name&amp;quot;: &amp;quot;Draft&amp;quot;,&lt;br /&gt;
        &amp;quot;tmdisplay&amp;quot;: &amp;quot;Draft&amp;quot;,&lt;br /&gt;
        &amp;quot;premium&amp;quot;: true,&lt;br /&gt;
        &amp;quot;nobeginner&amp;quot;: true&lt;br /&gt;
      }&lt;br /&gt;
    },&lt;br /&gt;
    &amp;quot;displaycondition&amp;quot;: [&lt;br /&gt;
      {&lt;br /&gt;
        &amp;quot;type&amp;quot;: &amp;quot;otheroption&amp;quot;,&lt;br /&gt;
        &amp;quot;id&amp;quot;: 100,&lt;br /&gt;
        &amp;quot;value&amp;quot;: [ 2, 3 ]&lt;br /&gt;
      },&lt;br /&gt;
      {&lt;br /&gt;
        &amp;quot;type&amp;quot;: &amp;quot;otheroption&amp;quot;,&lt;br /&gt;
        &amp;quot;id&amp;quot;: 201,&lt;br /&gt;
        &amp;quot;value&amp;quot;: 1&lt;br /&gt;
      }&lt;br /&gt;
    ],&lt;br /&gt;
    &amp;quot;startcondition&amp;quot;: {&lt;br /&gt;
      &amp;quot;1&amp;quot;: [],&lt;br /&gt;
      &amp;quot;2&amp;quot;: [&lt;br /&gt;
        {&lt;br /&gt;
          &amp;quot;type&amp;quot;: &amp;quot;maxplayers&amp;quot;,&lt;br /&gt;
          &amp;quot;value&amp;quot;: 3,&lt;br /&gt;
          &amp;quot;message&amp;quot;: &amp;quot;Draft option is available for 3 players maximum.&amp;quot;&lt;br /&gt;
        }&lt;br /&gt;
      ]&lt;br /&gt;
    }&lt;br /&gt;
  },&lt;br /&gt;
  &amp;quot;102&amp;quot;: {&lt;br /&gt;
    &amp;quot;name&amp;quot;: &amp;quot;Takeovers&amp;quot;,&lt;br /&gt;
    &amp;quot;values&amp;quot;: {&lt;br /&gt;
      &amp;quot;2&amp;quot;: {&lt;br /&gt;
        &amp;quot;name&amp;quot;: &amp;quot;No takeover&amp;quot;&lt;br /&gt;
      },&lt;br /&gt;
      &amp;quot;1&amp;quot;: {&lt;br /&gt;
        &amp;quot;name&amp;quot;: &amp;quot;Allow takeovers&amp;quot;,&lt;br /&gt;
        &amp;quot;tmdisplay&amp;quot;: &amp;quot;Takeovers&amp;quot;,&lt;br /&gt;
        &amp;quot;premium&amp;quot;: true,&lt;br /&gt;
        &amp;quot;nobeginner&amp;quot;: true&lt;br /&gt;
      }&lt;br /&gt;
    },&lt;br /&gt;
    &amp;quot;displaycondition&amp;quot;: [&lt;br /&gt;
      {&lt;br /&gt;
        &amp;quot;type&amp;quot;: &amp;quot;otheroption&amp;quot;,&lt;br /&gt;
        &amp;quot;id&amp;quot;: 100,&lt;br /&gt;
        &amp;quot;value&amp;quot;: [ 3 ]&lt;br /&gt;
      }&lt;br /&gt;
    ],&lt;br /&gt;
    &amp;quot;startcondition&amp;quot;: {&lt;br /&gt;
      &amp;quot;2&amp;quot;: [],&lt;br /&gt;
      &amp;quot;1&amp;quot;: [&lt;br /&gt;
        {&lt;br /&gt;
          &amp;quot;type&amp;quot;: &amp;quot;maxplayers&amp;quot;,&lt;br /&gt;
          &amp;quot;value&amp;quot;: 2,&lt;br /&gt;
          &amp;quot;message&amp;quot;: &amp;quot;Rebel vs Imperium Takeover Scenario is available for 2 players only.&amp;quot;&lt;br /&gt;
        }&lt;br /&gt;
      ]&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Example of option that condition on ELO off:&#039;&#039;&#039;&lt;br /&gt;
 {&lt;br /&gt;
   &amp;quot;100&amp;quot;: {&lt;br /&gt;
     &amp;quot;name&amp;quot;: &amp;quot;Learning Game (No Research)&amp;quot;,&lt;br /&gt;
     &amp;quot;values&amp;quot;: {&lt;br /&gt;
       &amp;quot;1&amp;quot;: {&lt;br /&gt;
         &amp;quot;name&amp;quot;: &amp;quot;Off&amp;quot;,&lt;br /&gt;
         &amp;quot;tmdisplay&amp;quot;: &amp;quot;&amp;quot;&lt;br /&gt;
       },&lt;br /&gt;
       &amp;quot;2&amp;quot;: {&lt;br /&gt;
         &amp;quot;name&amp;quot;: &amp;quot;On&amp;quot;,&lt;br /&gt;
         &amp;quot;tmdisplay&amp;quot;: &amp;quot;Learning Game&amp;quot;&lt;br /&gt;
       }&lt;br /&gt;
     },&lt;br /&gt;
     &amp;quot;startcondition&amp;quot;: {&lt;br /&gt;
       &amp;quot;2&amp;quot;: {&lt;br /&gt;
         &amp;quot;type&amp;quot;: &amp;quot;otheroption&amp;quot;,&lt;br /&gt;
         &amp;quot;id&amp;quot;: 201,&lt;br /&gt;
         &amp;quot;value&amp;quot;: 1,&lt;br /&gt;
         &amp;quot;message&amp;quot;: &amp;quot;Learning variant available only in friendly mode&amp;quot;&lt;br /&gt;
       }&lt;br /&gt;
     }&lt;br /&gt;
   }&lt;br /&gt;
 }&lt;br /&gt;
&#039;&#039;&#039;Example of condition that is only available for REALTIME game mode:&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;quot;displaycondition&amp;quot;: [&lt;br /&gt;
    { &amp;quot;type&amp;quot;: &amp;quot;otheroption&amp;quot;, &amp;quot;id&amp;quot;: 200, &amp;quot;value&amp;quot;: [0, 1, 2] }&lt;br /&gt;
],&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Example of using condition on your own option:&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
  &amp;quot;102&amp;quot;: {&lt;br /&gt;
    &amp;quot;name&amp;quot;: &amp;quot;Scenarios&amp;quot;,&lt;br /&gt;
    &amp;quot;values&amp;quot;: {&lt;br /&gt;
      &amp;quot;1&amp;quot;: {&lt;br /&gt;
        &amp;quot;name&amp;quot;: &amp;quot;Off&amp;quot;,&lt;br /&gt;
        &amp;quot;nobeginner&amp;quot;: false&lt;br /&gt;
      },&lt;br /&gt;
      &amp;quot;2&amp;quot;: {&lt;br /&gt;
        &amp;quot;name&amp;quot;: &amp;quot;On&amp;quot;,&lt;br /&gt;
        &amp;quot;tmdisplay&amp;quot;: &amp;quot;Scenarios&amp;quot;,&lt;br /&gt;
        &amp;quot;nobeginner&amp;quot;: true&lt;br /&gt;
      }&lt;br /&gt;
    },&lt;br /&gt;
    &amp;quot;displaycondition&amp;quot;: [&lt;br /&gt;
      {&lt;br /&gt;
        &amp;quot;type&amp;quot;: &amp;quot;otheroptionisnot&amp;quot;,&lt;br /&gt;
        &amp;quot;id&amp;quot;: 100,&lt;br /&gt;
        &amp;quot;value&amp;quot;: 1&lt;br /&gt;
      }&lt;br /&gt;
    ],&lt;br /&gt;
    &amp;quot;notdisplayedmessage&amp;quot;: &amp;quot;Scenarios variant is not available if Learning variant is chosen&amp;quot;&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Example of handling solo vs multiplayer options:&#039;&#039;&#039;&amp;lt;pre&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
  &amp;quot;100&amp;quot;: {&lt;br /&gt;
    &amp;quot;name&amp;quot;: &amp;quot;Board setup&amp;quot;,&lt;br /&gt;
    &amp;quot;values&amp;quot;: {&lt;br /&gt;
      &amp;quot;1&amp;quot;: {&lt;br /&gt;
        &amp;quot;name&amp;quot;: &amp;quot;Mirror setup&amp;quot;,&lt;br /&gt;
        &amp;quot;description&amp;quot;: &amp;quot;The starting player shuffles their 6 Farm Cards and randomly lays a card face up in each of the round spaces of their Fruit Island Board. The other players then lay their cards in exactly the same way, copying the order of the starting player.&amp;quot;,&lt;br /&gt;
        &amp;quot;tmdisplay&amp;quot;: &amp;quot;Mirror setup&amp;quot;&lt;br /&gt;
      },&lt;br /&gt;
      &amp;quot;2&amp;quot;: {&lt;br /&gt;
        &amp;quot;name&amp;quot;: &amp;quot;Random setup&amp;quot;,&lt;br /&gt;
        &amp;quot;description&amp;quot;: &amp;quot;Instead of every player copying the same card configuration as the starting player, every player shuffles their Farm Cards and lays down the cards randomly on their Fruit Island Board.&amp;quot;,&lt;br /&gt;
        &amp;quot;tmdisplay&amp;quot;: &amp;quot;Random setup&amp;quot;&lt;br /&gt;
      }&lt;br /&gt;
    },&lt;br /&gt;
    &amp;quot;displaycondition&amp;quot;: [&lt;br /&gt;
      {&lt;br /&gt;
        &amp;quot;type&amp;quot;: &amp;quot;minplayers&amp;quot;,&lt;br /&gt;
        &amp;quot;value&amp;quot;: [&lt;br /&gt;
          2,&lt;br /&gt;
          3,&lt;br /&gt;
          4&lt;br /&gt;
        ]&lt;br /&gt;
      }&lt;br /&gt;
    ]&lt;br /&gt;
  },&lt;br /&gt;
  &amp;quot;102&amp;quot;: {&lt;br /&gt;
    &amp;quot;name&amp;quot;: &amp;quot;Solo difficulty&amp;quot;,&lt;br /&gt;
    &amp;quot;values&amp;quot;: [&lt;br /&gt;
      {&lt;br /&gt;
        &amp;quot;name&amp;quot;: &amp;quot;Banana-apprentice&amp;quot;,&lt;br /&gt;
        &amp;quot;description&amp;quot;: &amp;quot;Do not remove any seed before starting the game.&amp;quot;,&lt;br /&gt;
        &amp;quot;tmdisplay&amp;quot;: &amp;quot;Banana-apprentice&amp;quot;&lt;br /&gt;
      },&lt;br /&gt;
      {&lt;br /&gt;
        &amp;quot;name&amp;quot;: &amp;quot;Pear to the Throne&amp;quot;,&lt;br /&gt;
        &amp;quot;description&amp;quot;: &amp;quot;Remove 1 seed before starting the game.&amp;quot;,&lt;br /&gt;
        &amp;quot;tmdisplay&amp;quot;: &amp;quot;Pear to the Throne&amp;quot;&lt;br /&gt;
      }&lt;br /&gt;
    ],&lt;br /&gt;
    &amp;quot;displaycondition&amp;quot;: [&lt;br /&gt;
      {&lt;br /&gt;
        &amp;quot;type&amp;quot;: &amp;quot;maxplayers&amp;quot;,&lt;br /&gt;
        &amp;quot;value&amp;quot;: 1&lt;br /&gt;
      }&lt;br /&gt;
    ]&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== displaycondition vs startcondition ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;displaycondition&amp;lt;/code&amp;gt; should be used when an option should not be present in the list under certain conditions.&lt;br /&gt;
&lt;br /&gt;
For example, displaying the option which is consistent with the player count.&lt;br /&gt;
&lt;br /&gt;
* 2 player maps: A B C D &lt;br /&gt;
* 3 player maps: E F G H&lt;br /&gt;
* 4 player maps: I J K L&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;startcondition&amp;lt;/code&amp;gt; should be used when a specific combination of option values is invalid, but the option itself still makes sense to show.&lt;br /&gt;
&lt;br /&gt;
For example:&lt;br /&gt;
&lt;br /&gt;
* Player 1 faction: A, B, C, D, E, F, G&lt;br /&gt;
* Player 2 faction: A, B, C, D, E, F, G&lt;br /&gt;
* startcondition: both players can&#039;t be the same faction&lt;br /&gt;
&lt;br /&gt;
These options should both be displayed at all times, but there are some invalid configurations.&lt;br /&gt;
&lt;br /&gt;
The other difference is displaycondition affect option itself, while startcondition affect specific values selected&lt;br /&gt;
&lt;br /&gt;
==== gamestartonly ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;padding: 1em; background: #FFCDD2; color: #B71C1C&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;b&amp;gt;WARNING:&amp;lt;/b&amp;gt; [https://studio.boardgamearena.com/bug?id=104 See studio bug #104]. You should &amp;lt;b&amp;gt;NEVER&amp;lt;/b&amp;gt; use &amp;lt;code&amp;gt;gamestartonly&amp;lt;/code&amp;gt;! Otherwise, you allow players to (unknowingly!) create a turn-based table with impossible options that can never start. Players receive no indication that the option combination they selected is invalid until the last player joins the table (hours or days later) and the game attempts to auto-start. The table won&#039;t start because of the &amp;lt;code&amp;gt;startcondition&amp;lt;/code&amp;gt;, and the table options cannot be changed because it&#039;s a turn-based table, so the table must be abandoned. This is a horrible user experience. Please don&#039;t subject players to this.&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
On the table configuration page, it won&#039;t let you select a combination which is invalid according to &amp;lt;code&amp;gt;startcondition&amp;lt;/code&amp;gt;. Doing so will show a red warning, and will revert the option to the previous value. This means you could end up in a situation where you can&#039;t easily change between certain options (requiring you to set or unset options in a specific order).&lt;br /&gt;
&lt;br /&gt;
The consequence of the &amp;lt;code&amp;gt;gamestartonly&amp;lt;/code&amp;gt; flag is that the player _can_ select an invalid combination. However, when clicking &amp;quot;Start&amp;quot;, an invalid combination will produce an error.&lt;br /&gt;
&lt;br /&gt;
Probably the easiest way to see what the difference is is with an example.&lt;br /&gt;
&lt;br /&gt;
With a _Clans of Caledonia_ table:&lt;br /&gt;
* set to training mode&lt;br /&gt;
* set player count to 1&lt;br /&gt;
* try setting &amp;quot;Clan Auction&amp;quot; to one of the &amp;quot;On&amp;quot; options&lt;br /&gt;
* try starting the game, there&#039;s an error! Ie. &amp;lt;code&amp;gt;&amp;quot;gamestartonly&amp;quot; =&amp;gt; true&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Then, with a _Sushi Go Party!_ table:&lt;br /&gt;
* set number of players to 7&lt;br /&gt;
* try setting &amp;quot;Sushi Go! / Sushi Go Party!&amp;quot; to &amp;quot;Sushi Go!&amp;quot;&lt;br /&gt;
* you can&#039;t set the option! Ie. &amp;lt;code&amp;gt;&amp;quot;gamestartonly&amp;quot; =&amp;gt; false&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In code:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
  &amp;quot;100&amp;quot;: {&lt;br /&gt;
    &amp;quot;name&amp;quot;: &amp;quot;Option name&amp;quot;,&lt;br /&gt;
    &amp;quot;values&amp;quot;: [],&lt;br /&gt;
    &amp;quot;startcondition&amp;quot;: {&lt;br /&gt;
      &amp;quot;1&amp;quot;: [&lt;br /&gt;
        {&lt;br /&gt;
          &amp;quot;type&amp;quot;: &amp;quot;maxplayers&amp;quot;,&lt;br /&gt;
          &amp;quot;value&amp;quot;: 2,&lt;br /&gt;
          &amp;quot;message&amp;quot;: &amp;quot;This option is available for 2 players only.&amp;quot;,&lt;br /&gt;
          &amp;quot;gamestartonly&amp;quot;: true&lt;br /&gt;
        }&lt;br /&gt;
      ]&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== level ====&lt;br /&gt;
Note: at this moment this only have impact in fancy lobby mode, presentation of level or checkboxes are not avaiable via normal table creation ui (such as in studio, or when you click Play button in control panel)&amp;lt;pre&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
    &amp;quot;100&amp;quot;: {&lt;br /&gt;
        &amp;quot;name&amp;quot;: &amp;quot;Option name&amp;quot;,&lt;br /&gt;
        &amp;quot;values&amp;quot;: [...],&lt;br /&gt;
        &amp;quot;level&amp;quot;: &amp;quot;major&amp;quot;&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;base&#039;&#039;&#039; is the default value (you don&#039;t need to specify it).&lt;br /&gt;
* &#039;&#039;&#039;major&#039;&#039;&#039; denotes a major option, which will always be displayed on top, and with a specific UI.&lt;br /&gt;
* &#039;&#039;&#039;additional&#039;&#039;&#039; means this option will not be displayed by default, to unclutter the option panel.&lt;br /&gt;
&lt;br /&gt;
About major options:&lt;br /&gt;
* a game can only have &#039;&#039;&#039;1 major option&#039;&#039;&#039;, and of course, it must be a important game changer.&lt;br /&gt;
* the pictures will default to the standard Game Box, and can be set independently for each value, from the [[Game metadata manager]] (in the &amp;quot;Major Variants&amp;quot; section). Note: this cannot be tested from Studio as there is not studio-only Game metadata manager, to see Major Variants option - the game has to be deployed at least as alpha.&lt;br /&gt;
* the major option can have more than 2 values (there will then be an arrow to slide to the other values, carousel-like)&lt;br /&gt;
* the naming of major variant values should be concise and the values should have descriptive text (not just &amp;quot;enabled&amp;quot; or &amp;quot;disabled&amp;quot;)&lt;br /&gt;
** 👍 Option name &amp;quot;Expansion&amp;quot;, option values &amp;quot;Base game&amp;quot;, &amp;quot;Bigger is Better&amp;quot; =&amp;gt; Displayed as &#039;&#039;&amp;quot;Expansion: Base game&amp;quot;&#039;&#039; or &#039;&#039;&amp;quot;Expansion: Bigger is Better&amp;quot;&#039;&#039;&lt;br /&gt;
** 👎 Option name &amp;quot;Bigger is Better&amp;quot;, option values &amp;quot;Enabled&amp;quot;, &amp;quot;Disabled =&amp;gt; Displayed as &#039;&#039;&amp;quot;Bigger is Better: Enabled&amp;quot;&#039;&#039; or &#039;&#039;&amp;quot;Bigger is Better: Disabled&amp;quot;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
About additional options:&lt;br /&gt;
* please set each option that concerns small details in this category: advanced players will find this option anyway, and it will simplify the interface of the page of your game.&lt;br /&gt;
&lt;br /&gt;
[[File:Option-levels.png|800px|Option levels]]&lt;br /&gt;
&lt;br /&gt;
==== option presentation ====&lt;br /&gt;
&lt;br /&gt;
An option WILL be displayed as a &#039;&#039;&#039;Checkbox&#039;&#039;&#039; instead of a selector if certain conditions are met:&lt;br /&gt;
&lt;br /&gt;
* option has only &#039;&#039;&#039;2 values&#039;&#039;&#039;&lt;br /&gt;
* values are either (case insensitive):&lt;br /&gt;
** &#039;&#039;yes&#039;&#039; and &#039;&#039;no&#039;&#039;&lt;br /&gt;
** &#039;&#039;on&#039;&#039; and &#039;&#039;off&#039;&#039;&lt;br /&gt;
** &#039;&#039;enabled&#039;&#039; and &#039;&#039;disabled&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
The &amp;quot;default&amp;quot; value still has to be specified, and can be &amp;quot;on&amp;quot; or &amp;quot;off&amp;quot; (it&#039;s actually just a difference in display).&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[File:Option-display.png|800px|Example of checkbox display]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== User Preferences ==&lt;br /&gt;
&lt;br /&gt;
User preferences is something cosmetic about the game interface which however can create user wars, so you can satisfy all users&lt;br /&gt;
by giving them individual preferences. You should use this only if it significantly improves the interface for a large proportion of users.&lt;br /&gt;
These preferences appear in the three-line hamburger menu in the top corner of the bga menu (and also at the bottom on the page in the Options tab).  &lt;br /&gt;
&amp;quot;Display game logs&amp;quot; and &amp;quot;Display tooltips&amp;quot; are baked-in by default, but you can extend this list as below. &lt;br /&gt;
&lt;br /&gt;
The preference json slightly resembles options, but these are conceptually different. The numbers comes from diffrent space and do not correspond or conflict with options,&lt;br /&gt;
i.e. preference 100 has nothing to do with option 100. You can use range 100-199 with gaps.&lt;br /&gt;
&lt;br /&gt;
[[File:century_preferences_menu.PNG|400px|The user preferences menu for the game Century]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;&lt;br /&gt;
&#039;&#039;These preferences are a good place to put accessibility options - as Century did for its Colorblind Support.&#039;&#039;&lt;br /&gt;
&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
  &amp;quot;100&amp;quot;: {&lt;br /&gt;
    &amp;quot;name&amp;quot;: &amp;quot;Colorblind Support&amp;quot;,&lt;br /&gt;
    &amp;quot;needReload&amp;quot;: true,&lt;br /&gt;
    &amp;quot;values&amp;quot;: {&lt;br /&gt;
      &amp;quot;1&amp;quot;: {&lt;br /&gt;
        &amp;quot;name&amp;quot;: &amp;quot;None&amp;quot;,&lt;br /&gt;
        &amp;quot;cssPref&amp;quot;: &amp;quot;colorblind_off&amp;quot;&lt;br /&gt;
      },&lt;br /&gt;
      &amp;quot;2&amp;quot;: {&lt;br /&gt;
        &amp;quot;name&amp;quot;: &amp;quot;Numbers&amp;quot;,&lt;br /&gt;
        &amp;quot;cssPref&amp;quot;: &amp;quot;colorblind_on&amp;quot;&lt;br /&gt;
      },&lt;br /&gt;
      &amp;quot;3&amp;quot;: {&lt;br /&gt;
        &amp;quot;name&amp;quot;: &amp;quot;Shapes&amp;quot;,&lt;br /&gt;
        &amp;quot;cssPref&amp;quot;: &amp;quot;colorblind_shapes&amp;quot;&lt;br /&gt;
      }&lt;br /&gt;
    },&lt;br /&gt;
    &amp;quot;default&amp;quot;: 1&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
There is two ways to check/apply this. In java Script&lt;br /&gt;
&lt;br /&gt;
  if (this.getGameUserPreference(100) == 2) ...&lt;br /&gt;
&lt;br /&gt;
This checks if preferences 100 has selected value 2.&lt;br /&gt;
&lt;br /&gt;
Second, if cssPref specified it will be applied to the &#039;&#039;&#039;&amp;lt;html&amp;gt;&#039;&#039;&#039; tag. So you can use different css styling for the preference. Note: you also need to set needReload to true for that class change to be effective.&lt;br /&gt;
&lt;br /&gt;
As user you have to select them from the Gear menu when game is started. On studio only dev0 account will have it actually working (bug?).&lt;br /&gt;
&lt;br /&gt;
The following are the parameters of preferences description array:&lt;br /&gt;
* &#039;&#039;&#039;name&#039;&#039;&#039; - &#039;&#039;&#039;mandatory&#039;&#039;&#039;. The name of the preference. This string is marked for translation.&lt;br /&gt;
* &#039;&#039;&#039;needReload&#039;&#039;&#039; - If set to true, the game interface will auto-reload after a change of the preference.&lt;br /&gt;
* &#039;&#039;&#039;values&#039;&#039;&#039; - &#039;&#039;&#039;mandatory&#039;&#039;&#039;. The map of values with additional parameters per value.&lt;br /&gt;
** &#039;&#039;&#039;name&#039;&#039;&#039; - &#039;&#039;&#039;mandatory&#039;&#039;&#039;. String representation of the numeric value.  This string is marked for translation.&lt;br /&gt;
** &#039;&#039;&#039;cssPref&#039;&#039;&#039; - CSS class to add to the &#039;&#039;&#039;&amp;lt;html&amp;gt;&#039;&#039;&#039; tag. Currently it is added or removed only after a reload (see needReload).&lt;br /&gt;
* &#039;&#039;&#039;default&#039;&#039;&#039; - Indicates the default value to use for this preference (optional, if not present the first value listed is the default).&lt;br /&gt;
&lt;br /&gt;
=== Listening for preference changes and updating preference from code ===&lt;br /&gt;
The BGA framework offers read/write and callback for user preference changes. See [[Game interface logic: yourgamename.js#User preferences]]&lt;br /&gt;
&lt;br /&gt;
=== Accessing User Preferences on the server ===&lt;br /&gt;
PHP has a variable called $this-&amp;gt;player_preferences.&lt;br /&gt;
This contains a table of player preferences, ONLY accessible in setupNewGame().&lt;br /&gt;
You can use this to populate a table that you manage yourself.&lt;br /&gt;
You have to update the table when a player changes preference (and you have to hook up a listener and initiate an AJAX call out-of-turn).&lt;br /&gt;
Check the code of Agricola for details but this should work:&lt;br /&gt;
&lt;br /&gt;
; In dbmodel.sql&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
CREATE TABLE IF NOT EXISTS `user_preferences` (&lt;br /&gt;
  `player_id` int(10) NOT NULL,&lt;br /&gt;
  `pref_id` int(10) NOT NULL,&lt;br /&gt;
  `pref_value` int(10) NOT NULL,&lt;br /&gt;
  PRIMARY KEY (`player_id`, `pref_id`)&lt;br /&gt;
) ENGINE=InnoDB DEFAULT CHARSET=utf8;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
; In ggg.game.php&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
protected function setupNewGame($players, $options = array())&lt;br /&gt;
{&lt;br /&gt;
// TODO: Save $this-&amp;gt;player_preferences: key is player_id, value is array with pref_id as key and pref_value as value&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Warning: &amp;lt;code&amp;gt;$this-&amp;gt;player_preferences[$player_id]&amp;lt;/code&amp;gt; can be null if the player has not set any player preferences.&lt;br /&gt;
&lt;br /&gt;
Note: to access json values you can call:&lt;br /&gt;
   $game_preferences = $this-&amp;gt;getTablePreferences();&lt;br /&gt;
&lt;br /&gt;
Warning: if you use bga undo system make sure this table is not restored from undo state, as this likely independed from it&lt;br /&gt;
&lt;br /&gt;
; In ggg.js&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
// use code for initPreferencesObserver from above example&lt;br /&gt;
&lt;br /&gt;
onGameUserPreferenceChanged(prefId, prefValue) {&lt;br /&gt;
    if (prefId === 101 /*TODO: You probably want to send only some preferences*/) {&lt;br /&gt;
        // TODO: Code your own action in ggg.action.php and send it prefId and prefValue&lt;br /&gt;
        //       The on the server side you can save it all in the user_preferences&lt;br /&gt;
        //       table you created above.&lt;br /&gt;
    }&lt;br /&gt;
},&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Translations ==&lt;br /&gt;
Note that any name or description values in these JSON files are automatically added to the translation system.&lt;br /&gt;
&lt;br /&gt;
== Migration ==&lt;br /&gt;
Previously, options and preferences were specified in a single &amp;lt;code&amp;gt;gameoptions.inc.php&amp;lt;/code&amp;gt; file.&lt;br /&gt;
&lt;br /&gt;
BGA has switched to a JSON format to make parsing easier on the server-side, and to avoid a reliance on PHP for static config.&lt;br /&gt;
&lt;br /&gt;
The PHP format will continue to work for &#039;&#039;existing&#039;&#039; games, and although preferred, there is no need to migrate unless you want to. However, newly created games must use the new format.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note&#039;&#039;&#039;: once a game has been committed with a &amp;lt;code&amp;gt;gameoptions.json&amp;lt;/code&amp;gt; file, however, it is not possible to go back without admin intervention.&lt;br /&gt;
&lt;br /&gt;
If you want to migrate:&lt;br /&gt;
&lt;br /&gt;
Simple method:&lt;br /&gt;
* Go to studio and press Reload game options configuration&lt;br /&gt;
* It will dump json on the log window - you can take this, format it and save into 2 files (if you have both). For gamepreference.json remove option &amp;quot;200&amp;quot; - this is default common option, it should not be in your file.&lt;br /&gt;
&lt;br /&gt;
Manual method:&lt;br /&gt;
* Remove all calls to &amp;lt;code&amp;gt;totranslate()&amp;lt;/code&amp;gt;, and replace with the plain string&lt;br /&gt;
* Remove any references to BGA&#039;s PHP constants, such as GAMESTATE_RATING_MODE, and replace with the plain value (in this case, 201)&lt;br /&gt;
* You can populate &amp;lt;code&amp;gt;gameinfos.json&amp;lt;/code&amp;gt; with the result of &amp;lt;code&amp;gt;json_encode($game_options, JSON_PRETTY_PRINT)&amp;lt;/code&amp;gt;&lt;br /&gt;
* You can populate &amp;lt;code&amp;gt;gamepreferences.json&amp;lt;/code&amp;gt; with the result of &amp;lt;code&amp;gt;json_encode($game_preferences, JSON_PRETTY_PRINT)&amp;lt;/code&amp;gt;&lt;br /&gt;
* If you include gameoptions.inc.php directly, to read the values, then replace those calls with &amp;lt;code&amp;gt;$this-&amp;gt;getTableOptions()&amp;lt;/code&amp;gt; or &amp;lt;code&amp;gt;$this-&amp;gt;getTablePreferences()&amp;lt;/code&amp;gt; as appropriate which return arrays parsed from the JSON files&lt;br /&gt;
This message was posted to the developer Discord channel:&amp;lt;blockquote&amp;gt;&#039;&#039;&#039;Game options change (Optional!)&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;gameoptions.inc.php&amp;lt;/code&amp;gt; is now considered legacy, and &amp;lt;code&amp;gt;gameoptions.json&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;gamepreferences.json&amp;lt;/code&amp;gt; are recommended for new projects:&lt;br /&gt;
&lt;br /&gt;
* The wiki and the template project have been updated: [[/en.doc.boardgamearena.com/Options and preferences: gameoptions.json, gamepreferences.json|https://en.doc.boardgamearena.com/Options_and_preferences:_gameoptions.json,_gamepreferences.json]]&lt;br /&gt;
* Any questions/problems can come to me, or can be asked here.&lt;br /&gt;
* The format of the json files matches the format of the old php files&lt;br /&gt;
&lt;br /&gt;
We realise there are some drawbacks (sorry!):&lt;br /&gt;
&lt;br /&gt;
* No comments in the JSON file, meaning you have to check the wiki for examples&lt;br /&gt;
* No PHP constants in the JSON file, meaning magic numbers&lt;br /&gt;
&lt;br /&gt;
However, we hope it&#039;s good for BGA because:&lt;br /&gt;
&lt;br /&gt;
* Simpler to parse (for robots and humans)&lt;br /&gt;
* Easier to check for errors (we could perhaps use an XSLT one day)&lt;br /&gt;
* No need to run game-specific PHP code on the metasite&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;NOTE&#039;&#039;&#039;: Switching is totally optional, and the legacy files will still work for existing projects, and for those who know about them. &amp;lt;/blockquote&amp;gt;&lt;br /&gt;
[[Category:Studio]]&lt;/div&gt;</summary>
		<author><name>Sguzzer Gunayer</name></author>
	</entry>
	<entry>
		<id>https://en.doc.boardgamearena.com/index.php?title=Options_and_preferences:_gameoptions.json,_gamepreferences.json&amp;diff=22487</id>
		<title>Options and preferences: gameoptions.json, gamepreferences.json</title>
		<link rel="alternate" type="text/html" href="https://en.doc.boardgamearena.com/index.php?title=Options_and_preferences:_gameoptions.json,_gamepreferences.json&amp;diff=22487"/>
		<updated>2024-09-07T09:13:10Z</updated>

		<summary type="html">&lt;p&gt;Sguzzer Gunayer: /* Game Options */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Studio_Framework_Navigation}}&lt;br /&gt;
&lt;br /&gt;
In &amp;lt;code&amp;gt;gameoptions.json&amp;lt;/code&amp;gt;, you can define your game options (i.e. game variants).&lt;br /&gt;
&lt;br /&gt;
In &amp;lt;code&amp;gt;gamepreferences.json&amp;lt;/code&amp;gt;, you can define user preferences.&lt;br /&gt;
   &lt;br /&gt;
Note: If your game has no variants or preferences, you don&#039;t have to modify these files.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;IMPORTANT:&#039;&#039;&#039; after edits to these files, you have to go to the control panel and press &amp;quot;Reload game options configuration&amp;quot; on Studio for your changes &#039;&#039;&#039;to take effect&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
Make sure you understand difference between options and preferences:&lt;br /&gt;
* Game options - something usually in the rule book defined as &amp;quot;variant&amp;quot; (except for player count, which is automatically handled). For example, whether to include &#039;&#039;The River&#039;&#039; in Carcassonne.&lt;br /&gt;
* User preferences - personal choices of each player only visible to that specific player - i.e. layout, whether or not to prompt for action, whether or not auto-opt in in some actions, etc.&lt;br /&gt;
&lt;br /&gt;
__TOC__&lt;br /&gt;
&lt;br /&gt;
== Game Options ==&lt;br /&gt;
&lt;br /&gt;
Game options are selected by the table creator and usually correspond to game variants, for example if the game includes expansions or certain special rules.&lt;br /&gt;
&lt;br /&gt;
These variants are defined in &amp;lt;code&amp;gt;gameoptions.json&amp;lt;/code&amp;gt; as an object:  &lt;br /&gt;
&lt;br /&gt;
  {&lt;br /&gt;
     &amp;quot;100&amp;quot;: { &amp;quot;name&amp;quot;: &amp;quot;Game Setup&amp;quot;, ... },&lt;br /&gt;
     &amp;quot;101&amp;quot;: { &amp;quot;name&amp;quot;: &amp;quot;Draft&amp;quot;, ... }&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
Each key corresponds to the option id, and each value is that option definition, which is described below.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note:&#039;&#039;&#039; the file must be valid [https://www.json.org/ JSON]. That is, trailing commas and comments are not allowed. However you can use still standard json hack to add a field like &amp;quot;$comment&amp;quot;: &amp;quot;Here we go&amp;quot;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note 2:&#039;&#039;&#039; the key in json file must be a string type, even its correspond to a number in other places (such as php, or other references in same json).&lt;br /&gt;
&lt;br /&gt;
All options defined in this file should have a corresponding &amp;quot;game state label&amp;quot; with the same ID (see &amp;quot;initGameStateLabels&amp;quot; in yourgame.game.php)&lt;br /&gt;
&lt;br /&gt;
             self::initGameStateLabels ([&lt;br /&gt;
                        ...&lt;br /&gt;
                        &amp;quot;my_game_variant&amp;quot; =&amp;gt; 100,&lt;br /&gt;
              ]);&lt;br /&gt;
&lt;br /&gt;
Numbers have to be exactly from 100 to 199 (there can be gaps).&lt;br /&gt;
&lt;br /&gt;
That is how you access them during runtime (by name):&lt;br /&gt;
&lt;br /&gt;
    public function isSecondVariant() {&lt;br /&gt;
        return $this-&amp;gt;getGameStateValue(&#039;my_game_variant&#039;) == 2;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
Or this (by numberic id)&lt;br /&gt;
    $this-&amp;gt;gamestate-&amp;gt;table_globals[100]&lt;br /&gt;
To access json data (the metadata only) can use&lt;br /&gt;
   $game_options = $this-&amp;gt;getTableOptions();&lt;br /&gt;
=== Details of game options format ===&lt;br /&gt;
&lt;br /&gt;
The following are the values of the option definition object:&lt;br /&gt;
* &#039;&#039;&#039;name&#039;&#039;&#039; - &#039;&#039;&#039;mandatory&#039;&#039;&#039;. The name of the option visible for table creator. This is automatically marked for translation.&lt;br /&gt;
* &#039;&#039;&#039;values&#039;&#039;&#039; - &#039;&#039;&#039;mandatory&#039;&#039;&#039;. The map representing possible values of this option. The key of the map is possible value of this option, its a number but has to be string in json. The value is an object descring it.&lt;br /&gt;
** &#039;&#039;&#039;name&#039;&#039;&#039; - &#039;&#039;&#039;mandatory&#039;&#039;&#039;. String representation of the numeric value visible to table creator. This is automatically marked for translation.&lt;br /&gt;
** &#039;&#039;&#039;description&#039;&#039;&#039; - String description of this value to use when the name of the option is not self-explanatory. Displayed at the table under the option when this value is selected. Note: if there is no description, this should be omitted.&lt;br /&gt;
** &#039;&#039;&#039;tmdisplay&#039;&#039;&#039; - String representation of the option visible in the table description in the lobby. Usually if a variant values are On and Off (default), the tmdisplay would be same as description name when On, and nothing (empty string) when Off. (&#039;&#039;&#039;Warning&#039;&#039;&#039;: due to some caching, a change in tmdisplay may not be effective immediately in the studio, even after forcing a reload of options.) &#039;&#039;&#039;Pro Tip:&#039;&#039;&#039; You can use this as a pre-game communication by adding fake options that just do nothing in the game but make it easier to find other player wanted the same game configuration (see the crew deep sea for example).&lt;br /&gt;
** &#039;&#039;&#039;nobeginner&#039;&#039;&#039; - Set to true if not recommended for beginners&lt;br /&gt;
** &#039;&#039;&#039;firstgameonly&#039;&#039;&#039; - Set to true if this option is recommended only for the first game (discovery option)&lt;br /&gt;
** &#039;&#039;&#039;beta&#039;&#039;&#039; - Set to true to indicate that this option is in &amp;quot;beta&amp;quot; development stage (there will be a warning for players starting the game)&lt;br /&gt;
** &#039;&#039;&#039;alpha&#039;&#039;&#039; - Set to true to indicate that this option is in &amp;quot;alpha&amp;quot; development stage (there will be a warning, and starting the game will be allowed only in training mode except for the developer)&lt;br /&gt;
** &#039;&#039;&#039;premium&#039;&#039;&#039; - Option can be only used by premium members&lt;br /&gt;
* &#039;&#039;&#039;default&#039;&#039;&#039; - indicates the default value to use for this option (optional, if not present the first value listed is the default)&lt;br /&gt;
* &#039;&#039;&#039;displaycondition&#039;&#039;&#039; - (array of conditions) - checks the conditions before displaying the option for selection. All (or any) conditions must be true for the option to be displayed. All or any depends on value of displayconditionoperand&lt;br /&gt;
Supported display condition types:&lt;br /&gt;
** &#039;&#039;minplayers&#039;&#039; condition ensures at least this many players (Note: if your game works with a disjoint interval of player counts, you can supply an array of valid counts instead of a single value)&lt;br /&gt;
** &#039;&#039;maxplayers&#039;&#039; condition ensures at most this many players&lt;br /&gt;
** &#039;&#039;otheroption&#039;&#039; condition ensures another option is set to given values. &lt;br /&gt;
** &#039;&#039;otheroptionisnot&#039;&#039; condition ensure another option is NOT set to this given values&lt;br /&gt;
* &#039;&#039;&#039;displayconditionoperand&#039;&#039;&#039; - can be &#039;and&#039; (this is the default) or &#039;or&#039;. Allows to change the behaviour to display the option if one of the conditions is true instead of all of them.&lt;br /&gt;
* &#039;&#039;&#039;startcondition&#039;&#039;&#039; - (map from value to conditions array) - checks the conditions (on options VALUES) before starting the game. All conditions must be true for the game to start, otherwise players will get a red error message when attempting to begin the game. &lt;br /&gt;
Supported start condition types:&lt;br /&gt;
** &#039;&#039;minplayers&#039;&#039; condition ensures at least this many players (an array of values is not supported here)&lt;br /&gt;
** &#039;&#039;maxplayers&#039;&#039; condition ensures at most this many players&lt;br /&gt;
** &#039;&#039;otheroption&#039;&#039; conditions ensure another option is set to this given values. That works the same as in &#039;&#039;&#039;displaycondition&#039;&#039;&#039;.&lt;br /&gt;
** &#039;&#039;otheroptionisnot&#039;&#039; conditions ensure another option is NOT set to this given value.  That works the same as in &#039;&#039;&#039;displaycondition&#039;&#039;&#039;.&lt;br /&gt;
*: For all these condition types, a &#039;&#039;gamestartonly&#039;&#039; boolean option can be added, if you have options that are exclusive. Setting this boolean to &#039;&#039;true&#039;&#039; will defer the evaluation of the startcondition to the game creation, instead of preventing the player to select options that are exclusive at all. See [[#gamestartonly|below]] for an example. &amp;lt;span style=&amp;quot;background: #FFCDD2; color: #B71C1C; padding: 2px;&amp;quot;&amp;gt;But this should never be used -- see the warning below&amp;lt;/span&amp;gt;&lt;br /&gt;
* &#039;&#039;&#039;notdisplayedmessage&#039;&#039;&#039; - if option is not suppose to be visible because of displaycondition but this is set, the text will be visible instead of combo drop down&lt;br /&gt;
* &#039;&#039;&#039;level&#039;&#039;&#039; - what kind of option it is: &#039;&#039;base&#039;&#039;, &#039;&#039;major&#039;&#039;, or &#039;&#039;additional&#039;&#039;. See [[#level|below]] for more informations.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Common (reserved) options for all tables (reserved range 200-299):&lt;br /&gt;
*201 (const GAMESTATE_RATING_MODE) - ELO OFF (aka Training mode), &lt;br /&gt;
**0 = Normal&lt;br /&gt;
**1 = Training&lt;br /&gt;
**2 = Arena&lt;br /&gt;
*200 (const GAMESTATE_CLOCK_MODE) - game speed profile&lt;br /&gt;
**[0, 1, 2] - realtime (technically &amp;lt;10 realtime but you cannot define range in php)&lt;br /&gt;
**values &amp;gt;=10 - turn based (currently 10..21)&lt;br /&gt;
**Note there are two similar values, 9 = realtime &amp;quot;no time limit with friends only&amp;quot; vs. 20 = turn-based &amp;quot;no time limit with friends only&amp;quot;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Example:&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
  &amp;quot;100&amp;quot;: {&lt;br /&gt;
    &amp;quot;name&amp;quot;: &amp;quot;Game Variant&amp;quot;,&lt;br /&gt;
    &amp;quot;values&amp;quot;: {&lt;br /&gt;
      &amp;quot;1&amp;quot;: {&lt;br /&gt;
        &amp;quot;name&amp;quot;: &amp;quot;Learning&amp;quot;,&lt;br /&gt;
        &amp;quot;firstgameonly&amp;quot;: true,&lt;br /&gt;
        &amp;quot;tmdisplay&amp;quot;: &amp;quot;Learning&amp;quot;&lt;br /&gt;
      },&lt;br /&gt;
      &amp;quot;2&amp;quot;: {&lt;br /&gt;
        &amp;quot;name&amp;quot;: &amp;quot;Base&amp;quot;,&lt;br /&gt;
      },&lt;br /&gt;
      &amp;quot;3&amp;quot;: {&lt;br /&gt;
        &amp;quot;name&amp;quot;: &amp;quot;Extended&amp;quot;,&lt;br /&gt;
        &amp;quot;nobeginner&amp;quot;: true,&lt;br /&gt;
        &amp;quot;beta&amp;quot;: true,&lt;br /&gt;
        &amp;quot;tmdisplay&amp;quot;: &amp;quot;Extended&amp;quot;&lt;br /&gt;
      }&lt;br /&gt;
    },&lt;br /&gt;
    &amp;quot;default&amp;quot;: 2&lt;br /&gt;
  },&lt;br /&gt;
  &amp;quot;101&amp;quot;: {&lt;br /&gt;
    &amp;quot;name&amp;quot;: &amp;quot;Draft variant&amp;quot;,&lt;br /&gt;
    &amp;quot;values&amp;quot;: {&lt;br /&gt;
      &amp;quot;1&amp;quot;: {&lt;br /&gt;
        &amp;quot;name&amp;quot;: &amp;quot;No draft&amp;quot;&lt;br /&gt;
      },&lt;br /&gt;
      &amp;quot;2&amp;quot;: {&lt;br /&gt;
        &amp;quot;name&amp;quot;: &amp;quot;Draft&amp;quot;,&lt;br /&gt;
        &amp;quot;tmdisplay&amp;quot;: &amp;quot;Draft&amp;quot;,&lt;br /&gt;
        &amp;quot;premium&amp;quot;: true,&lt;br /&gt;
        &amp;quot;nobeginner&amp;quot;: true&lt;br /&gt;
      }&lt;br /&gt;
    },&lt;br /&gt;
    &amp;quot;displaycondition&amp;quot;: [&lt;br /&gt;
      {&lt;br /&gt;
        &amp;quot;type&amp;quot;: &amp;quot;otheroption&amp;quot;,&lt;br /&gt;
        &amp;quot;id&amp;quot;: 100,&lt;br /&gt;
        &amp;quot;value&amp;quot;: [ 2, 3 ]&lt;br /&gt;
      },&lt;br /&gt;
      {&lt;br /&gt;
        &amp;quot;type&amp;quot;: &amp;quot;otheroption&amp;quot;,&lt;br /&gt;
        &amp;quot;id&amp;quot;: 201,&lt;br /&gt;
        &amp;quot;value&amp;quot;: 1&lt;br /&gt;
      }&lt;br /&gt;
    ],&lt;br /&gt;
    &amp;quot;startcondition&amp;quot;: {&lt;br /&gt;
      &amp;quot;1&amp;quot;: [],&lt;br /&gt;
      &amp;quot;2&amp;quot;: [&lt;br /&gt;
        {&lt;br /&gt;
          &amp;quot;type&amp;quot;: &amp;quot;maxplayers&amp;quot;,&lt;br /&gt;
          &amp;quot;value&amp;quot;: 3,&lt;br /&gt;
          &amp;quot;message&amp;quot;: &amp;quot;Draft option is available for 3 players maximum.&amp;quot;&lt;br /&gt;
        }&lt;br /&gt;
      ]&lt;br /&gt;
    }&lt;br /&gt;
  },&lt;br /&gt;
  &amp;quot;102&amp;quot;: {&lt;br /&gt;
    &amp;quot;name&amp;quot;: &amp;quot;Takeovers&amp;quot;,&lt;br /&gt;
    &amp;quot;values&amp;quot;: {&lt;br /&gt;
      &amp;quot;2&amp;quot;: {&lt;br /&gt;
        &amp;quot;name&amp;quot;: &amp;quot;No takeover&amp;quot;&lt;br /&gt;
      },&lt;br /&gt;
      &amp;quot;1&amp;quot;: {&lt;br /&gt;
        &amp;quot;name&amp;quot;: &amp;quot;Allow takeovers&amp;quot;,&lt;br /&gt;
        &amp;quot;tmdisplay&amp;quot;: &amp;quot;Takeovers&amp;quot;,&lt;br /&gt;
        &amp;quot;premium&amp;quot;: true,&lt;br /&gt;
        &amp;quot;nobeginner&amp;quot;: true&lt;br /&gt;
      }&lt;br /&gt;
    },&lt;br /&gt;
    &amp;quot;displaycondition&amp;quot;: [&lt;br /&gt;
      {&lt;br /&gt;
        &amp;quot;type&amp;quot;: &amp;quot;otheroption&amp;quot;,&lt;br /&gt;
        &amp;quot;id&amp;quot;: 100,&lt;br /&gt;
        &amp;quot;value&amp;quot;: [ 3 ]&lt;br /&gt;
      }&lt;br /&gt;
    ],&lt;br /&gt;
    &amp;quot;startcondition&amp;quot;: {&lt;br /&gt;
      &amp;quot;2&amp;quot;: [],&lt;br /&gt;
      &amp;quot;1&amp;quot;: [&lt;br /&gt;
        {&lt;br /&gt;
          &amp;quot;type&amp;quot;: &amp;quot;maxplayers&amp;quot;,&lt;br /&gt;
          &amp;quot;value&amp;quot;: 2,&lt;br /&gt;
          &amp;quot;message&amp;quot;: &amp;quot;Rebel vs Imperium Takeover Scenario is available for 2 players only.&amp;quot;&lt;br /&gt;
        }&lt;br /&gt;
      ]&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Example of option that condition on ELO off:&#039;&#039;&#039;&lt;br /&gt;
 {&lt;br /&gt;
   &amp;quot;100&amp;quot;: {&lt;br /&gt;
     &amp;quot;name&amp;quot;: &amp;quot;Learning Game (No Research)&amp;quot;,&lt;br /&gt;
     &amp;quot;values&amp;quot;: {&lt;br /&gt;
       &amp;quot;1&amp;quot;: {&lt;br /&gt;
         &amp;quot;name&amp;quot;: &amp;quot;Off&amp;quot;,&lt;br /&gt;
         &amp;quot;tmdisplay&amp;quot;: &amp;quot;&amp;quot;&lt;br /&gt;
       },&lt;br /&gt;
       &amp;quot;2&amp;quot;: {&lt;br /&gt;
         &amp;quot;name&amp;quot;: &amp;quot;On&amp;quot;,&lt;br /&gt;
         &amp;quot;tmdisplay&amp;quot;: &amp;quot;Learning Game&amp;quot;&lt;br /&gt;
       }&lt;br /&gt;
     },&lt;br /&gt;
     &amp;quot;startcondition&amp;quot;: {&lt;br /&gt;
       &amp;quot;2&amp;quot;: {&lt;br /&gt;
         &amp;quot;type&amp;quot;: &amp;quot;otheroption&amp;quot;,&lt;br /&gt;
         &amp;quot;id&amp;quot;: 201,&lt;br /&gt;
         &amp;quot;value&amp;quot;: 1,&lt;br /&gt;
         &amp;quot;message&amp;quot;: &amp;quot;Learning variant available only in friendly mode&amp;quot;&lt;br /&gt;
       }&lt;br /&gt;
     }&lt;br /&gt;
   }&lt;br /&gt;
 }&lt;br /&gt;
&#039;&#039;&#039;Example of condition that is only available for REALTIME game mode:&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;quot;displaycondition&amp;quot;: [&lt;br /&gt;
    { &amp;quot;type&amp;quot;: &amp;quot;otheroption&amp;quot;, &amp;quot;id&amp;quot;: 200, &amp;quot;value&amp;quot;: [0, 1, 2] }&lt;br /&gt;
],&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Example of using condition on your own option:&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
  &amp;quot;102&amp;quot;: {&lt;br /&gt;
    &amp;quot;name&amp;quot;: &amp;quot;Scenarios&amp;quot;,&lt;br /&gt;
    &amp;quot;values&amp;quot;: {&lt;br /&gt;
      &amp;quot;1&amp;quot;: {&lt;br /&gt;
        &amp;quot;name&amp;quot;: &amp;quot;Off&amp;quot;,&lt;br /&gt;
        &amp;quot;nobeginner&amp;quot;: false&lt;br /&gt;
      },&lt;br /&gt;
      &amp;quot;2&amp;quot;: {&lt;br /&gt;
        &amp;quot;name&amp;quot;: &amp;quot;On&amp;quot;,&lt;br /&gt;
        &amp;quot;tmdisplay&amp;quot;: &amp;quot;Scenarios&amp;quot;,&lt;br /&gt;
        &amp;quot;nobeginner&amp;quot;: true&lt;br /&gt;
      }&lt;br /&gt;
    },&lt;br /&gt;
    &amp;quot;displaycondition&amp;quot;: [&lt;br /&gt;
      {&lt;br /&gt;
        &amp;quot;type&amp;quot;: &amp;quot;otheroptionisnot&amp;quot;,&lt;br /&gt;
        &amp;quot;id&amp;quot;: 100,&lt;br /&gt;
        &amp;quot;value&amp;quot;: 1&lt;br /&gt;
      }&lt;br /&gt;
    ],&lt;br /&gt;
    &amp;quot;notdisplayedmessage&amp;quot;: &amp;quot;Scenarios variant is not available if Learning variant is chosen&amp;quot;&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Example of handling solo vs multiplayer options:&#039;&#039;&#039;&amp;lt;pre&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
  &amp;quot;100&amp;quot;: {&lt;br /&gt;
    &amp;quot;name&amp;quot;: &amp;quot;Board setup&amp;quot;,&lt;br /&gt;
    &amp;quot;values&amp;quot;: {&lt;br /&gt;
      &amp;quot;1&amp;quot;: {&lt;br /&gt;
        &amp;quot;name&amp;quot;: &amp;quot;Mirror setup&amp;quot;,&lt;br /&gt;
        &amp;quot;description&amp;quot;: &amp;quot;The starting player shuffles their 6 Farm Cards and randomly lays a card face up in each of the round spaces of their Fruit Island Board. The other players then lay their cards in exactly the same way, copying the order of the starting player.&amp;quot;,&lt;br /&gt;
        &amp;quot;tmdisplay&amp;quot;: &amp;quot;Mirror setup&amp;quot;&lt;br /&gt;
      },&lt;br /&gt;
      &amp;quot;2&amp;quot;: {&lt;br /&gt;
        &amp;quot;name&amp;quot;: &amp;quot;Random setup&amp;quot;,&lt;br /&gt;
        &amp;quot;description&amp;quot;: &amp;quot;Instead of every player copying the same card configuration as the starting player, every player shuffles their Farm Cards and lays down the cards randomly on their Fruit Island Board.&amp;quot;,&lt;br /&gt;
        &amp;quot;tmdisplay&amp;quot;: &amp;quot;Random setup&amp;quot;&lt;br /&gt;
      }&lt;br /&gt;
    },&lt;br /&gt;
    &amp;quot;displaycondition&amp;quot;: [&lt;br /&gt;
      {&lt;br /&gt;
        &amp;quot;type&amp;quot;: &amp;quot;minplayers&amp;quot;,&lt;br /&gt;
        &amp;quot;value&amp;quot;: [&lt;br /&gt;
          2,&lt;br /&gt;
          3,&lt;br /&gt;
          4&lt;br /&gt;
        ]&lt;br /&gt;
      }&lt;br /&gt;
    ]&lt;br /&gt;
  },&lt;br /&gt;
  &amp;quot;102&amp;quot;: {&lt;br /&gt;
    &amp;quot;name&amp;quot;: &amp;quot;Solo difficulty&amp;quot;,&lt;br /&gt;
    &amp;quot;values&amp;quot;: [&lt;br /&gt;
      {&lt;br /&gt;
        &amp;quot;name&amp;quot;: &amp;quot;Banana-apprentice&amp;quot;,&lt;br /&gt;
        &amp;quot;description&amp;quot;: &amp;quot;Do not remove any seed before starting the game.&amp;quot;,&lt;br /&gt;
        &amp;quot;tmdisplay&amp;quot;: &amp;quot;Banana-apprentice&amp;quot;&lt;br /&gt;
      },&lt;br /&gt;
      {&lt;br /&gt;
        &amp;quot;name&amp;quot;: &amp;quot;Pear to the Throne&amp;quot;,&lt;br /&gt;
        &amp;quot;description&amp;quot;: &amp;quot;Remove 1 seed before starting the game.&amp;quot;,&lt;br /&gt;
        &amp;quot;tmdisplay&amp;quot;: &amp;quot;Pear to the Throne&amp;quot;&lt;br /&gt;
      }&lt;br /&gt;
    ],&lt;br /&gt;
    &amp;quot;displaycondition&amp;quot;: [&lt;br /&gt;
      {&lt;br /&gt;
        &amp;quot;type&amp;quot;: &amp;quot;maxplayers&amp;quot;,&lt;br /&gt;
        &amp;quot;value&amp;quot;: 1&lt;br /&gt;
      }&lt;br /&gt;
    ]&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== displaycondition vs startcondition ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;displaycondition&amp;lt;/code&amp;gt; should be used when an option should not be present in the list under certain conditions.&lt;br /&gt;
&lt;br /&gt;
For example, displaying the option which is consistent with the player count.&lt;br /&gt;
&lt;br /&gt;
* 2 player maps: A B C D &lt;br /&gt;
* 3 player maps: E F G H&lt;br /&gt;
* 4 player maps: I J K L&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;startcondition&amp;lt;/code&amp;gt; should be used when a specific combination of option values is invalid, but the option itself still makes sense to show.&lt;br /&gt;
&lt;br /&gt;
For example:&lt;br /&gt;
&lt;br /&gt;
* Player 1 faction: A, B, C, D, E, F, G&lt;br /&gt;
* Player 2 faction: A, B, C, D, E, F, G&lt;br /&gt;
* startcondition: both players can&#039;t be the same faction&lt;br /&gt;
&lt;br /&gt;
These options should both be displayed at all times, but there are some invalid configurations.&lt;br /&gt;
&lt;br /&gt;
The other difference is displaycondition affect option itself, while startcondition affect specific values selected&lt;br /&gt;
&lt;br /&gt;
==== gamestartonly ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;padding: 1em; background: #FFCDD2; color: #B71C1C&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;b&amp;gt;WARNING:&amp;lt;/b&amp;gt; [https://studio.boardgamearena.com/bug?id=104 See studio bug #104]. You should &amp;lt;b&amp;gt;NEVER&amp;lt;/b&amp;gt; use &amp;lt;code&amp;gt;gamestartonly&amp;lt;/code&amp;gt;! Otherwise, you allow players to (unknowingly!) create a turn-based table with impossible options that can never start. Players receive no indication that the option combination they selected is invalid until the last player joins the table (hours or days later) and the game attempts to auto-start. The table won&#039;t start because of the &amp;lt;code&amp;gt;startcondition&amp;lt;/code&amp;gt;, and the table options cannot be changed because it&#039;s a turn-based table, so the table must be abandoned. This is a horrible user experience. Please don&#039;t subject players to this.&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
On the table configuration page, it won&#039;t let you select a combination which is invalid according to &amp;lt;code&amp;gt;startcondition&amp;lt;/code&amp;gt;. Doing so will show a red warning, and will revert the option to the previous value. This means you could end up in a situation where you can&#039;t easily change between certain options (requiring you to set or unset options in a specific order).&lt;br /&gt;
&lt;br /&gt;
The consequence of the &amp;lt;code&amp;gt;gamestartonly&amp;lt;/code&amp;gt; flag is that the player _can_ select an invalid combination. However, when clicking &amp;quot;Start&amp;quot;, an invalid combination will produce an error.&lt;br /&gt;
&lt;br /&gt;
Probably the easiest way to see what the difference is is with an example.&lt;br /&gt;
&lt;br /&gt;
With a _Clans of Caledonia_ table:&lt;br /&gt;
* set to training mode&lt;br /&gt;
* set player count to 1&lt;br /&gt;
* try setting &amp;quot;Clan Auction&amp;quot; to one of the &amp;quot;On&amp;quot; options&lt;br /&gt;
* try starting the game, there&#039;s an error! Ie. &amp;lt;code&amp;gt;&amp;quot;gamestartonly&amp;quot; =&amp;gt; true&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Then, with a _Sushi Go Party!_ table:&lt;br /&gt;
* set number of players to 7&lt;br /&gt;
* try setting &amp;quot;Sushi Go! / Sushi Go Party!&amp;quot; to &amp;quot;Sushi Go!&amp;quot;&lt;br /&gt;
* you can&#039;t set the option! Ie. &amp;lt;code&amp;gt;&amp;quot;gamestartonly&amp;quot; =&amp;gt; false&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In code:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
  &amp;quot;100&amp;quot;: {&lt;br /&gt;
    &amp;quot;name&amp;quot;: &amp;quot;Option name&amp;quot;,&lt;br /&gt;
    &amp;quot;values&amp;quot;: [],&lt;br /&gt;
    &amp;quot;startcondition&amp;quot;: {&lt;br /&gt;
      &amp;quot;1&amp;quot;: [&lt;br /&gt;
        {&lt;br /&gt;
          &amp;quot;type&amp;quot;: &amp;quot;maxplayers&amp;quot;,&lt;br /&gt;
          &amp;quot;value&amp;quot;: 2,&lt;br /&gt;
          &amp;quot;message&amp;quot;: &amp;quot;This option is available for 2 players only.&amp;quot;,&lt;br /&gt;
          &amp;quot;gamestartonly&amp;quot;: true&lt;br /&gt;
        }&lt;br /&gt;
      ]&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== level ====&lt;br /&gt;
Note: at this moment this only have impact in fancy lobby mode, presentation of level or checkboxes are not avaiable via normal table creation ui (such as in studio, or when you click Play button in control panel)&amp;lt;pre&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
    &amp;quot;100&amp;quot;: {&lt;br /&gt;
        &amp;quot;name&amp;quot;: &amp;quot;Option name&amp;quot;,&lt;br /&gt;
        &amp;quot;values&amp;quot;: [...],&lt;br /&gt;
        &amp;quot;level&amp;quot;: &amp;quot;major&amp;quot;&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;base&#039;&#039;&#039; is the default value (you don&#039;t need to specify it).&lt;br /&gt;
* &#039;&#039;&#039;major&#039;&#039;&#039; denotes a major option, which will always be displayed on top, and with a specific UI.&lt;br /&gt;
* &#039;&#039;&#039;additional&#039;&#039;&#039; means this option will not be displayed by default, to unclutter the option panel.&lt;br /&gt;
&lt;br /&gt;
About major options:&lt;br /&gt;
* a game can only have &#039;&#039;&#039;1 major option&#039;&#039;&#039;, and of course, it must be a important game changer.&lt;br /&gt;
* the pictures will default to the standard Game Box, and can be set independently for each value, from the [[Game metadata manager]] (in the &amp;quot;Major Variants&amp;quot; section). Note: this cannot be tested from Studio as there is not studio-only Game metadata manager, to see Major Variants option - the game has to be deployed at least as alpha.&lt;br /&gt;
* the major option can have more than 2 values (there will then be an arrow to slide to the other values, carousel-like)&lt;br /&gt;
* the naming of major variant values should be concise and the values should have descriptive text (not just &amp;quot;enabled&amp;quot; or &amp;quot;disabled&amp;quot;)&lt;br /&gt;
** 👍 Option name &amp;quot;Expansion&amp;quot;, option values &amp;quot;Base game&amp;quot;, &amp;quot;Bigger is Better&amp;quot; =&amp;gt; Displayed as &#039;&#039;&amp;quot;Expansion: Base game&amp;quot;&#039;&#039; or &#039;&#039;&amp;quot;Expansion: Bigger is Better&amp;quot;&#039;&#039;&lt;br /&gt;
** 👎 Option name &amp;quot;Bigger is Better&amp;quot;, option values &amp;quot;Enabled&amp;quot;, &amp;quot;Disabled =&amp;gt; Displayed as &#039;&#039;&amp;quot;Bigger is Better: Enabled&amp;quot;&#039;&#039; or &#039;&#039;&amp;quot;Bigger is Better: Disabled&amp;quot;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
About additional options:&lt;br /&gt;
* please set each option that concerns small details in this category: advanced players will find this option anyway, and it will simplify the interface of the page of your game.&lt;br /&gt;
&lt;br /&gt;
[[File:Option-levels.png|800px|Option levels]]&lt;br /&gt;
&lt;br /&gt;
==== option presentation ====&lt;br /&gt;
&lt;br /&gt;
An option WILL be displayed as a &#039;&#039;&#039;Checkbox&#039;&#039;&#039; instead of a selector if certain conditions are met:&lt;br /&gt;
&lt;br /&gt;
* option has only &#039;&#039;&#039;2 values&#039;&#039;&#039;&lt;br /&gt;
* values are either (case insensitive):&lt;br /&gt;
** &#039;&#039;yes&#039;&#039; and &#039;&#039;no&#039;&#039;&lt;br /&gt;
** &#039;&#039;on&#039;&#039; and &#039;&#039;off&#039;&#039;&lt;br /&gt;
** &#039;&#039;enabled&#039;&#039; and &#039;&#039;disabled&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
The &amp;quot;default&amp;quot; value still has to be specified, and can be &amp;quot;on&amp;quot; or &amp;quot;off&amp;quot; (it&#039;s actually just a difference in display).&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[File:Option-display.png|800px|Example of checkbox display]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== User Preferences ==&lt;br /&gt;
&lt;br /&gt;
User preferences is something cosmetic about the game interface which however can create user wars, so you can satisfy all users&lt;br /&gt;
by giving them individual preferences. You should use this only if it significantly improves the interface for a large proportion of users.&lt;br /&gt;
These preferences appear in the three-line hamburger menu in the top corner of the bga menu (and also at the bottom on the page in the Options tab).  &lt;br /&gt;
&amp;quot;Display game logs&amp;quot; and &amp;quot;Display tooltips&amp;quot; are baked-in by default, but you can extend this list as below. &lt;br /&gt;
&lt;br /&gt;
The preference json slightly resembles options, but these are conceptually different. The numbers comes from diffrent space and do not correspond or conflict with options,&lt;br /&gt;
i.e. preference 100 has nothing to do with option 100. You can use range 100-199 with gaps.&lt;br /&gt;
&lt;br /&gt;
[[File:century_preferences_menu.PNG|400px|The user preferences menu for the game Century]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;&lt;br /&gt;
&#039;&#039;These preferences are a good place to put accessibility options - as Century did for its Colorblind Support.&#039;&#039;&lt;br /&gt;
&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
  &amp;quot;100&amp;quot;: {&lt;br /&gt;
    &amp;quot;name&amp;quot;: &amp;quot;Colorblind Support&amp;quot;,&lt;br /&gt;
    &amp;quot;needReload&amp;quot;: true,&lt;br /&gt;
    &amp;quot;values&amp;quot;: {&lt;br /&gt;
      &amp;quot;1&amp;quot;: {&lt;br /&gt;
        &amp;quot;name&amp;quot;: &amp;quot;None&amp;quot;,&lt;br /&gt;
        &amp;quot;cssPref&amp;quot;: &amp;quot;colorblind_off&amp;quot;&lt;br /&gt;
      },&lt;br /&gt;
      &amp;quot;2&amp;quot;: {&lt;br /&gt;
        &amp;quot;name&amp;quot;: &amp;quot;Numbers&amp;quot;,&lt;br /&gt;
        &amp;quot;cssPref&amp;quot;: &amp;quot;colorblind_on&amp;quot;&lt;br /&gt;
      },&lt;br /&gt;
      &amp;quot;3&amp;quot;: {&lt;br /&gt;
        &amp;quot;name&amp;quot;: &amp;quot;Shapes&amp;quot;,&lt;br /&gt;
        &amp;quot;cssPref&amp;quot;: &amp;quot;colorblind_shapes&amp;quot;&lt;br /&gt;
      }&lt;br /&gt;
    },&lt;br /&gt;
    &amp;quot;default&amp;quot;: 1&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
There is two ways to check/apply this. In java Script&lt;br /&gt;
&lt;br /&gt;
  if (this.getGameUserPreference(100) == 2) ...&lt;br /&gt;
&lt;br /&gt;
This checks if preferences 100 has selected value 2.&lt;br /&gt;
&lt;br /&gt;
Second, if cssPref specified it will be applied to the &#039;&#039;&#039;&amp;lt;html&amp;gt;&#039;&#039;&#039; tag. So you can use different css styling for the preference. Note: you also need to set needReload to true for that class change to be effective.&lt;br /&gt;
&lt;br /&gt;
As user you have to select them from the Gear menu when game is started. On studio only dev0 account will have it actually working (bug?).&lt;br /&gt;
&lt;br /&gt;
The following are the parameters of preferences description array:&lt;br /&gt;
* &#039;&#039;&#039;name&#039;&#039;&#039; - &#039;&#039;&#039;mandatory&#039;&#039;&#039;. The name of the preference. This string is marked for translation.&lt;br /&gt;
* &#039;&#039;&#039;needReload&#039;&#039;&#039; - If set to true, the game interface will auto-reload after a change of the preference.&lt;br /&gt;
* &#039;&#039;&#039;values&#039;&#039;&#039; - &#039;&#039;&#039;mandatory&#039;&#039;&#039;. The map of values with additional parameters per value.&lt;br /&gt;
** &#039;&#039;&#039;name&#039;&#039;&#039; - &#039;&#039;&#039;mandatory&#039;&#039;&#039;. String representation of the numeric value.  This string is marked for translation.&lt;br /&gt;
** &#039;&#039;&#039;cssPref&#039;&#039;&#039; - CSS class to add to the &#039;&#039;&#039;&amp;lt;html&amp;gt;&#039;&#039;&#039; tag. Currently it is added or removed only after a reload (see needReload).&lt;br /&gt;
* &#039;&#039;&#039;default&#039;&#039;&#039; - Indicates the default value to use for this preference (optional, if not present the first value listed is the default).&lt;br /&gt;
&lt;br /&gt;
=== Listening for preference changes and updating preference from code ===&lt;br /&gt;
The BGA framework offers read/write and callback for user preference changes. See [[Game interface logic: yourgamename.js#User preferences]]&lt;br /&gt;
&lt;br /&gt;
=== Accessing User Preferences on the server ===&lt;br /&gt;
PHP has a variable called $this-&amp;gt;player_preferences.&lt;br /&gt;
This contains a table of player preferences, ONLY accessible in setupNewGame().&lt;br /&gt;
You can use this to populate a table that you manage yourself.&lt;br /&gt;
You have to update the table when a player changes preference (and you have to hook up a listener and initiate an AJAX call out-of-turn).&lt;br /&gt;
Check the code of Agricola for details but this should work:&lt;br /&gt;
&lt;br /&gt;
; In dbmodel.sql&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
CREATE TABLE IF NOT EXISTS `user_preferences` (&lt;br /&gt;
  `player_id` int(10) NOT NULL,&lt;br /&gt;
  `pref_id` int(10) NOT NULL,&lt;br /&gt;
  `pref_value` int(10) NOT NULL,&lt;br /&gt;
  PRIMARY KEY (`player_id`, `pref_id`)&lt;br /&gt;
) ENGINE=InnoDB DEFAULT CHARSET=utf8;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
; In ggg.game.php&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
protected function setupNewGame($players, $options = array())&lt;br /&gt;
{&lt;br /&gt;
// TODO: Save $this-&amp;gt;player_preferences: key is player_id, value is array with pref_id as key and pref_value as value&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Warning: &amp;lt;code&amp;gt;$this-&amp;gt;player_preferences[$player_id]&amp;lt;/code&amp;gt; can be null if the player has not set any player preferences.&lt;br /&gt;
&lt;br /&gt;
Note: to access json values you can call:&lt;br /&gt;
   $game_preferences = $this-&amp;gt;getTablePreferences();&lt;br /&gt;
&lt;br /&gt;
Warning: if you use bga undo system make sure this table is not restored from undo state, as this likely independed from it&lt;br /&gt;
&lt;br /&gt;
; In ggg.js&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
// use code for initPreferencesObserver from above example&lt;br /&gt;
&lt;br /&gt;
onGameUserPreferenceChanged(prefId, prefValue) {&lt;br /&gt;
    if (prefId === 101 /*TODO: You probably want to send only some preferences*/) {&lt;br /&gt;
        // TODO: Code your own action in ggg.action.php and send it prefId and prefValue&lt;br /&gt;
        //       The on the server side you can save it all in the user_preferences&lt;br /&gt;
        //       table you created above.&lt;br /&gt;
    }&lt;br /&gt;
},&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Translations ==&lt;br /&gt;
Note that any name or description values in these JSON files are automatically added to the translation system.&lt;br /&gt;
&lt;br /&gt;
== Migration ==&lt;br /&gt;
Previously, options and preferences were specified in a single &amp;lt;code&amp;gt;gameoptions.inc.php&amp;lt;/code&amp;gt; file.&lt;br /&gt;
&lt;br /&gt;
BGA has switched to a JSON format to make parsing easier on the server-side, and to avoid a reliance on PHP for static config.&lt;br /&gt;
&lt;br /&gt;
The PHP format will continue to work for &#039;&#039;existing&#039;&#039; games, and although preferred, there is no need to migrate unless you want to. However, newly created games must use the new format.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note&#039;&#039;&#039;: once a game has been committed with a &amp;lt;code&amp;gt;gameoptions.json&amp;lt;/code&amp;gt; file, however, it is not possible to go back without admin intervention.&lt;br /&gt;
&lt;br /&gt;
If you want to migrate:&lt;br /&gt;
&lt;br /&gt;
Simple method:&lt;br /&gt;
* Go to studio and press Reload game options configuration&lt;br /&gt;
* It will dump json on the log window - you can take this, format it and save into 2 files (if you have both). For gamepreference.json remove option &amp;quot;200&amp;quot; - this is default common option, it should not be in your file.&lt;br /&gt;
&lt;br /&gt;
Manual method:&lt;br /&gt;
* Remove all calls to &amp;lt;code&amp;gt;totranslate()&amp;lt;/code&amp;gt;, and replace with the plain string&lt;br /&gt;
* Remove any references to BGA&#039;s PHP constants, such as GAMESTATE_RATING_MODE, and replace with the plain value (in this case, 201)&lt;br /&gt;
* You can populate &amp;lt;code&amp;gt;gameinfos.json&amp;lt;/code&amp;gt; with the result of &amp;lt;code&amp;gt;json_encode($game_options, JSON_PRETTY_PRINT)&amp;lt;/code&amp;gt;&lt;br /&gt;
* You can populate &amp;lt;code&amp;gt;gamepreferences.json&amp;lt;/code&amp;gt; with the result of &amp;lt;code&amp;gt;json_encode($game_preferences, JSON_PRETTY_PRINT)&amp;lt;/code&amp;gt;&lt;br /&gt;
* If you include gameoptions.inc.php directly, to read the values, then replace those calls with &amp;lt;code&amp;gt;$this-&amp;gt;getTableOptions()&amp;lt;/code&amp;gt; or &amp;lt;code&amp;gt;$this-&amp;gt;getTablePreferences()&amp;lt;/code&amp;gt; as appropriate which return arrays parsed from the JSON files&lt;br /&gt;
This message was posted to the developer Discord channel:&amp;lt;blockquote&amp;gt;&#039;&#039;&#039;Game options change (Optional!)&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;gameoptions.inc.php&amp;lt;/code&amp;gt; is now considered legacy, and &amp;lt;code&amp;gt;gameoptions.json&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;gamepreferences.json&amp;lt;/code&amp;gt; are recommended for new projects:&lt;br /&gt;
&lt;br /&gt;
* The wiki and the template project have been updated: [[/en.doc.boardgamearena.com/Options and preferences: gameoptions.json, gamepreferences.json|https://en.doc.boardgamearena.com/Options_and_preferences:_gameoptions.json,_gamepreferences.json]]&lt;br /&gt;
* Any questions/problems can come to me, or can be asked here.&lt;br /&gt;
* The format of the json files matches the format of the old php files&lt;br /&gt;
&lt;br /&gt;
We realise there are some drawbacks (sorry!):&lt;br /&gt;
&lt;br /&gt;
* No comments in the JSON file, meaning you have to check the wiki for examples&lt;br /&gt;
* No PHP constants in the JSON file, meaning magic numbers&lt;br /&gt;
&lt;br /&gt;
However, we hope it&#039;s good for BGA because:&lt;br /&gt;
&lt;br /&gt;
* Simpler to parse (for robots and humans)&lt;br /&gt;
* Easier to check for errors (we could perhaps use an XSLT one day)&lt;br /&gt;
* No need to run game-specific PHP code on the metasite&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;NOTE&#039;&#039;&#039;: Switching is totally optional, and the legacy files will still work for existing projects, and for those who know about them. &amp;lt;/blockquote&amp;gt;&lt;br /&gt;
[[Category:Studio]]&lt;/div&gt;</summary>
		<author><name>Sguzzer Gunayer</name></author>
	</entry>
	<entry>
		<id>https://en.doc.boardgamearena.com/index.php?title=Game_meta-information:_gameinfos.jsonc&amp;diff=22486</id>
		<title>Game meta-information: gameinfos.jsonc</title>
		<link rel="alternate" type="text/html" href="https://en.doc.boardgamearena.com/index.php?title=Game_meta-information:_gameinfos.jsonc&amp;diff=22486"/>
		<updated>2024-09-07T08:46:17Z</updated>

		<summary type="html">&lt;p&gt;Sguzzer Gunayer: /* Beta */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Studio_Framework_Navigation}}&lt;br /&gt;
&lt;br /&gt;
__TOC__&lt;br /&gt;
&lt;br /&gt;
== Overview ==&lt;br /&gt;
&lt;br /&gt;
From this file, you can edit the various meta-information of your game.&lt;br /&gt;
&lt;br /&gt;
After modifying the file, don&#039;t forget to click on &amp;quot;Reload game informations&amp;quot; from the Control Panel so that the changes can be taken into account.&lt;br /&gt;
&lt;br /&gt;
Note: if you break gameinfos and cannot load the management page, then reload using the direct URL: https://studio.boardgamearena.com/admin/studio/reloadGameInfos.html?game= (with your game name at the end of url).&lt;br /&gt;
&lt;br /&gt;
Most of the information provided in this file is self-explanatory.&lt;br /&gt;
&lt;br /&gt;
See sections below for specific cases.&lt;br /&gt;
&lt;br /&gt;
==Publisher==&lt;br /&gt;
&lt;br /&gt;
These fields should match the publisher of the game. In the case of a public domain name, they should be left empty (empty string)&lt;br /&gt;
&lt;br /&gt;
==Beta==&lt;br /&gt;
&lt;br /&gt;
You are not allowed to set the &amp;quot;&#039;&#039;&#039;is_beta&#039;&#039;&#039;&amp;quot; to 0 before the game has been released on BGA and stabilized.&lt;br /&gt;
==Time Profiles==&lt;br /&gt;
&#039;&#039;&#039;fast/medium/slow_additional_time&#039;&#039;&#039;: please set high values here: after the game has been released, there is a process that adjusts these values to match the real game duration. Adjustment starts when the game enters beta, after that these have no effect, and require admin intervention to change.&lt;br /&gt;
&lt;br /&gt;
==Number of players==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;players&#039;&#039;&#039;&lt;br /&gt;
  &#039;players&#039; =&amp;gt; array( 3, 4, 6 ),&lt;br /&gt;
&lt;br /&gt;
*during the first step of development of a game, it is recommended to have a &amp;quot;1 player&amp;quot; configuration: it is much easier to start/stop a game this way, as you don&#039;t need to switch players.&lt;br /&gt;
*if you change the minimum number of players from 1 to 2, for example, make sure the new tables you create are not restricted from 1 to 1 player otherwise when you create a new table and this account setting is used, there will be a conflict with the new minimum number of players allowed and you will be blocked from creating the game.&lt;br /&gt;
But you can also unblock yourself by changing the number of players again, launching a game with a larger number, and then getting back to the number you want.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;suggest_player_number&#039;&#039;&#039; / &#039;&#039;&#039;not_recommend_player_number&#039;&#039;&#039;&lt;br /&gt;
  &#039;suggest_player_number&#039; =&amp;gt; 3,&lt;br /&gt;
  &#039;not_recommend_player_number&#039; =&amp;gt; array( 6 ),&lt;br /&gt;
&lt;br /&gt;
Don&#039;t specify anything here (null) if there is no configuration that is REALLY better/worse than another one. You can check player&#039;s poll on BoardGameGeek game page if you have any doubt. Note that there can be at most one suggested player count (provide either null or a single number), but there can be several not recommended player counts (provide either null or an array of values).&lt;br /&gt;
&lt;br /&gt;
Another reason to leave it blank unless there is really strong reason to do so is that suggest_player_number also has an implication on the ELO calculation, whereby the K-factor is multiplied by the number of players up to a maximum of this value (or, no max if it&#039;s not provided). That is to say, a 6-player game with a suggestion of 3-players will have ELO calculated as if it were a 3-player game.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Important exception:&#039;&#039;&#039; in the automatic lobby, if &#039;suggest_player_number&#039; is not specified, the system will try first the lowest. So if the lowest player number is not compatible with the default options for your game (especially if there is a Solo mode that can only be played in training mode) you have to specify a suggest_player_number of your choice, so that players launching a game in the automatic lobby without checking the option don&#039;t get an error with the default configuration.&lt;br /&gt;
&lt;br /&gt;
==Colors==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;player_colors&#039;&#039;&#039;&lt;br /&gt;
   &#039;player_colors&#039; =&amp;gt; array( &amp;quot;ff0000&amp;quot;, &amp;quot;008000&amp;quot;, &amp;quot;0000ff&amp;quot;, &amp;quot;ffa500&amp;quot;, &amp;quot;ffffff&amp;quot; ),&lt;br /&gt;
&lt;br /&gt;
This array defines the default player colors, theoretically this can be bigger then maximum number of players but you have to support all of the in your game.&lt;br /&gt;
Your setupNewGame in php is responsible for attributing these values to players. See section &amp;quot;Player color preferences&amp;quot; in [[Main_game_logic:_yourgamename.game.php]] for details.&lt;br /&gt;
&lt;br /&gt;
== Minimum screen size == &lt;br /&gt;
The settings to specify mobile (or small desktop) screen size if detailled here:&lt;br /&gt;
https://en.doc.boardgamearena.com/Your_game_mobile_version&lt;br /&gt;
&lt;br /&gt;
== Losers not ranked between themselves==&lt;br /&gt;
&lt;br /&gt;
By default, all player are ranked, but in some games, the rules say that all non-winners are losers and not ranked between themselves. You can set this option to true so that for your game, there are only winners and losers, without a full ranking of all players.&lt;br /&gt;
&lt;br /&gt;
The score in this case should be the same for the winners and 0 for the losers.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;padding: 1em; background: #FFCDD2; color: #B71C1C&amp;quot;&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Warning: Do not use this option in 2-player games, co-op games, or games where perfect ties are frequent, as ELO will not change when everyone is perfectly tied (including tiebreakers).&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
 // If in the game, all losers are equal (no score to rank them or explicit in the rules that losers are not ranked between them), set this to true &lt;br /&gt;
 // The game end result will display &amp;quot;Winner&amp;quot; for the 1st player and &amp;quot;Loser&amp;quot; for all other players&lt;br /&gt;
 &#039;losers_not_ranked&#039; =&amp;gt; false,&lt;br /&gt;
&#039;&#039;&#039;Note&#039;&#039;&#039;: In some team games like Tichu, Spades, and Belote, players do not gain or lose ELO by teammates. (Hover over the ELO changes to find &#039;Teammate: -100%&#039;)&lt;br /&gt;
&lt;br /&gt;
To activate this modifier for your game, please contact the BGA admin. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;b style=&amp;quot;color:darkred&amp;quot;&amp;gt;Warning:&amp;lt;/b&amp;gt; This modifier should not be applied to co-op games or games where 3 or more parties can compete each other (e.g. individual mode with 3 or more players, 2v2v2 6 player mode, and etc.).&lt;br /&gt;
&lt;br /&gt;
==Disable player rotation in case of rematch==&lt;br /&gt;
&lt;br /&gt;
By default, in case of a rematch players are rotated so that the first player changes. If for your game it&#039;s better to always have a random player order you can change this option.&lt;br /&gt;
&lt;br /&gt;
 // When doing a rematch, the player order is swapped using a &amp;quot;rotation&amp;quot; so the starting player is not the same&lt;br /&gt;
 // If you want to disable this, set this to true (even if the comment in your game file say the opposite).&lt;br /&gt;
 &#039;disable_player_order_swap_on_rematch&#039; =&amp;gt; false,&lt;br /&gt;
&lt;br /&gt;
==Deprecated fields==&lt;br /&gt;
&lt;br /&gt;
* Game designer (&amp;lt;code&amp;gt;designer&amp;lt;/code&amp;gt;)&lt;br /&gt;
* Game artist (&amp;lt;code&amp;gt;artist&amp;lt;/code&amp;gt;)&lt;br /&gt;
* Year (&amp;lt;code&amp;gt;year&amp;lt;/code&amp;gt;)&lt;br /&gt;
* Tags (&amp;lt;code&amp;gt;tags&amp;lt;/code&amp;gt;)&lt;br /&gt;
* Game presentation (&amp;lt;code&amp;gt;presentation&amp;lt;/code&amp;gt;)&lt;br /&gt;
* Game page warning (&amp;lt;code&amp;gt;gamepanel_page_warning&amp;lt;/code&amp;gt;)&lt;br /&gt;
* Custom &amp;quot;buy this game&amp;quot; button (&amp;lt;code&amp;gt;custom_buy_button&amp;lt;/code&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;⚠ Note&#039;&#039;&#039;: these fields are &amp;lt;b style=&amp;quot;color:darkred&amp;quot;&amp;gt;no longer read from this file&amp;lt;/b&amp;gt;; these are now managed via the [[Game_metadata_manager|Game Metadata Manager]].&lt;br /&gt;
&lt;br /&gt;
==Tie breaker description==&lt;br /&gt;
Describe tie breaker score calculation (player_score_aux in player table).&lt;br /&gt;
&lt;br /&gt;
Important: This is used in the javascript too, which is automatically generated. Using newlines in here will cause errors in the javascript, which will cause the game to not load.&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
 &#039;tie_breaker_description&#039; =&amp;gt; totranslate(&amp;quot;Number of remaining cards in hand&amp;quot;),&lt;br /&gt;
&lt;br /&gt;
== Multiple tie breaker management ==&lt;br /&gt;
&lt;br /&gt;
If your game has multiple tie breakers, here is what you should do.&lt;br /&gt;
&lt;br /&gt;
Let&#039;s take this example: &amp;quot;In case of a tie, the winner is the game with the most remaining money, then number of buildings built, then number of cards in your hand&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
In this example, your &amp;quot;player_score_aux&amp;quot; field might be calculated like this:&lt;br /&gt;
&lt;br /&gt;
10000 * (remaining_money ) + 100 * (buildings_built) + (number_of_cards)&lt;br /&gt;
&lt;br /&gt;
In this case, you should add the following in gameinfos.inc.php:&lt;br /&gt;
&lt;br /&gt;
  &#039;tie_breaker_split&#039; =&amp;gt; array( 10000, 100 , 1 ),&lt;br /&gt;
&lt;br /&gt;
It means that the first tie breaker has been multiplied by 10000, the second by 100, and the third by 1.&lt;br /&gt;
&lt;br /&gt;
Using this, the result screen will be adapted to show exactly what is needed. For example:&lt;br /&gt;
* When 2 players are tied, it will show their remaining money.&lt;br /&gt;
* If their remaining money are equal, it will show the number of building built in addition to the remaining money.&lt;br /&gt;
*If these two tie breaker are still the same, it will show the 3 tie breaking values.&lt;br /&gt;
&lt;br /&gt;
==Language dependency==&lt;br /&gt;
&lt;br /&gt;
If you have a game that is language dependent, you can use the option described here: [[Main_game_logic:_yourgamename.game.php#Language_dependent_games_API]]&lt;br /&gt;
&lt;br /&gt;
== Coop Elo Mode==&lt;br /&gt;
&lt;br /&gt;
For cooperative games, by default players will earn as many rating points as the score. Games ended with a positive score counts as wins, and scores of 0 or below count as losses. &lt;br /&gt;
&lt;br /&gt;
For games where there is no or little variable difficulty (such as for example Bandido) the fixed amount of score can be assigned across all settings. However, for all coop games where we have options to change the difficulty level and/or where the score reached indicates a higher level of skill and/or where the number of players has a significant impact on the difficulty, the final score should be adjusted according to the difficulty level and the number of players.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
If needed, a reference scale for Elo points (between 1300 and 2500) can be set up. Players regularly winning with a specific difficulty setting will have their Elo nearing this value asymptotically over time. For this, you can set up the coop_elo_mode parameter.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;padding: 1em; background: #FFCDD2; color: #B71C1C&amp;quot;&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Warning: While this can reflect player skills more precisely compared to flat rating gain, this parameter is generally not recommended as players may abandon losing games or avoid new players to prevent rating loss.&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Related discussion:&lt;br /&gt;
&lt;br /&gt;
https://forum.boardgamearena.com/viewtopic.php?f=3&amp;amp;t=24363&lt;br /&gt;
&lt;br /&gt;
https://boardgamearena.com/forum/viewtopic.php?t=32289&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Here is an example using options and win/loss (score 1/0):&lt;br /&gt;
&lt;br /&gt;
    &#039;coop_elo_mode&#039; =&amp;gt; [&lt;br /&gt;
        &#039;type&#039; =&amp;gt; &#039;points_references&#039;,&lt;br /&gt;
        &#039;references&#039; =&amp;gt; [&lt;br /&gt;
            // Difficulty 1&lt;br /&gt;
            [&#039;players_nbr&#039; =&amp;gt; 2, &#039;options&#039; =&amp;gt; [100 =&amp;gt; 1, 101 =&amp;gt; 0], &#039;elo&#039; =&amp;gt; [0 =&amp;gt; 1000, 1 =&amp;gt; 1400]],&lt;br /&gt;
            [&#039;players_nbr&#039; =&amp;gt; 2, &#039;options&#039; =&amp;gt; [100 =&amp;gt; 1, 101 =&amp;gt; 1], &#039;elo&#039; =&amp;gt; [0 =&amp;gt; 1000, 1 =&amp;gt; 1470]],&lt;br /&gt;
            [&#039;players_nbr&#039; =&amp;gt; 3, &#039;options&#039; =&amp;gt; [100 =&amp;gt; 1, 101 =&amp;gt; 0], &#039;elo&#039; =&amp;gt; [0 =&amp;gt; 1000, 1 =&amp;gt; 1350]],&lt;br /&gt;
            [&#039;players_nbr&#039; =&amp;gt; 3, &#039;options&#039; =&amp;gt; [100 =&amp;gt; 1, 101 =&amp;gt; 1], &#039;elo&#039; =&amp;gt; [0 =&amp;gt; 1000, 1 =&amp;gt; 1400]],&lt;br /&gt;
            [&#039;players_nbr&#039; =&amp;gt; 4, &#039;options&#039; =&amp;gt; [100 =&amp;gt; 1, 101 =&amp;gt; 0], &#039;elo&#039; =&amp;gt; [0 =&amp;gt; 1000, 1 =&amp;gt; 1400]],&lt;br /&gt;
            [&#039;players_nbr&#039; =&amp;gt; 4, &#039;options&#039; =&amp;gt; [100 =&amp;gt; 1, 101 =&amp;gt; 1], &#039;elo&#039; =&amp;gt; [0 =&amp;gt; 1000, 1 =&amp;gt; 1470]],&lt;br /&gt;
            // Difficulty 2&lt;br /&gt;
            [&#039;players_nbr&#039; =&amp;gt; 2, &#039;options&#039; =&amp;gt; [100 =&amp;gt; 2, 101 =&amp;gt; 0], &#039;elo&#039; =&amp;gt; [0 =&amp;gt; 1000, 1 =&amp;gt; 1540]],&lt;br /&gt;
            [&#039;players_nbr&#039; =&amp;gt; 2, &#039;options&#039; =&amp;gt; [100 =&amp;gt; 2, 101 =&amp;gt; 1], &#039;elo&#039; =&amp;gt; [0 =&amp;gt; 1000, 1 =&amp;gt; 1690]],&lt;br /&gt;
            [&#039;players_nbr&#039; =&amp;gt; 3, &#039;options&#039; =&amp;gt; [100 =&amp;gt; 2, 101 =&amp;gt; 0], &#039;elo&#039; =&amp;gt; [0 =&amp;gt; 1000, 1 =&amp;gt; 1450]],&lt;br /&gt;
            [&#039;players_nbr&#039; =&amp;gt; 3, &#039;options&#039; =&amp;gt; [100 =&amp;gt; 2, 101 =&amp;gt; 1], &#039;elo&#039; =&amp;gt; [0 =&amp;gt; 1000, 1 =&amp;gt; 1540]],&lt;br /&gt;
            [&#039;players_nbr&#039; =&amp;gt; 4, &#039;options&#039; =&amp;gt; [100 =&amp;gt; 2, 101 =&amp;gt; 0], &#039;elo&#039; =&amp;gt; [0 =&amp;gt; 1000, 1 =&amp;gt; 1540]],&lt;br /&gt;
            [&#039;players_nbr&#039; =&amp;gt; 4, &#039;options&#039; =&amp;gt; [100 =&amp;gt; 2, 101 =&amp;gt; 1], &#039;elo&#039; =&amp;gt; [0 =&amp;gt; 1000, 1 =&amp;gt; 1690]],&lt;br /&gt;
            // Difficulty 3&lt;br /&gt;
            [&#039;players_nbr&#039; =&amp;gt; 2, &#039;options&#039; =&amp;gt; [100 =&amp;gt; 3, 101 =&amp;gt; 0], &#039;elo&#039; =&amp;gt; [0 =&amp;gt; 1000, 1 =&amp;gt; 1690]],&lt;br /&gt;
            [&#039;players_nbr&#039; =&amp;gt; 2, &#039;options&#039; =&amp;gt; [100 =&amp;gt; 3, 101 =&amp;gt; 1], &#039;elo&#039; =&amp;gt; [0 =&amp;gt; 1000, 1 =&amp;gt; 1910]],&lt;br /&gt;
            [&#039;players_nbr&#039; =&amp;gt; 3, &#039;options&#039; =&amp;gt; [100 =&amp;gt; 3, 101 =&amp;gt; 0], &#039;elo&#039; =&amp;gt; [0 =&amp;gt; 1000, 1 =&amp;gt; 1540]],&lt;br /&gt;
            [&#039;players_nbr&#039; =&amp;gt; 3, &#039;options&#039; =&amp;gt; [100 =&amp;gt; 3, 101 =&amp;gt; 1], &#039;elo&#039; =&amp;gt; [0 =&amp;gt; 1000, 1 =&amp;gt; 1690]],&lt;br /&gt;
            [&#039;players_nbr&#039; =&amp;gt; 4, &#039;options&#039; =&amp;gt; [100 =&amp;gt; 3, 101 =&amp;gt; 0], &#039;elo&#039; =&amp;gt; [0 =&amp;gt; 1000, 1 =&amp;gt; 1690]],&lt;br /&gt;
            [&#039;players_nbr&#039; =&amp;gt; 4, &#039;options&#039; =&amp;gt; [100 =&amp;gt; 3, 101 =&amp;gt; 1], &#039;elo&#039; =&amp;gt; [0 =&amp;gt; 1000, 1 =&amp;gt; 1910]],&lt;br /&gt;
            // Difficulty 4&lt;br /&gt;
            [&#039;players_nbr&#039; =&amp;gt; 2, &#039;options&#039; =&amp;gt; [100 =&amp;gt; 4, 101 =&amp;gt; 0], &#039;elo&#039; =&amp;gt; [0 =&amp;gt; 1000, 1 =&amp;gt; 1830]],&lt;br /&gt;
            [&#039;players_nbr&#039; =&amp;gt; 2, &#039;options&#039; =&amp;gt; [100 =&amp;gt; 4, 101 =&amp;gt; 1], &#039;elo&#039; =&amp;gt; [0 =&amp;gt; 1000, 1 =&amp;gt; 2120]],&lt;br /&gt;
            [&#039;players_nbr&#039; =&amp;gt; 3, &#039;options&#039; =&amp;gt; [100 =&amp;gt; 4, 101 =&amp;gt; 0], &#039;elo&#039; =&amp;gt; [0 =&amp;gt; 1000, 1 =&amp;gt; 1640]],&lt;br /&gt;
            [&#039;players_nbr&#039; =&amp;gt; 3, &#039;options&#039; =&amp;gt; [100 =&amp;gt; 4, 101 =&amp;gt; 1], &#039;elo&#039; =&amp;gt; [0 =&amp;gt; 1000, 1 =&amp;gt; 1830]],&lt;br /&gt;
            [&#039;players_nbr&#039; =&amp;gt; 4, &#039;options&#039; =&amp;gt; [100 =&amp;gt; 4, 101 =&amp;gt; 0], &#039;elo&#039; =&amp;gt; [0 =&amp;gt; 1000, 1 =&amp;gt; 1830]],&lt;br /&gt;
            [&#039;players_nbr&#039; =&amp;gt; 4, &#039;options&#039; =&amp;gt; [100 =&amp;gt; 4, 101 =&amp;gt; 1], &#039;elo&#039; =&amp;gt; [0 =&amp;gt; 1000, 1 =&amp;gt; 2120]],&lt;br /&gt;
            // Difficulty 5&lt;br /&gt;
            [&#039;players_nbr&#039; =&amp;gt; 2, &#039;options&#039; =&amp;gt; [100 =&amp;gt; 5, 101 =&amp;gt; 0], &#039;elo&#039; =&amp;gt; [0 =&amp;gt; 1000, 1 =&amp;gt; 1980]],&lt;br /&gt;
            [&#039;players_nbr&#039; =&amp;gt; 2, &#039;options&#039; =&amp;gt; [100 =&amp;gt; 5, 101 =&amp;gt; 1], &#039;elo&#039; =&amp;gt; [0 =&amp;gt; 1000, 1 =&amp;gt; 2340]],&lt;br /&gt;
            [&#039;players_nbr&#039; =&amp;gt; 3, &#039;options&#039; =&amp;gt; [100 =&amp;gt; 5, 101 =&amp;gt; 0], &#039;elo&#039; =&amp;gt; [0 =&amp;gt; 1000, 1 =&amp;gt; 1740]],&lt;br /&gt;
            [&#039;players_nbr&#039; =&amp;gt; 3, &#039;options&#039; =&amp;gt; [100 =&amp;gt; 5, 101 =&amp;gt; 1], &#039;elo&#039; =&amp;gt; [0 =&amp;gt; 1000, 1 =&amp;gt; 1980]],&lt;br /&gt;
            [&#039;players_nbr&#039; =&amp;gt; 4, &#039;options&#039; =&amp;gt; [100 =&amp;gt; 5, 101 =&amp;gt; 0], &#039;elo&#039; =&amp;gt; [0 =&amp;gt; 1000, 1 =&amp;gt; 1980]],&lt;br /&gt;
            [&#039;players_nbr&#039; =&amp;gt; 4, &#039;options&#039; =&amp;gt; [100 =&amp;gt; 5, 101 =&amp;gt; 1], &#039;elo&#039; =&amp;gt; [0 =&amp;gt; 1000, 1 =&amp;gt; 2340]],&lt;br /&gt;
        ],&lt;br /&gt;
    ],&lt;br /&gt;
&lt;br /&gt;
Here is an example using different scoring values to indicate the level of difficulty mastered by the players winning the game:&lt;br /&gt;
&lt;br /&gt;
    &#039;coop_elo_mode&#039; =&amp;gt; array(&lt;br /&gt;
        &#039;type&#039; =&amp;gt; &#039;points_references&#039;,&lt;br /&gt;
        &#039;references&#039; =&amp;gt; array(&lt;br /&gt;
            array(&lt;br /&gt;
                &#039;players_nbr&#039; =&amp;gt; 2,&lt;br /&gt;
                //&#039;options&#039; =&amp;gt; array( ),&lt;br /&gt;
                &#039;elo&#039; =&amp;gt; array(&lt;br /&gt;
                    0 =&amp;gt; 1000,&lt;br /&gt;
                    1 =&amp;gt; 1350,&lt;br /&gt;
                    2 =&amp;gt; 1425,&lt;br /&gt;
                    3 =&amp;gt; 1500,&lt;br /&gt;
                    4 =&amp;gt; 1576,&lt;br /&gt;
                    5 =&amp;gt; 1651,&lt;br /&gt;
                    6 =&amp;gt; 1727,&lt;br /&gt;
                    7 =&amp;gt; 1802,&lt;br /&gt;
                    8 =&amp;gt; 1878,&lt;br /&gt;
                    9 =&amp;gt; 1953,&lt;br /&gt;
                    10 =&amp;gt; 2029,&lt;br /&gt;
                    11 =&amp;gt; 2104,&lt;br /&gt;
                    12 =&amp;gt; 2180&lt;br /&gt;
                )&lt;br /&gt;
            ),&lt;br /&gt;
            array(&lt;br /&gt;
                &#039;players_nbr&#039; =&amp;gt; 3,&lt;br /&gt;
                //&#039;options&#039; =&amp;gt; array( ),&lt;br /&gt;
                &#039;elo&#039; =&amp;gt; array(&lt;br /&gt;
                    0 =&amp;gt; 1000,&lt;br /&gt;
                    1 =&amp;gt; 1400,&lt;br /&gt;
                    2 =&amp;gt; 1470,&lt;br /&gt;
                    3 =&amp;gt; 1541,&lt;br /&gt;
                    4 =&amp;gt; 1612,&lt;br /&gt;
                    5 =&amp;gt; 1683,&lt;br /&gt;
                    6 =&amp;gt; 1754,&lt;br /&gt;
                    7 =&amp;gt; 1825,&lt;br /&gt;
                    8 =&amp;gt; 1895,&lt;br /&gt;
                    9 =&amp;gt; 1966,&lt;br /&gt;
                    10 =&amp;gt; 2018,&lt;br /&gt;
                    11 =&amp;gt; 2095,&lt;br /&gt;
                    12 =&amp;gt; 2250&lt;br /&gt;
                )&lt;br /&gt;
            ),&lt;br /&gt;
            array(&lt;br /&gt;
                &#039;players_nbr&#039; =&amp;gt; 4,&lt;br /&gt;
                //&#039;options&#039; =&amp;gt; array( ),&lt;br /&gt;
                &#039;elo&#039; =&amp;gt; array(&lt;br /&gt;
                    0 =&amp;gt; 1000,&lt;br /&gt;
                    1 =&amp;gt; 1430,&lt;br /&gt;
                    2 =&amp;gt; 1505,&lt;br /&gt;
                    3 =&amp;gt; 1580,&lt;br /&gt;
                    4 =&amp;gt; 1655,&lt;br /&gt;
                    5 =&amp;gt; 1730,&lt;br /&gt;
                    6 =&amp;gt; 1805,&lt;br /&gt;
                    7 =&amp;gt; 1880,&lt;br /&gt;
                    8 =&amp;gt; 1955,&lt;br /&gt;
                    9 =&amp;gt; 2030,&lt;br /&gt;
                    10 =&amp;gt; 2105,&lt;br /&gt;
                    11 =&amp;gt; 2180,&lt;br /&gt;
                    12 =&amp;gt; 2330&lt;br /&gt;
                )&lt;br /&gt;
            ),&lt;br /&gt;
            array(&lt;br /&gt;
                &#039;players_nbr&#039; =&amp;gt; 5,&lt;br /&gt;
                // &#039;options&#039; =&amp;gt; array( ),&lt;br /&gt;
                &#039;elo&#039; =&amp;gt; array(&lt;br /&gt;
                    0 =&amp;gt; 1000,&lt;br /&gt;
                    1 =&amp;gt; 1480,&lt;br /&gt;
                    2 =&amp;gt; 1558,&lt;br /&gt;
                    3 =&amp;gt; 1636,&lt;br /&gt;
                    4 =&amp;gt; 1714,&lt;br /&gt;
                    5 =&amp;gt; 1792,&lt;br /&gt;
                    6 =&amp;gt; 1870,&lt;br /&gt;
                    7 =&amp;gt; 1949,&lt;br /&gt;
                    8 =&amp;gt; 2027,&lt;br /&gt;
                    9 =&amp;gt; 2105,&lt;br /&gt;
                    10 =&amp;gt; 2183,&lt;br /&gt;
                    11 =&amp;gt; 2261,&lt;br /&gt;
                    12 =&amp;gt; 2340&lt;br /&gt;
                )&lt;br /&gt;
            )&lt;br /&gt;
        )&lt;br /&gt;
    ),&lt;br /&gt;
&lt;br /&gt;
[[Category:Studio]]&lt;/div&gt;</summary>
		<author><name>Sguzzer Gunayer</name></author>
	</entry>
	<entry>
		<id>https://en.doc.boardgamearena.com/index.php?title=Game_material_description:_material.inc.php&amp;diff=22453</id>
		<title>Game material description: material.inc.php</title>
		<link rel="alternate" type="text/html" href="https://en.doc.boardgamearena.com/index.php?title=Game_material_description:_material.inc.php&amp;diff=22453"/>
		<updated>2024-09-06T16:12:42Z</updated>

		<summary type="html">&lt;p&gt;Sguzzer Gunayer: /* PHP constants */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Studio_Framework_Navigation}}&lt;br /&gt;
&lt;br /&gt;
== Overview ==&lt;br /&gt;
This PHP file describes all the material of your game.&lt;br /&gt;
&lt;br /&gt;
This file is included by the constructor of your main game logic (yourgame.game.php), and then the variables defined here are accessible everywhere in your game logic file (and also view.php file).&lt;br /&gt;
&lt;br /&gt;
Using material.inc.php makes your PHP logic file smaller and clean. Normally you put ALL static information about your cards, tokens, tiles, etc in that file which do not change. Do not store static info in database.&lt;br /&gt;
&lt;br /&gt;
== Definition ==&lt;br /&gt;
Example from &amp;quot;Eminent Domain&amp;quot;: &lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$this-&amp;gt;token_types = [&lt;br /&gt;
 &#039;card_role_survey&#039; =&amp;gt; [&lt;br /&gt;
   &#039;type&#039; =&amp;gt; &#039;card_role&#039;,&lt;br /&gt;
   &#039;name&#039; =&amp;gt; clienttranslate(&amp;quot;Survey&amp;quot;),&lt;br /&gt;
   &#039;tooltip&#039; =&amp;gt; clienttranslate(&amp;quot;ACTION: Draw 2 Cards&amp;lt;br/&amp;gt;&amp;lt;br/&amp;gt;ROLE: Look at &amp;lt;div class=&#039;icon survey&#039;&amp;gt;&amp;lt;/div&amp;gt; - 1 planet cards, keep 1&amp;lt;br/&amp;gt; &amp;lt;span class=&#039;yellow&#039;&amp;gt;Leader:&amp;lt;/span&amp;gt; Look at 1 additional card&amp;quot;),&lt;br /&gt;
   &#039;b&#039;=&amp;gt;0,&lt;br /&gt;
   &#039;p&#039;=&amp;gt;&#039;&#039;,&lt;br /&gt;
   &#039;i&#039;=&amp;gt;&#039;S&#039;,&lt;br /&gt;
   &#039;v&#039;=&amp;gt;0,&lt;br /&gt;
   &#039;a&#039;=&amp;gt;&#039;dd&#039;,&lt;br /&gt;
   &#039;r&#039;=&amp;gt;&#039;S&#039;, &lt;br /&gt;
   &#039;l&#039;=&amp;gt;&#039;v&#039;,&lt;br /&gt;
  ],&lt;br /&gt;
&lt;br /&gt;
 &#039;card_tech_1_51&#039; =&amp;gt; [&lt;br /&gt;
   &#039;type&#039; =&amp;gt; &#039;tech&#039;,&lt;br /&gt;
   &#039;name&#039; =&amp;gt; clienttranslate(&amp;quot;Improved Trade&amp;quot;),&lt;br /&gt;
   &#039;b&#039; =&amp;gt; 3,&lt;br /&gt;
   &#039;p&#039; =&amp;gt; &#039;E&#039;,&lt;br /&gt;
   &#039;i&#039; =&amp;gt; &#039;TP&#039;,&lt;br /&gt;
   &#039;v&#039; =&amp;gt; 0,&lt;br /&gt;
   &#039;a&#039; =&amp;gt; &#039;i&#039;,&lt;br /&gt;
   &#039;side&#039; =&amp;gt; 0,&lt;br /&gt;
   &#039;tooltip&#039; =&amp;gt; clienttranslate(&amp;quot;Collect 1 Influence from the supply.&amp;quot;),&lt;br /&gt;
 ],&lt;br /&gt;
&lt;br /&gt;
...&lt;br /&gt;
];&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
So this defines all info about cards, including types, names, tooltips (to be show on client), rules, payment cost, etc.&lt;br /&gt;
&lt;br /&gt;
You can also define PHP constants that can be used in material file and game.php file:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
if (!defined(&#039;TAPESTRY&#039;)) { // guard since this included multiple times&lt;br /&gt;
    define(&amp;quot;TAPESTRY&amp;quot;, 0);&lt;br /&gt;
    define(&amp;quot;TRACK_EXPLORATION&amp;quot;, 1);&lt;br /&gt;
    define(&amp;quot;TRACK_SCIENCE&amp;quot;, 2);&lt;br /&gt;
    define(&amp;quot;TRACK_MILITARY&amp;quot;, 3);&lt;br /&gt;
    define(&amp;quot;TRACK_TECHNOLOGY&amp;quot;, 4);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Access ==&lt;br /&gt;
&lt;br /&gt;
=== Data fields ===&lt;br /&gt;
To access this in PHP side:&lt;br /&gt;
  $type = $this-&amp;gt;token_types[&#039;card_tech_1_51&#039;][&#039;type&#039;];&lt;br /&gt;
&lt;br /&gt;
To access on JS side you have to send all variables from material file via getAllDatas first:&lt;br /&gt;
    protected function getAllDatas() {&lt;br /&gt;
        $result = array ();&lt;br /&gt;
        $result [&#039;token_types&#039;] = $this-&amp;gt;token_types;&lt;br /&gt;
        ...&lt;br /&gt;
        return $result;&lt;br /&gt;
    }&lt;br /&gt;
  &lt;br /&gt;
Then you can access it in similar way:&lt;br /&gt;
  var type = this.gamedatas.token_types[&#039;card_tech_1_51&#039;].type; // not translatable&lt;br /&gt;
  var name = _(this.gamedatas.token_types[&#039;card_tech_1_51&#039;].name); // to be shown to user (NOI18N)&lt;br /&gt;
&lt;br /&gt;
To send this in notification from PHP side:&lt;br /&gt;
  $this-&amp;gt;notifyAllUsers(&#039;gainCard&#039;,clienttranslate(&#039;player gains ${card_name}&#039;), [&lt;br /&gt;
       &#039;i18n&#039;=&amp;gt;[&#039;card_name&#039;],&lt;br /&gt;
       &#039;card_id&#039; =&amp;gt; $card_id,&lt;br /&gt;
       &#039;card_name&#039; =&amp;gt; $this-&amp;gt;token_types[$card_id][&#039;name&#039;]&lt;br /&gt;
  ]);&lt;br /&gt;
&lt;br /&gt;
=== PHP constants ===&lt;br /&gt;
If you also want to access constants in JS side, you can send them via getAllData like this&lt;br /&gt;
&lt;br /&gt;
        $cc = get_defined_constants(true)[&#039;user&#039;];&lt;br /&gt;
        $result[&#039;constants&#039;]=$cc; // this will be all constants though, you may have to filter some stuff out for security reasons&lt;br /&gt;
&lt;br /&gt;
Alternately you can include a material.inc.php in local php file and call this method to print constants in JS format, then include this file in JS, you may have to synchronize this manually, but its better for auto-complete also.&lt;br /&gt;
        // this needs to be run locally after including materal file (see example in testing below)&lt;br /&gt;
        $cc = get_defined_constants(true)[&#039;user&#039;];&lt;br /&gt;
        foreach ($cc as $key =&amp;gt; $value) {          &lt;br /&gt;
            print (&amp;quot;const $key = $value;\n&amp;quot;);&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
== Testing ==&lt;br /&gt;
If you screw up you material file such as miss some brackets it is very hard to diagnose. But you can test it locally like this&lt;br /&gt;
&lt;br /&gt;
misc/material_test.php:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;?php&lt;br /&gt;
class material_test {&lt;br /&gt;
    function __construct() {&lt;br /&gt;
        include &#039;../material.inc.php&#039;;&lt;br /&gt;
        var_dump($this-&amp;gt;token_types); // whatever your var&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
// stub&lt;br /&gt;
function clienttranslate($x) { return $x; }&lt;br /&gt;
&lt;br /&gt;
new material_test();&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Adjusting material ==&lt;br /&gt;
&lt;br /&gt;
In rare cases expansions of the game change the materials of the original game, in such cases same card for example was re-printed with a different text/rules.&lt;br /&gt;
Can you keep same card and have material adjust based on seelcted game options? It is possible with some trickery.&lt;br /&gt;
&lt;br /&gt;
You need to modify the data in that file AFTER constructor when database access is initialized, and have it available for all php entry points.&lt;br /&gt;
This is possible if you override function initTable() in your game.php file:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    /**&lt;br /&gt;
     * This is called before every action, unlike constructor this method has initialized state of the table so it can&lt;br /&gt;
     * access db&lt;br /&gt;
     *&lt;br /&gt;
     * @Override&lt;br /&gt;
     */&lt;br /&gt;
    protected function initTable() {&lt;br /&gt;
        // this fiddles with material file depending on the extension selected&lt;br /&gt;
        $this-&amp;gt;adjustMaterial();&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function adjustMaterial($force = false) {&lt;br /&gt;
        if ( !$force &amp;amp;&amp;amp; $this-&amp;gt;token_types_adjusted)&lt;br /&gt;
            return;&lt;br /&gt;
        $this-&amp;gt;token_types_adjusted = true;&lt;br /&gt;
        ... // fiddle with data in material file&lt;br /&gt;
    }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
To adjust material itself - you can do it in any number of ways I personally use this method: for modified values I specify key posfix that match my game option, and adjustment function re-write my keys, for example&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 &#039;card_tech_1_51&#039; =&amp;gt; [&lt;br /&gt;
   &#039;name&#039; =&amp;gt; clienttranslate(&amp;quot;Improved Trade&amp;quot;),&lt;br /&gt;
   &#039;name@e3&#039; =&amp;gt; clienttranslate(&amp;quot;Much Improved Trade&amp;quot;),&lt;br /&gt;
   &#039;cost&#039; =&amp;gt; 3,&lt;br /&gt;
   &#039;cost@p2&#039; =&amp;gt; 2&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In this example if player selects game expansion 3, the key name@e2 would override key name, and if there is 2 players, cost@p2 will override cost. If you need exact code, check adjustMaterial in Ultimate Railroads&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Note: if you need to add some data to material.inc.php programmatically which does not require database, you can just do it right in that file. Keep in mind will run multiple time for each php call back, so it should be very light&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$this-&amp;gt;decks = array (&lt;br /&gt;
        &#039;g&#039; =&amp;gt; array (&#039;id&#039; =&amp;gt; &#039;green&#039;,&#039;name&#039; =&amp;gt; clienttranslate(&#039;Green&#039;),&#039;num&#039; =&amp;gt; 1 ),&lt;br /&gt;
        &#039;r&#039; =&amp;gt; array (&#039;id&#039; =&amp;gt; &#039;red&#039;,&#039;name&#039; =&amp;gt; clienttranslate(&#039;Red&#039;),&#039;num&#039; =&amp;gt; 3 ),&lt;br /&gt;
        &#039;v&#039; =&amp;gt; array (&#039;id&#039; =&amp;gt; &#039;violet&#039;,&#039;name&#039; =&amp;gt; clienttranslate(&#039;Violet&#039;),&#039;num&#039; =&amp;gt; 4 ),&lt;br /&gt;
        &#039;y&#039; =&amp;gt; array (&#039;id&#039; =&amp;gt; &#039;yellow&#039;,&#039;name&#039; =&amp;gt; clienttranslate(&#039;Yellow&#039;),&#039;num&#039; =&amp;gt; 2 ) )&lt;br /&gt;
;&lt;br /&gt;
    &lt;br /&gt;
$this-&amp;gt;dcolor_map = array();&lt;br /&gt;
// reverse map&lt;br /&gt;
foreach ($this-&amp;gt;decks as $info) {&lt;br /&gt;
    $this-&amp;gt;dcolor_map[$info[&#039;num&#039;]]=$info[&#039;id&#039;];&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Category:Studio]]&lt;/div&gt;</summary>
		<author><name>Sguzzer Gunayer</name></author>
	</entry>
	<entry>
		<id>https://en.doc.boardgamearena.com/index.php?title=Game_material_description:_material.inc.php&amp;diff=22452</id>
		<title>Game material description: material.inc.php</title>
		<link rel="alternate" type="text/html" href="https://en.doc.boardgamearena.com/index.php?title=Game_material_description:_material.inc.php&amp;diff=22452"/>
		<updated>2024-09-06T16:12:15Z</updated>

		<summary type="html">&lt;p&gt;Sguzzer Gunayer: /* PHP constants */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Studio_Framework_Navigation}}&lt;br /&gt;
&lt;br /&gt;
== Overview ==&lt;br /&gt;
This PHP file describes all the material of your game.&lt;br /&gt;
&lt;br /&gt;
This file is included by the constructor of your main game logic (yourgame.game.php), and then the variables defined here are accessible everywhere in your game logic file (and also view.php file).&lt;br /&gt;
&lt;br /&gt;
Using material.inc.php makes your PHP logic file smaller and clean. Normally you put ALL static information about your cards, tokens, tiles, etc in that file which do not change. Do not store static info in database.&lt;br /&gt;
&lt;br /&gt;
== Definition ==&lt;br /&gt;
Example from &amp;quot;Eminent Domain&amp;quot;: &lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$this-&amp;gt;token_types = [&lt;br /&gt;
 &#039;card_role_survey&#039; =&amp;gt; [&lt;br /&gt;
   &#039;type&#039; =&amp;gt; &#039;card_role&#039;,&lt;br /&gt;
   &#039;name&#039; =&amp;gt; clienttranslate(&amp;quot;Survey&amp;quot;),&lt;br /&gt;
   &#039;tooltip&#039; =&amp;gt; clienttranslate(&amp;quot;ACTION: Draw 2 Cards&amp;lt;br/&amp;gt;&amp;lt;br/&amp;gt;ROLE: Look at &amp;lt;div class=&#039;icon survey&#039;&amp;gt;&amp;lt;/div&amp;gt; - 1 planet cards, keep 1&amp;lt;br/&amp;gt; &amp;lt;span class=&#039;yellow&#039;&amp;gt;Leader:&amp;lt;/span&amp;gt; Look at 1 additional card&amp;quot;),&lt;br /&gt;
   &#039;b&#039;=&amp;gt;0,&lt;br /&gt;
   &#039;p&#039;=&amp;gt;&#039;&#039;,&lt;br /&gt;
   &#039;i&#039;=&amp;gt;&#039;S&#039;,&lt;br /&gt;
   &#039;v&#039;=&amp;gt;0,&lt;br /&gt;
   &#039;a&#039;=&amp;gt;&#039;dd&#039;,&lt;br /&gt;
   &#039;r&#039;=&amp;gt;&#039;S&#039;, &lt;br /&gt;
   &#039;l&#039;=&amp;gt;&#039;v&#039;,&lt;br /&gt;
  ],&lt;br /&gt;
&lt;br /&gt;
 &#039;card_tech_1_51&#039; =&amp;gt; [&lt;br /&gt;
   &#039;type&#039; =&amp;gt; &#039;tech&#039;,&lt;br /&gt;
   &#039;name&#039; =&amp;gt; clienttranslate(&amp;quot;Improved Trade&amp;quot;),&lt;br /&gt;
   &#039;b&#039; =&amp;gt; 3,&lt;br /&gt;
   &#039;p&#039; =&amp;gt; &#039;E&#039;,&lt;br /&gt;
   &#039;i&#039; =&amp;gt; &#039;TP&#039;,&lt;br /&gt;
   &#039;v&#039; =&amp;gt; 0,&lt;br /&gt;
   &#039;a&#039; =&amp;gt; &#039;i&#039;,&lt;br /&gt;
   &#039;side&#039; =&amp;gt; 0,&lt;br /&gt;
   &#039;tooltip&#039; =&amp;gt; clienttranslate(&amp;quot;Collect 1 Influence from the supply.&amp;quot;),&lt;br /&gt;
 ],&lt;br /&gt;
&lt;br /&gt;
...&lt;br /&gt;
];&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
So this defines all info about cards, including types, names, tooltips (to be show on client), rules, payment cost, etc.&lt;br /&gt;
&lt;br /&gt;
You can also define PHP constants that can be used in material file and game.php file:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
if (!defined(&#039;TAPESTRY&#039;)) { // guard since this included multiple times&lt;br /&gt;
    define(&amp;quot;TAPESTRY&amp;quot;, 0);&lt;br /&gt;
    define(&amp;quot;TRACK_EXPLORATION&amp;quot;, 1);&lt;br /&gt;
    define(&amp;quot;TRACK_SCIENCE&amp;quot;, 2);&lt;br /&gt;
    define(&amp;quot;TRACK_MILITARY&amp;quot;, 3);&lt;br /&gt;
    define(&amp;quot;TRACK_TECHNOLOGY&amp;quot;, 4);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Access ==&lt;br /&gt;
&lt;br /&gt;
=== Data fields ===&lt;br /&gt;
To access this in PHP side:&lt;br /&gt;
  $type = $this-&amp;gt;token_types[&#039;card_tech_1_51&#039;][&#039;type&#039;];&lt;br /&gt;
&lt;br /&gt;
To access on JS side you have to send all variables from material file via getAllDatas first:&lt;br /&gt;
    protected function getAllDatas() {&lt;br /&gt;
        $result = array ();&lt;br /&gt;
        $result [&#039;token_types&#039;] = $this-&amp;gt;token_types;&lt;br /&gt;
        ...&lt;br /&gt;
        return $result;&lt;br /&gt;
    }&lt;br /&gt;
  &lt;br /&gt;
Then you can access it in similar way:&lt;br /&gt;
  var type = this.gamedatas.token_types[&#039;card_tech_1_51&#039;].type; // not translatable&lt;br /&gt;
  var name = _(this.gamedatas.token_types[&#039;card_tech_1_51&#039;].name); // to be shown to user (NOI18N)&lt;br /&gt;
&lt;br /&gt;
To send this in notification from PHP side:&lt;br /&gt;
  $this-&amp;gt;notifyAllUsers(&#039;gainCard&#039;,clienttranslate(&#039;player gains ${card_name}&#039;), [&lt;br /&gt;
       &#039;i18n&#039;=&amp;gt;[&#039;card_name&#039;],&lt;br /&gt;
       &#039;card_id&#039; =&amp;gt; $card_id,&lt;br /&gt;
       &#039;card_name&#039; =&amp;gt; $this-&amp;gt;token_types[$card_id][&#039;name&#039;]&lt;br /&gt;
  ]);&lt;br /&gt;
&lt;br /&gt;
=== PHP constants ===&lt;br /&gt;
If you also want to access constants in JS side, you can send them via getAllData like this&lt;br /&gt;
&lt;br /&gt;
        $cc = get_defined_constants(true)[&#039;user&#039;];&lt;br /&gt;
        $result[&#039;constants&#039;]=$cc; // this will be all constants though, you may have to filter some stuff out for security reasons&lt;br /&gt;
&lt;br /&gt;
Alternately you can include a material.inc.php in local php file and call this method to print constants in JS format, then include this file in JS, you may have to syncronize this manually, but its better for auto-complete also.&lt;br /&gt;
        // this needs to be run locally after including materal file (see example in testing below)&lt;br /&gt;
        $cc = get_defined_constants(true)[&#039;user&#039;];&lt;br /&gt;
        foreach ($cc as $key =&amp;gt; $value) {          &lt;br /&gt;
            print (&amp;quot;const $key = $value;\n&amp;quot;);&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
== Testing ==&lt;br /&gt;
If you screw up you material file such as miss some brackets it is very hard to diagnose. But you can test it locally like this&lt;br /&gt;
&lt;br /&gt;
misc/material_test.php:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;?php&lt;br /&gt;
class material_test {&lt;br /&gt;
    function __construct() {&lt;br /&gt;
        include &#039;../material.inc.php&#039;;&lt;br /&gt;
        var_dump($this-&amp;gt;token_types); // whatever your var&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
// stub&lt;br /&gt;
function clienttranslate($x) { return $x; }&lt;br /&gt;
&lt;br /&gt;
new material_test();&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Adjusting material ==&lt;br /&gt;
&lt;br /&gt;
In rare cases expansions of the game change the materials of the original game, in such cases same card for example was re-printed with a different text/rules.&lt;br /&gt;
Can you keep same card and have material adjust based on seelcted game options? It is possible with some trickery.&lt;br /&gt;
&lt;br /&gt;
You need to modify the data in that file AFTER constructor when database access is initialized, and have it available for all php entry points.&lt;br /&gt;
This is possible if you override function initTable() in your game.php file:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    /**&lt;br /&gt;
     * This is called before every action, unlike constructor this method has initialized state of the table so it can&lt;br /&gt;
     * access db&lt;br /&gt;
     *&lt;br /&gt;
     * @Override&lt;br /&gt;
     */&lt;br /&gt;
    protected function initTable() {&lt;br /&gt;
        // this fiddles with material file depending on the extension selected&lt;br /&gt;
        $this-&amp;gt;adjustMaterial();&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    function adjustMaterial($force = false) {&lt;br /&gt;
        if ( !$force &amp;amp;&amp;amp; $this-&amp;gt;token_types_adjusted)&lt;br /&gt;
            return;&lt;br /&gt;
        $this-&amp;gt;token_types_adjusted = true;&lt;br /&gt;
        ... // fiddle with data in material file&lt;br /&gt;
    }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
To adjust material itself - you can do it in any number of ways I personally use this method: for modified values I specify key posfix that match my game option, and adjustment function re-write my keys, for example&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 &#039;card_tech_1_51&#039; =&amp;gt; [&lt;br /&gt;
   &#039;name&#039; =&amp;gt; clienttranslate(&amp;quot;Improved Trade&amp;quot;),&lt;br /&gt;
   &#039;name@e3&#039; =&amp;gt; clienttranslate(&amp;quot;Much Improved Trade&amp;quot;),&lt;br /&gt;
   &#039;cost&#039; =&amp;gt; 3,&lt;br /&gt;
   &#039;cost@p2&#039; =&amp;gt; 2&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In this example if player selects game expansion 3, the key name@e2 would override key name, and if there is 2 players, cost@p2 will override cost. If you need exact code, check adjustMaterial in Ultimate Railroads&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Note: if you need to add some data to material.inc.php programmatically which does not require database, you can just do it right in that file. Keep in mind will run multiple time for each php call back, so it should be very light&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$this-&amp;gt;decks = array (&lt;br /&gt;
        &#039;g&#039; =&amp;gt; array (&#039;id&#039; =&amp;gt; &#039;green&#039;,&#039;name&#039; =&amp;gt; clienttranslate(&#039;Green&#039;),&#039;num&#039; =&amp;gt; 1 ),&lt;br /&gt;
        &#039;r&#039; =&amp;gt; array (&#039;id&#039; =&amp;gt; &#039;red&#039;,&#039;name&#039; =&amp;gt; clienttranslate(&#039;Red&#039;),&#039;num&#039; =&amp;gt; 3 ),&lt;br /&gt;
        &#039;v&#039; =&amp;gt; array (&#039;id&#039; =&amp;gt; &#039;violet&#039;,&#039;name&#039; =&amp;gt; clienttranslate(&#039;Violet&#039;),&#039;num&#039; =&amp;gt; 4 ),&lt;br /&gt;
        &#039;y&#039; =&amp;gt; array (&#039;id&#039; =&amp;gt; &#039;yellow&#039;,&#039;name&#039; =&amp;gt; clienttranslate(&#039;Yellow&#039;),&#039;num&#039; =&amp;gt; 2 ) )&lt;br /&gt;
;&lt;br /&gt;
    &lt;br /&gt;
$this-&amp;gt;dcolor_map = array();&lt;br /&gt;
// reverse map&lt;br /&gt;
foreach ($this-&amp;gt;decks as $info) {&lt;br /&gt;
    $this-&amp;gt;dcolor_map[$info[&#039;num&#039;]]=$info[&#039;id&#039;];&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Category:Studio]]&lt;/div&gt;</summary>
		<author><name>Sguzzer Gunayer</name></author>
	</entry>
	<entry>
		<id>https://en.doc.boardgamearena.com/index.php?title=Game_layout:_view_and_template:_yourgamename.view.php_and_yourgamename_yourgamename.tpl&amp;diff=22445</id>
		<title>Game layout: view and template: yourgamename.view.php and yourgamename yourgamename.tpl</title>
		<link rel="alternate" type="text/html" href="https://en.doc.boardgamearena.com/index.php?title=Game_layout:_view_and_template:_yourgamename.view.php_and_yourgamename_yourgamename.tpl&amp;diff=22445"/>
		<updated>2024-09-05T18:30:58Z</updated>

		<summary type="html">&lt;p&gt;Sguzzer Gunayer: /* Access spectator status */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Studio_Framework_Navigation}}&lt;br /&gt;
&lt;br /&gt;
== Overview ==&lt;br /&gt;
[[File:bga-pages-from-templates.PNG|700px]]&lt;br /&gt;
&lt;br /&gt;
There are two files involved in overall game layout: yourgamename.view.php and yourgamename_yourgamename.tpl.&lt;br /&gt;
&lt;br /&gt;
These files work together to provide the HTML layout of your game.&lt;br /&gt;
&lt;br /&gt;
Using these 2 files, you specify what HTML is rendered in your game client interface.&lt;br /&gt;
&lt;br /&gt;
In .tpl file you can directly write raw HTML that will be displayed by the browser.&lt;br /&gt;
&lt;br /&gt;
Example: extract of &amp;quot;hearts_hearts.tpl&amp;quot;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  &amp;lt;div id=&amp;quot;myhand_wrap&amp;quot; class=&amp;quot;whiteblock&amp;quot;&amp;gt;&lt;br /&gt;
    &amp;lt;h3&amp;gt;{MY_HAND}&amp;lt;/h3&amp;gt;&lt;br /&gt;
    &amp;lt;div id=&amp;quot;myhand&amp;quot;&amp;gt;&lt;br /&gt;
    &amp;lt;/div&amp;gt;&lt;br /&gt;
  &amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Things in curly braces are template variables. You cannot put any english text directly there.&lt;br /&gt;
&lt;br /&gt;
Your view and your template are supposed to generate only the BASE layout of the game.&lt;br /&gt;
&lt;br /&gt;
You shouldn&#039;t try to setup the current game situation in the view: this is the role of your Javascript code. Why? Because you&#039;ll have to write Javascript code to put game elements in place anyway, and you don&#039;t want to write it twice :)&lt;br /&gt;
&lt;br /&gt;
Example of things to generate in your view:&lt;br /&gt;
* The overall layout of your game interface (what is displayed where).&lt;br /&gt;
* The board and fixed elements on the board (ex: places for cards, squares, ...).&lt;br /&gt;
* The tokens which are always on the board (but JS code may move them around during setup)&lt;br /&gt;
&lt;br /&gt;
Example of things that shouldn&#039;t be generate by your view:&lt;br /&gt;
* Game elements that come and go from the game area.&lt;br /&gt;
* Game elements that normally hidden from players (other players cards, cards in the deck).&lt;br /&gt;
&lt;br /&gt;
== Template system ==&lt;br /&gt;
&lt;br /&gt;
BGA is using the phplib template system, used for example in PHPbb forums.&lt;br /&gt;
&lt;br /&gt;
More details about how to use phplib template system here:&lt;br /&gt;
https://web.archive.org/web/20170506065401/http://www.phpbuilder.com:80/columns/david20000512.php3&lt;br /&gt;
&lt;br /&gt;
== Variables ==&lt;br /&gt;
&lt;br /&gt;
In your template (.tpl) file, you can use variables. Then in your view (.view.php) file, you fill these variables with values.&lt;br /&gt;
&lt;br /&gt;
In the example above, &amp;quot;{MY_HAND}&amp;quot; is a variable. As you can see, a variable is uppercase characters surrounded by &amp;quot;{&amp;quot; and &amp;quot;}&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
This is example of how to assign values to these variables in .view.php:&lt;br /&gt;
&lt;br /&gt;
Examples:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
   // Display a translated version of &amp;quot;My hand&amp;quot; at the place of the variable in the template&lt;br /&gt;
   $this-&amp;gt;tpl[&#039;MY_HAND&#039;] = self::_(&amp;quot;My hand&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
   // Display some raw HTML material at the place of the variable&lt;br /&gt;
   $this-&amp;gt;tpl[&#039;MY_HAND&#039;] = self::raw( &amp;quot;&amp;lt;div class=&#039;myhand_icon&#039;&amp;gt;&amp;lt;/div&amp;gt;&amp;quot; );&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
WARNING: do not use a variable called {id} as it will interfere with action buttons.&lt;br /&gt;
&lt;br /&gt;
WARNING: do not use a variable called {LB_[whatever]} as any variable starting with LB_ will interfere with the translation system.&lt;br /&gt;
&lt;br /&gt;
WARNING: do not use a variable called {ID} as it could receive unexpected values.&lt;br /&gt;
&lt;br /&gt;
== Template Blocks ==&lt;br /&gt;
&lt;br /&gt;
Using &amp;quot;blocks&amp;quot;, you can repeat a piece of HTML from your template several time.&lt;br /&gt;
&lt;br /&gt;
You should use &amp;quot;blocks&amp;quot; whenever you have a block of HTML that must be repeated many times. For example, for &#039;&#039;Reversi&#039;&#039;, we have to generate 64 (8x8) squares:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
(in reversi_reversi.tpl)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div id=&amp;quot;board&amp;quot;&amp;gt;&lt;br /&gt;
    &amp;lt;!-- BEGIN square --&amp;gt;&lt;br /&gt;
        &amp;lt;div id=&amp;quot;square_{X}_{Y}&amp;quot; class=&amp;quot;square&amp;quot; style=&amp;quot;left: {LEFT}px; top: {TOP}px;&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
    &amp;lt;!-- END square --&amp;gt;&lt;br /&gt;
    &lt;br /&gt;
    &amp;lt;div id=&amp;quot;discs&amp;quot;&amp;gt;&lt;br /&gt;
    &amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
(in reversi.view.php)&lt;br /&gt;
&lt;br /&gt;
 $this-&amp;gt;page-&amp;gt;begin_block( &amp;quot;reversi_reversi&amp;quot;, &amp;quot;square&amp;quot; );&lt;br /&gt;
        &lt;br /&gt;
 $hor_scale = 64.8;&lt;br /&gt;
 $ver_scale = 64.4;&lt;br /&gt;
 for( $x=1; $x&amp;lt;=8; $x++ ) {&lt;br /&gt;
    for( $y=1; $y&amp;lt;=8; $y++ ) {&lt;br /&gt;
       $this-&amp;gt;page-&amp;gt;insert_block( &amp;quot;square&amp;quot;, array(&lt;br /&gt;
         &#039;X&#039; =&amp;gt; $x,&lt;br /&gt;
         &#039;Y&#039; =&amp;gt; $y,&lt;br /&gt;
         &#039;LEFT&#039; =&amp;gt; round( ($x-1)*$hor_scale+10 ),&lt;br /&gt;
         &#039;TOP&#039; =&amp;gt; round( ($y-1)*$ver_scale+7 )&lt;br /&gt;
        ) );&lt;br /&gt;
    }        &lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Explanations:&lt;br /&gt;
* You specify a block in your template file, using &amp;quot;BEGIN&amp;quot; and &amp;quot;END&amp;quot; keywords as xml comment. In the example above, we are creating a block named &amp;quot;square&amp;quot;.&lt;br /&gt;
* In your view, you declare your block using &amp;quot;begin_block&amp;quot; method.&lt;br /&gt;
* Then, you can insert as many block as you want to, using &amp;quot;insert_block&amp;quot; method.&lt;br /&gt;
&lt;br /&gt;
The insert_block method takes 2 parameters:&lt;br /&gt;
* the name of the block to insert.&lt;br /&gt;
* an associative array you can use to assign values to template variables of this block. In the example above, there are 4 parameters in the block (X, Y, LEFT and TOP).&lt;br /&gt;
&lt;br /&gt;
== Nested blocks ==&lt;br /&gt;
&lt;br /&gt;
You can use nested blocks. In the example below, we are going to add a mini-board for each player of the game, with 4 card places on each of it:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
ggg_ggg.tpl file:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;!-- BEGIN player --&amp;gt;&lt;br /&gt;
    &amp;lt;div class=&amp;quot;miniboard&amp;quot; id=&amp;quot;miniboard_{PLAYER_ID}&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
        &amp;lt;div class=&amp;quot;card_places&amp;quot;&amp;gt;&lt;br /&gt;
            &amp;lt;!-- BEGIN card_place --&amp;gt;&lt;br /&gt;
            &amp;lt;div id=&amp;quot;card_place_{PLAYER_ID}_{PLACE_ID}&amp;quot;&amp;gt;&lt;br /&gt;
            &amp;lt;/div&amp;gt;&lt;br /&gt;
            &amp;lt;!-- END card_place --&amp;gt;&lt;br /&gt;
        &amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
    &amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;!-- END player --&amp;gt;&lt;br /&gt;
 &amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
ggg.view.php file:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$this-&amp;gt;page-&amp;gt;begin_block( &amp;quot;mygame_mygame.tpl&amp;quot;, &amp;quot;card_place&amp;quot; ); // Nested block must be declared first&lt;br /&gt;
$this-&amp;gt;page-&amp;gt;begin_block( &amp;quot;mygame_mygame.tpl&amp;quot;, &amp;quot;player&amp;quot; );&lt;br /&gt;
&lt;br /&gt;
foreach( $players as $player_id =&amp;gt; $player ) {&lt;br /&gt;
    // Important: nested block must be reset here, otherwise the second player miniboard will&lt;br /&gt;
    //  have 8 card_place, the third will have 12 card_place, and so one...&lt;br /&gt;
    $this-&amp;gt;page-&amp;gt;reset_subblocks( &#039;card_place&#039; ); &lt;br /&gt;
&lt;br /&gt;
    for( $i=1; $i&amp;lt;=4; $i++ ) {&lt;br /&gt;
       $this-&amp;gt;page-&amp;gt;insert_block( &amp;quot;card_place&amp;quot;, array( &lt;br /&gt;
             &#039;PLAYER_ID&#039; =&amp;gt; $player_id,&lt;br /&gt;
             &#039;PLACE_ID&#039; =&amp;gt; $i&lt;br /&gt;
          )&lt;br /&gt;
       );&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    $this-&amp;gt;page-&amp;gt;insert_block( &#039;player&#039;, array( &#039;PLAYER_ID&#039; =&amp;gt; $player_id );&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Conditional blocks ==&lt;br /&gt;
There is no if blocks but you can just have 2 blocks and make one to be &amp;quot;empty&amp;quot; i.e.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
            &amp;lt;!-- BEGIN a --&amp;gt;&lt;br /&gt;
            &amp;lt;div id=&amp;quot;something&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
            &amp;lt;!-- END a --&amp;gt;&lt;br /&gt;
            &amp;lt;!-- BEGIN not_a --&amp;gt;&lt;br /&gt;
            &amp;lt;div id=&amp;quot;something_else&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
            &amp;lt;!-- END not_a --&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
code in view.php&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    if ($condition_a) {&lt;br /&gt;
      // hide not_a&lt;br /&gt;
      $this-&amp;gt;page-&amp;gt;begin_block(&amp;quot;mygame_mygame.tpl&amp;quot;, &amp;quot;not_a&amp;quot;);&lt;br /&gt;
      $this-&amp;gt;page-&amp;gt;insert_template( &amp;quot;not_a&amp;quot;, &#039;&#039;, []);&lt;br /&gt;
    } else {&lt;br /&gt;
     // hide a&lt;br /&gt;
      $this-&amp;gt;page-&amp;gt;begin_block(&amp;quot;mygame_mygame.tpl&amp;quot;, &amp;quot;a&amp;quot;);&lt;br /&gt;
      $this-&amp;gt;page-&amp;gt;insert_template( &amp;quot;a&amp;quot;, &#039;&#039;, []);&lt;br /&gt;
    }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Note: if you need variable in these block do the insert_block on one that stays as usual&lt;br /&gt;
&lt;br /&gt;
== Javascript templates ==&lt;br /&gt;
&lt;br /&gt;
For game elements that come and go from the game area, we suggest you to define a Javascript template.&lt;br /&gt;
&lt;br /&gt;
These will allow to separate all html from javascript and php files and keep it strictly in template file.&lt;br /&gt;
&lt;br /&gt;
A Javascript template is defined in your template file like this:&lt;br /&gt;
&lt;br /&gt;
(Reversi Token from Reversi example):&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;script type=&amp;quot;text/javascript&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
// Templates&lt;br /&gt;
&lt;br /&gt;
var jstpl_disc=&#039;&amp;lt;div class=&amp;quot;disc disccolor_${color}&amp;quot; id=&amp;quot;disc_${xy}&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&#039;;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/script&amp;gt;  &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note: a section for javascript templates is already available at the end of your template skeleton file.&lt;br /&gt;
&lt;br /&gt;
Then, you can use this javascript template to insert this piece of HTML in your game interface, like this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    dojo.place( this.format_block( &#039;jstpl_disc&#039;, {&lt;br /&gt;
           xy: x+&#039;&#039;+y,&lt;br /&gt;
           color: color&lt;br /&gt;
    } ) , &#039;discs&#039; );&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
WARNING: always use lowercase for substitution variables in your Javascript templates, in order to avoid collision with phplib template variables (in particular, do not use ${ID}).&lt;br /&gt;
&lt;br /&gt;
Note that &#039;&#039;&#039;you must translate&#039;&#039;&#039; any text arguments passed to &#039;&#039;this.format_block()&#039;&#039; that will be rendered on the screen, for example [[Translations#On_client_side_.28Javascript.29|using &amp;quot;_()&amp;quot;]].&lt;br /&gt;
&lt;br /&gt;
== How to access game information from .view.php ==&lt;br /&gt;
&lt;br /&gt;
From your .view.php, you can access the following:&lt;br /&gt;
&lt;br /&gt;
=== Access current player id===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  global $g_user;&lt;br /&gt;
  $current_player_id = $g_user-&amp;gt;get_id();&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Access game object ===&lt;br /&gt;
&lt;br /&gt;
In your view file, &amp;lt;code&amp;gt;&amp;quot;$this-&amp;gt;game&amp;quot;&amp;lt;/code&amp;gt; contains an instance of your main game class.&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
   // Access to some game elements description described in your &amp;quot;material.inc.php&amp;quot;:&lt;br /&gt;
   $my_cards_types = $this-&amp;gt;game-&amp;gt;card_types;&lt;br /&gt;
&lt;br /&gt;
   // Access to any (public) method defined in my .game.php file:&lt;br /&gt;
   $result = $this-&amp;gt;game-&amp;gt;myMethod();&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Access spectator status ===&lt;br /&gt;
&lt;br /&gt;
For spectators (players who are not part of the game but just spectating it) you must be careful of displaying all public information, but no private information.&lt;br /&gt;
&lt;br /&gt;
In your view file, you can use &amp;lt;code&amp;gt;$this-&amp;gt;game-&amp;gt;isSpectator()&amp;lt;/code&amp;gt; to know if the player is not part of the game, and adapt the interface to this case.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Category:Studio]]&lt;/div&gt;</summary>
		<author><name>Sguzzer Gunayer</name></author>
	</entry>
	<entry>
		<id>https://en.doc.boardgamearena.com/index.php?title=Game_layout:_view_and_template:_yourgamename.view.php_and_yourgamename_yourgamename.tpl&amp;diff=22444</id>
		<title>Game layout: view and template: yourgamename.view.php and yourgamename yourgamename.tpl</title>
		<link rel="alternate" type="text/html" href="https://en.doc.boardgamearena.com/index.php?title=Game_layout:_view_and_template:_yourgamename.view.php_and_yourgamename_yourgamename.tpl&amp;diff=22444"/>
		<updated>2024-09-05T18:30:32Z</updated>

		<summary type="html">&lt;p&gt;Sguzzer Gunayer: /* Access game object */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Studio_Framework_Navigation}}&lt;br /&gt;
&lt;br /&gt;
== Overview ==&lt;br /&gt;
[[File:bga-pages-from-templates.PNG|700px]]&lt;br /&gt;
&lt;br /&gt;
There are two files involved in overall game layout: yourgamename.view.php and yourgamename_yourgamename.tpl.&lt;br /&gt;
&lt;br /&gt;
These files work together to provide the HTML layout of your game.&lt;br /&gt;
&lt;br /&gt;
Using these 2 files, you specify what HTML is rendered in your game client interface.&lt;br /&gt;
&lt;br /&gt;
In .tpl file you can directly write raw HTML that will be displayed by the browser.&lt;br /&gt;
&lt;br /&gt;
Example: extract of &amp;quot;hearts_hearts.tpl&amp;quot;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  &amp;lt;div id=&amp;quot;myhand_wrap&amp;quot; class=&amp;quot;whiteblock&amp;quot;&amp;gt;&lt;br /&gt;
    &amp;lt;h3&amp;gt;{MY_HAND}&amp;lt;/h3&amp;gt;&lt;br /&gt;
    &amp;lt;div id=&amp;quot;myhand&amp;quot;&amp;gt;&lt;br /&gt;
    &amp;lt;/div&amp;gt;&lt;br /&gt;
  &amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Things in curly braces are template variables. You cannot put any english text directly there.&lt;br /&gt;
&lt;br /&gt;
Your view and your template are supposed to generate only the BASE layout of the game.&lt;br /&gt;
&lt;br /&gt;
You shouldn&#039;t try to setup the current game situation in the view: this is the role of your Javascript code. Why? Because you&#039;ll have to write Javascript code to put game elements in place anyway, and you don&#039;t want to write it twice :)&lt;br /&gt;
&lt;br /&gt;
Example of things to generate in your view:&lt;br /&gt;
* The overall layout of your game interface (what is displayed where).&lt;br /&gt;
* The board and fixed elements on the board (ex: places for cards, squares, ...).&lt;br /&gt;
* The tokens which are always on the board (but JS code may move them around during setup)&lt;br /&gt;
&lt;br /&gt;
Example of things that shouldn&#039;t be generate by your view:&lt;br /&gt;
* Game elements that come and go from the game area.&lt;br /&gt;
* Game elements that normally hidden from players (other players cards, cards in the deck).&lt;br /&gt;
&lt;br /&gt;
== Template system ==&lt;br /&gt;
&lt;br /&gt;
BGA is using the phplib template system, used for example in PHPbb forums.&lt;br /&gt;
&lt;br /&gt;
More details about how to use phplib template system here:&lt;br /&gt;
https://web.archive.org/web/20170506065401/http://www.phpbuilder.com:80/columns/david20000512.php3&lt;br /&gt;
&lt;br /&gt;
== Variables ==&lt;br /&gt;
&lt;br /&gt;
In your template (.tpl) file, you can use variables. Then in your view (.view.php) file, you fill these variables with values.&lt;br /&gt;
&lt;br /&gt;
In the example above, &amp;quot;{MY_HAND}&amp;quot; is a variable. As you can see, a variable is uppercase characters surrounded by &amp;quot;{&amp;quot; and &amp;quot;}&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
This is example of how to assign values to these variables in .view.php:&lt;br /&gt;
&lt;br /&gt;
Examples:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
   // Display a translated version of &amp;quot;My hand&amp;quot; at the place of the variable in the template&lt;br /&gt;
   $this-&amp;gt;tpl[&#039;MY_HAND&#039;] = self::_(&amp;quot;My hand&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
   // Display some raw HTML material at the place of the variable&lt;br /&gt;
   $this-&amp;gt;tpl[&#039;MY_HAND&#039;] = self::raw( &amp;quot;&amp;lt;div class=&#039;myhand_icon&#039;&amp;gt;&amp;lt;/div&amp;gt;&amp;quot; );&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
WARNING: do not use a variable called {id} as it will interfere with action buttons.&lt;br /&gt;
&lt;br /&gt;
WARNING: do not use a variable called {LB_[whatever]} as any variable starting with LB_ will interfere with the translation system.&lt;br /&gt;
&lt;br /&gt;
WARNING: do not use a variable called {ID} as it could receive unexpected values.&lt;br /&gt;
&lt;br /&gt;
== Template Blocks ==&lt;br /&gt;
&lt;br /&gt;
Using &amp;quot;blocks&amp;quot;, you can repeat a piece of HTML from your template several time.&lt;br /&gt;
&lt;br /&gt;
You should use &amp;quot;blocks&amp;quot; whenever you have a block of HTML that must be repeated many times. For example, for &#039;&#039;Reversi&#039;&#039;, we have to generate 64 (8x8) squares:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
(in reversi_reversi.tpl)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div id=&amp;quot;board&amp;quot;&amp;gt;&lt;br /&gt;
    &amp;lt;!-- BEGIN square --&amp;gt;&lt;br /&gt;
        &amp;lt;div id=&amp;quot;square_{X}_{Y}&amp;quot; class=&amp;quot;square&amp;quot; style=&amp;quot;left: {LEFT}px; top: {TOP}px;&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
    &amp;lt;!-- END square --&amp;gt;&lt;br /&gt;
    &lt;br /&gt;
    &amp;lt;div id=&amp;quot;discs&amp;quot;&amp;gt;&lt;br /&gt;
    &amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
(in reversi.view.php)&lt;br /&gt;
&lt;br /&gt;
 $this-&amp;gt;page-&amp;gt;begin_block( &amp;quot;reversi_reversi&amp;quot;, &amp;quot;square&amp;quot; );&lt;br /&gt;
        &lt;br /&gt;
 $hor_scale = 64.8;&lt;br /&gt;
 $ver_scale = 64.4;&lt;br /&gt;
 for( $x=1; $x&amp;lt;=8; $x++ ) {&lt;br /&gt;
    for( $y=1; $y&amp;lt;=8; $y++ ) {&lt;br /&gt;
       $this-&amp;gt;page-&amp;gt;insert_block( &amp;quot;square&amp;quot;, array(&lt;br /&gt;
         &#039;X&#039; =&amp;gt; $x,&lt;br /&gt;
         &#039;Y&#039; =&amp;gt; $y,&lt;br /&gt;
         &#039;LEFT&#039; =&amp;gt; round( ($x-1)*$hor_scale+10 ),&lt;br /&gt;
         &#039;TOP&#039; =&amp;gt; round( ($y-1)*$ver_scale+7 )&lt;br /&gt;
        ) );&lt;br /&gt;
    }        &lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Explanations:&lt;br /&gt;
* You specify a block in your template file, using &amp;quot;BEGIN&amp;quot; and &amp;quot;END&amp;quot; keywords as xml comment. In the example above, we are creating a block named &amp;quot;square&amp;quot;.&lt;br /&gt;
* In your view, you declare your block using &amp;quot;begin_block&amp;quot; method.&lt;br /&gt;
* Then, you can insert as many block as you want to, using &amp;quot;insert_block&amp;quot; method.&lt;br /&gt;
&lt;br /&gt;
The insert_block method takes 2 parameters:&lt;br /&gt;
* the name of the block to insert.&lt;br /&gt;
* an associative array you can use to assign values to template variables of this block. In the example above, there are 4 parameters in the block (X, Y, LEFT and TOP).&lt;br /&gt;
&lt;br /&gt;
== Nested blocks ==&lt;br /&gt;
&lt;br /&gt;
You can use nested blocks. In the example below, we are going to add a mini-board for each player of the game, with 4 card places on each of it:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
ggg_ggg.tpl file:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;!-- BEGIN player --&amp;gt;&lt;br /&gt;
    &amp;lt;div class=&amp;quot;miniboard&amp;quot; id=&amp;quot;miniboard_{PLAYER_ID}&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
        &amp;lt;div class=&amp;quot;card_places&amp;quot;&amp;gt;&lt;br /&gt;
            &amp;lt;!-- BEGIN card_place --&amp;gt;&lt;br /&gt;
            &amp;lt;div id=&amp;quot;card_place_{PLAYER_ID}_{PLACE_ID}&amp;quot;&amp;gt;&lt;br /&gt;
            &amp;lt;/div&amp;gt;&lt;br /&gt;
            &amp;lt;!-- END card_place --&amp;gt;&lt;br /&gt;
        &amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
    &amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;!-- END player --&amp;gt;&lt;br /&gt;
 &amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
ggg.view.php file:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$this-&amp;gt;page-&amp;gt;begin_block( &amp;quot;mygame_mygame.tpl&amp;quot;, &amp;quot;card_place&amp;quot; ); // Nested block must be declared first&lt;br /&gt;
$this-&amp;gt;page-&amp;gt;begin_block( &amp;quot;mygame_mygame.tpl&amp;quot;, &amp;quot;player&amp;quot; );&lt;br /&gt;
&lt;br /&gt;
foreach( $players as $player_id =&amp;gt; $player ) {&lt;br /&gt;
    // Important: nested block must be reset here, otherwise the second player miniboard will&lt;br /&gt;
    //  have 8 card_place, the third will have 12 card_place, and so one...&lt;br /&gt;
    $this-&amp;gt;page-&amp;gt;reset_subblocks( &#039;card_place&#039; ); &lt;br /&gt;
&lt;br /&gt;
    for( $i=1; $i&amp;lt;=4; $i++ ) {&lt;br /&gt;
       $this-&amp;gt;page-&amp;gt;insert_block( &amp;quot;card_place&amp;quot;, array( &lt;br /&gt;
             &#039;PLAYER_ID&#039; =&amp;gt; $player_id,&lt;br /&gt;
             &#039;PLACE_ID&#039; =&amp;gt; $i&lt;br /&gt;
          )&lt;br /&gt;
       );&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    $this-&amp;gt;page-&amp;gt;insert_block( &#039;player&#039;, array( &#039;PLAYER_ID&#039; =&amp;gt; $player_id );&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Conditional blocks ==&lt;br /&gt;
There is no if blocks but you can just have 2 blocks and make one to be &amp;quot;empty&amp;quot; i.e.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
            &amp;lt;!-- BEGIN a --&amp;gt;&lt;br /&gt;
            &amp;lt;div id=&amp;quot;something&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
            &amp;lt;!-- END a --&amp;gt;&lt;br /&gt;
            &amp;lt;!-- BEGIN not_a --&amp;gt;&lt;br /&gt;
            &amp;lt;div id=&amp;quot;something_else&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
            &amp;lt;!-- END not_a --&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
code in view.php&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    if ($condition_a) {&lt;br /&gt;
      // hide not_a&lt;br /&gt;
      $this-&amp;gt;page-&amp;gt;begin_block(&amp;quot;mygame_mygame.tpl&amp;quot;, &amp;quot;not_a&amp;quot;);&lt;br /&gt;
      $this-&amp;gt;page-&amp;gt;insert_template( &amp;quot;not_a&amp;quot;, &#039;&#039;, []);&lt;br /&gt;
    } else {&lt;br /&gt;
     // hide a&lt;br /&gt;
      $this-&amp;gt;page-&amp;gt;begin_block(&amp;quot;mygame_mygame.tpl&amp;quot;, &amp;quot;a&amp;quot;);&lt;br /&gt;
      $this-&amp;gt;page-&amp;gt;insert_template( &amp;quot;a&amp;quot;, &#039;&#039;, []);&lt;br /&gt;
    }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Note: if you need variable in these block do the insert_block on one that stays as usual&lt;br /&gt;
&lt;br /&gt;
== Javascript templates ==&lt;br /&gt;
&lt;br /&gt;
For game elements that come and go from the game area, we suggest you to define a Javascript template.&lt;br /&gt;
&lt;br /&gt;
These will allow to separate all html from javascript and php files and keep it strictly in template file.&lt;br /&gt;
&lt;br /&gt;
A Javascript template is defined in your template file like this:&lt;br /&gt;
&lt;br /&gt;
(Reversi Token from Reversi example):&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;script type=&amp;quot;text/javascript&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
// Templates&lt;br /&gt;
&lt;br /&gt;
var jstpl_disc=&#039;&amp;lt;div class=&amp;quot;disc disccolor_${color}&amp;quot; id=&amp;quot;disc_${xy}&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&#039;;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/script&amp;gt;  &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note: a section for javascript templates is already available at the end of your template skeleton file.&lt;br /&gt;
&lt;br /&gt;
Then, you can use this javascript template to insert this piece of HTML in your game interface, like this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    dojo.place( this.format_block( &#039;jstpl_disc&#039;, {&lt;br /&gt;
           xy: x+&#039;&#039;+y,&lt;br /&gt;
           color: color&lt;br /&gt;
    } ) , &#039;discs&#039; );&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
WARNING: always use lowercase for substitution variables in your Javascript templates, in order to avoid collision with phplib template variables (in particular, do not use ${ID}).&lt;br /&gt;
&lt;br /&gt;
Note that &#039;&#039;&#039;you must translate&#039;&#039;&#039; any text arguments passed to &#039;&#039;this.format_block()&#039;&#039; that will be rendered on the screen, for example [[Translations#On_client_side_.28Javascript.29|using &amp;quot;_()&amp;quot;]].&lt;br /&gt;
&lt;br /&gt;
== How to access game information from .view.php ==&lt;br /&gt;
&lt;br /&gt;
From your .view.php, you can access the following:&lt;br /&gt;
&lt;br /&gt;
=== Access current player id===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  global $g_user;&lt;br /&gt;
  $current_player_id = $g_user-&amp;gt;get_id();&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Access game object ===&lt;br /&gt;
&lt;br /&gt;
In your view file, &amp;lt;code&amp;gt;&amp;quot;$this-&amp;gt;game&amp;quot;&amp;lt;/code&amp;gt; contains an instance of your main game class.&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
   // Access to some game elements description described in your &amp;quot;material.inc.php&amp;quot;:&lt;br /&gt;
   $my_cards_types = $this-&amp;gt;game-&amp;gt;card_types;&lt;br /&gt;
&lt;br /&gt;
   // Access to any (public) method defined in my .game.php file:&lt;br /&gt;
   $result = $this-&amp;gt;game-&amp;gt;myMethod();&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Access spectator status ===&lt;br /&gt;
&lt;br /&gt;
For spectators (players who are not part of the game but just spectating it) you must be careful of displaying all public information, but no private information.&lt;br /&gt;
&lt;br /&gt;
In your view file, you can use $this-&amp;gt;game-&amp;gt;isSpectator() to know if the player is not part of the game, and adapt the interface to this case.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Category:Studio]]&lt;/div&gt;</summary>
		<author><name>Sguzzer Gunayer</name></author>
	</entry>
	<entry>
		<id>https://en.doc.boardgamearena.com/index.php?title=Tutorial_reversi&amp;diff=22419</id>
		<title>Tutorial reversi</title>
		<link rel="alternate" type="text/html" href="https://en.doc.boardgamearena.com/index.php?title=Tutorial_reversi&amp;diff=22419"/>
		<updated>2024-09-03T15:03:40Z</updated>

		<summary type="html">&lt;p&gt;Sguzzer Gunayer: /* Build your States */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&#039;&#039;&#039;Check out an update version&#039;&#039;&#039; of the [[BGA Type Safe Template: Reversi|Reversi Tutorial]] which uses the [[BGA Type Safe Template]]. {{Studio_Framework_Navigation}}&lt;br /&gt;
&lt;br /&gt;
== Introduction ==&lt;br /&gt;
&lt;br /&gt;
Using this tutorial, you can build a complete working game on the BGA environment: Reversi.&lt;br /&gt;
&lt;br /&gt;
Before you read this tutorial, you must:&lt;br /&gt;
* Read the overall presentations of the BGA Framework ([[Studio|see here]]).&lt;br /&gt;
* Know the [http://en.wikipedia.org/wiki/Reversi#Rules rules of Reversi].&lt;br /&gt;
* Know the languages used on BGA: PHP, SQL, HTML, CSS, Javascript&lt;br /&gt;
* &#039;&#039;&#039;Setup your development environment&#039;&#039;&#039; [http://en.doc.boardgamearena.com/First_steps_with_BGA_Studio First Steps with BGA Studio]&lt;br /&gt;
&lt;br /&gt;
== Create your first game ==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Note: you should already have created a project following instructions in [[First_steps_with_BGA_Studio#Create_a_new_game_project|Create a new game project]]. While you will find a &#039;&#039;&#039;reversi&#039;&#039;&#039; directory in your SFTP folder, do not use it for this tutorial. Instead, use the project you have created as an (empty) starting point.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
With the initial skeleton of code provided in your project, you can already start a game from the BGA Studio:&lt;br /&gt;
* Go to your [https://studio.boardgamearena.com/controlpanel studio Control panel], then Manage games and select your initial project. &#039;&#039;Note: there are warnings displayed about a missing BGG_ID and presentation text. You can ignore that for now.&#039;&#039;&lt;br /&gt;
* Click the Play link next to your project name. This will open the Play page and offer to create a new table for your project. &#039;&#039;Optional: click the Heart icon to add your project to your favorite games list.&#039;&#039;&lt;br /&gt;
* On the Play page, on the top of the page, make sure that your settings are &amp;quot;Simple game&amp;quot;, &amp;quot;Real time&amp;quot; and &amp;quot;Manual&amp;quot;.&lt;br /&gt;
* Click &amp;quot;Create table&amp;quot; to create a table of your project. &lt;br /&gt;
* For now, we are going to work with one player only, so use the (-) button to set the number of players to 1. Most of the time it is simpler to proceed with only one player during the early phase of development of your game, as it&#039;s easy and fast to start/stop games. If you choose to start with 2 players, you should see two names on the right: testdude0 and testdude1. To switch between them, press the red arrow button near their names; it will open another tab. This way you don&#039;t need to login and logout from multiple accounts.) &lt;br /&gt;
* Reminder: Always use the &amp;quot;Express Start&amp;quot; button to start the game.&lt;br /&gt;
&lt;br /&gt;
Thus, you can start a &amp;quot;Reversi&amp;quot; game, and arrive on a void, empty game. Yeah.&lt;br /&gt;
&lt;br /&gt;
End the game by clicking on the game options icon on the top right, and then on &amp;quot;Express Stop&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
== Editing the game information (Optional) ==&lt;br /&gt;
&lt;br /&gt;
This step is optional and will fix the warnings on the project page (missing BGG_ID and presentation).&lt;br /&gt;
&lt;br /&gt;
==== Edits to fix Errors ====&lt;br /&gt;
* Edit your local copy of the &amp;lt;code&amp;gt;gameinfos.inc.php&amp;lt;/code&amp;gt; file:&lt;br /&gt;
** Change the &amp;lt;code&amp;gt;bgg_id&amp;lt;/code&amp;gt; value from &amp;lt;code&amp;gt;0&amp;lt;/code&amp;gt; to &amp;lt;code&amp;gt;2389&amp;lt;/code&amp;gt; - that&#039;s around line 37.&lt;br /&gt;
** Add &amp;lt;code&amp;gt;1,&amp;lt;/code&amp;gt; to the players array - that&#039;s around line 41.&lt;br /&gt;
** Change the presentation array content - that&#039;s around line 134. Uncomment one line and change the text. Remove the final comma if you keep only one line!&lt;br /&gt;
* Upload the &amp;lt;code&amp;gt;gameinfos.inc.php&amp;lt;/code&amp;gt; file to the SFTP server (see [[First_steps_with_BGA_Studio#Connect_to_your_SFTP_folder|Connect to your SFTP folder]]).&lt;br /&gt;
&lt;br /&gt;
==== Test your Edits ====&lt;br /&gt;
* Go back to your project page, and in the &amp;quot;Game Information&amp;quot; section, click &amp;quot;Reload game informations&amp;quot;.&lt;br /&gt;
* Finally, refresh the project page in your browser (usually CTRL-F5).&lt;br /&gt;
&lt;br /&gt;
===== Not working? =====&lt;br /&gt;
Some changes will require bypassing the cache. It is often worth doing a hard refresh to make sure the&lt;br /&gt;
&lt;br /&gt;
Sometimes the cache will keep your changes from showing. Since this is a possibility, it will be useful to know how to bypass the cache. To do so you may manually clear cache or use a shortcut to refresh and ignore the cached version of the page. Here&#039;s how&lt;br /&gt;
&lt;br /&gt;
====== Windows ======&lt;br /&gt;
Chrome, Firefox, or Edge: Press &amp;lt;code&amp;gt;Ctrl+F5&amp;lt;/code&amp;gt; or &amp;lt;code&amp;gt;Shift+F5&amp;lt;/code&amp;gt; or &amp;lt;code&amp;gt;Ctrl+Shift+R&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====== Mac ======&lt;br /&gt;
Chrome or Firefox: Press &amp;lt;code&amp;gt;Shift+Command+R&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Safari for Mac: Press &amp;lt;code&amp;gt;Command+Option+E&amp;lt;/code&amp;gt; to empty the cache, then hold down Shift and click Reload in the toolbar&lt;br /&gt;
&lt;br /&gt;
== Make it look like Reversi ==&lt;br /&gt;
&lt;br /&gt;
Let&#039;s start with the board. This will give you a good idea of how things will look and where tokens should go.&lt;br /&gt;
&lt;br /&gt;
Be careful designing the layout of your game: you must always keep in mind that players with a 1024px screen width must be able to play. Usually, it means that the width of the play area can be 750px (in the worst case).&lt;br /&gt;
&lt;br /&gt;
For Reversi, it&#039;s useless to have a 750x750px board - much too big, so we chose this one which fit perfectly (536x528):&lt;br /&gt;
&lt;br /&gt;
[[File:Board.jpg]]&lt;br /&gt;
&lt;br /&gt;
Note that we are using a jpg file. Jpg files are lighter than png, so they are faster to load. Later, we are going to use PNGs for tokens because they allow for transparency.&lt;br /&gt;
&lt;br /&gt;
==== Add the board ====&lt;br /&gt;
use lowercase file names&lt;br /&gt;
* upload &amp;lt;code&amp;gt;board.jpg&amp;lt;/code&amp;gt; in your &amp;lt;code&amp;gt;img/&amp;lt;/code&amp;gt; directory. &lt;br /&gt;
* edit &amp;lt;code&amp;gt;reversi_reversi.tpl&amp;lt;/code&amp;gt; to add a &amp;lt;code&amp;gt;div&amp;lt;/code&amp;gt; for your board.&lt;br /&gt;
&lt;br /&gt;
Note: If you are building this game by following the tutorial, you will have a different project name than &amp;lt;code&amp;gt;reversi&amp;lt;/code&amp;gt; (i.e. &amp;lt;code&amp;gt;mygame_mygame.tpl&amp;lt;/code&amp;gt;). The file names in your project will be different than shown in this tutorial, replacing &amp;lt;code&amp;gt;reversi&amp;lt;/code&amp;gt; with your project name. Be sure that any code (other than comments) that references &amp;lt;code&amp;gt;reversi&amp;lt;/code&amp;gt; is changed to your actual project name.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;div id=&amp;quot;board&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* edit your &amp;lt;code&amp;gt;reversi.css&amp;lt;/code&amp;gt; file to transform it into a visible board:&lt;br /&gt;
&lt;br /&gt;
 #board {&lt;br /&gt;
    width: 536px;&lt;br /&gt;
    height: 528px;&lt;br /&gt;
    background-image: url(&#039;img/board.jpg&#039;);&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Important: refresh your page.&#039;&#039;&#039; Here&#039;s your board:[[File:reversi1.jpg]]&lt;br /&gt;
&lt;br /&gt;
If the board does not appear, refresh the page (always do this when you update the CSS file), and check the image filename. Remember file names are case sensitive!&lt;br /&gt;
&lt;br /&gt;
==== Code the Grid ====&lt;br /&gt;
Now, we need to create some invisible HTML elements where squares are. These elements will be used as position references for the white and black tokens. &lt;br /&gt;
&lt;br /&gt;
===== Build the grid of squares =====&lt;br /&gt;
The board is 8 squares by 8 squares. This means we need 64 squares. To avoid writing 64 individual &amp;lt;code&amp;gt;div&amp;lt;/code&amp;gt; elements on our template, we are going to generate the squares on JS setup.&lt;br /&gt;
&lt;br /&gt;
We&#039;ll do this in our Javascript &amp;lt;code&amp;gt;setup&amp;lt;/code&amp;gt; method under &amp;lt;code&amp;gt;// TODO: Set up your game interface here, according to &amp;quot;gamedatas&amp;quot;&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
const board = document.getElementById(&#039;board&#039;);&lt;br /&gt;
const hor_scale = 64.8;&lt;br /&gt;
const ver_scale = 64.4;&lt;br /&gt;
for (let x=1; x&amp;lt;=8; x++) {&lt;br /&gt;
    for (let y=1; y&amp;lt;=8; y++) {&lt;br /&gt;
        const left = Math.round((x - 1) * hor_scale + 10);&lt;br /&gt;
        const top = Math.round((y - 1) * ver_scale + 7);&lt;br /&gt;
        // we use afterbegin to make sure squares are placed before discs&lt;br /&gt;
        board.insertAdjacentHTML(`afterbegin`, `&amp;lt;div id=&amp;quot;square_${x}_${y}&amp;quot; class=&amp;quot;square&amp;quot; style=&amp;quot;left: ${left}px; top: ${top}px;&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;`);&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note: as you can see, squares in our &amp;lt;code&amp;gt;board.jpg&amp;lt;/code&amp;gt; files do not have an exact width/height in pixels, and that&#039;s the reason we are using floating point numbers here.&lt;br /&gt;
&lt;br /&gt;
===== Style Those Squares =====&lt;br /&gt;
Now, to finish our work and check if everything works fine, we are going to style our square a little bit in our CSS stylesheet:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#board {&lt;br /&gt;
    width: 536px;&lt;br /&gt;
    height: 528px;&lt;br /&gt;
    background-image: url(&#039;img/board.jpg&#039;);&lt;br /&gt;
    position: relative;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.square {&lt;br /&gt;
    width: 62px;&lt;br /&gt;
    height: 62px;&lt;br /&gt;
    position: absolute;&lt;br /&gt;
    background-color: red;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Explanations:&lt;br /&gt;
* With &amp;quot;position: relative&amp;quot; on board, we ensure square elements are positioned relatively to board.&lt;br /&gt;
* &amp;lt;code&amp;gt;background-color: red;&amp;lt;/code&amp;gt; is used for testing. This allows us to see the invisible elements. (You could instead do something like &amp;lt;code&amp;gt;outline: 2px solid orange;&amp;lt;/code&amp;gt; have fun and be creative)&lt;br /&gt;
&lt;br /&gt;
Let&#039;s refresh and check our (beautiful) squares:&lt;br /&gt;
&lt;br /&gt;
[[File:reversi2.jpg]]&lt;br /&gt;
&lt;br /&gt;
Now that you know the squares are there, you can remove the test line &amp;lt;code&amp;gt;background-color: red;&amp;lt;/code&amp;gt;  from your &amp;lt;code&amp;gt;.square&amp;lt;/code&amp;gt; class in the CSS stylesheet.&lt;br /&gt;
&lt;br /&gt;
===== Not Working? =====&lt;br /&gt;
If the styled squares do not appear, inspect and check your css (Chrome DevTools: Application &amp;gt; Frames &amp;gt; top &amp;gt; Stylesheets &amp;gt; reversi.css). &lt;br /&gt;
&lt;br /&gt;
== The Tokens ==&lt;br /&gt;
&lt;br /&gt;
Now, our board is ready for some tokens!&lt;br /&gt;
&lt;br /&gt;
[Note: Throughout this tutorial, sometimes &amp;quot;tokens&amp;quot; is used, and sometimes &amp;quot;discs&amp;quot; is used. They are often swapped if you&#039;re looking at code in the reversi example project.]&lt;br /&gt;
&lt;br /&gt;
=== Build the Token ===&lt;br /&gt;
There are quite a few steps before the tokens will appear. You may be used to testing after every change, but that won&#039;t work well here. The token will &#039;&#039;&#039;not&#039;&#039;&#039; show until you have add styles to the css, js template to the tpl, utility method in the js,  adjusted the php file, and added the token to the board in the js file.&lt;br /&gt;
&lt;br /&gt;
==== HTML in the .tpl file ====&lt;br /&gt;
At first, we introduce a new &#039;div&#039; element as a child of &amp;quot;board&amp;quot; to host all these tokens (in our template):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;div id=&amp;quot;board&amp;quot;&amp;gt;&lt;br /&gt;
    &lt;br /&gt;
    &amp;lt;div id=&amp;quot;discs&amp;quot;&amp;gt;&lt;br /&gt;
    &amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note: &amp;lt;code&amp;gt;discs&amp;lt;/code&amp;gt; is plural. This div will be used to hold the token divs. Shortly, we will use javascript to add individual tokens to the board.&lt;br /&gt;
&lt;br /&gt;
==== Add Token to img directory ====&lt;br /&gt;
Here&#039;s a new piece of art with the tokens. We need transparency here so we are using a png file:&lt;br /&gt;
&lt;br /&gt;
[[File:tokens.png]]&lt;br /&gt;
&lt;br /&gt;
Upload this image file &amp;lt;code&amp;gt;tokens.png&amp;lt;/code&amp;gt; in your &amp;lt;code&amp;gt;img/&amp;lt;/code&amp;gt; directory.&lt;br /&gt;
&lt;br /&gt;
Important Fun Fact: we are using ONE file for both tokens. It is really important to use a minimum number of graphic files for your game. This is called the &amp;quot;CSS sprite&amp;quot; technique, because it makes the game load faster and more reliable. [http://www.w3schools.com/css/css_image_sprites.asp Read more about CSS sprites].&lt;br /&gt;
&lt;br /&gt;
==== Style the Tokens in .css file ====&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
.disc {&lt;br /&gt;
    width: 56px;&lt;br /&gt;
    height: 56px;&lt;br /&gt;
    position: absolute;&lt;br /&gt;
    background-image: url(&#039;img/tokens.png&#039;);&lt;br /&gt;
    background-size: auto 100%;&lt;br /&gt;
}&lt;br /&gt;
.disc[data-color=&amp;quot;ffffff&amp;quot;] { background-position-x: 0%; }&lt;br /&gt;
.disc[data-color=&amp;quot;000000&amp;quot;] { background-position-x: 100%; }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
With this CSS code, we can set and change the token color by changing the data-color attribute. Using data instead of a class ensures it can be only one of them (the disc cannot be black and white at the same time).&lt;br /&gt;
&lt;br /&gt;
Note the &amp;quot;&amp;lt;code&amp;gt;position: absolute&amp;lt;/code&amp;gt;&amp;quot; which allows us to position tokens on the board and make them &amp;quot;slide&amp;quot; to their positions.&lt;br /&gt;
&lt;br /&gt;
==== Add Token Utility Method in .js file ====&lt;br /&gt;
Now, let&#039;s make the first token appear on our board. Tokens are not visible at the beginning of the game: they appear dynamically during the game. For this reason, we are going to make them appear from our Javascript code, using a template string&lt;br /&gt;
&lt;br /&gt;
Let&#039;s create a method in our Javascript code (in the &amp;lt;code&amp;gt;reversi.js&amp;lt;/code&amp;gt; file) that will make a token appear on the board, using this template. Add under the section //// Utility methods:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
addDiscOnBoard: function( x, y, player )&lt;br /&gt;
{&lt;br /&gt;
    var color = this.gamedatas.players[ player ].color;&lt;br /&gt;
    &lt;br /&gt;
    document.getElementById(&#039;discs&#039;).insertAdjacentHTML(&#039;beforeend&#039;, `&amp;lt;div class=&amp;quot;disc&amp;quot; data-color=&amp;quot;${color}&amp;quot; id=&amp;quot;disc_${x}${y}&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;`);&lt;br /&gt;
    &lt;br /&gt;
    this.placeOnObject( `disc_${x}${y}`, &#039;overall_player_board_&#039;+player );&lt;br /&gt;
    this.slideToObject( `disc_${x}${y}`, &#039;square_&#039;+x+&#039;_&#039;+y ).play();&lt;br /&gt;
},  &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===== Utility Method Explanation =====&lt;br /&gt;
* with &amp;lt;code&amp;gt;element.insertAdjacentHTML&amp;lt;/code&amp;gt; method, we create a HTML piece of code and insert it as a new child of &amp;lt;code&amp;gt;tokens&amp;lt;/code&amp;gt; div element.&lt;br /&gt;
* with &amp;lt;code&amp;gt;this.placeOnObject&amp;lt;/code&amp;gt; BGA method, we place this element over the panel of some player. &lt;br /&gt;
* Immediately after, using &amp;lt;code&amp;gt;this.slideToObject&amp;lt;/code&amp;gt; BGA method, we make the token slide to the &amp;lt;code&amp;gt;square&amp;lt;/code&amp;gt; element, its final destination.&lt;br /&gt;
* &amp;lt;code&amp;gt;&#039;overall_player_board_&#039;+player&amp;lt;/code&amp;gt; refers to the div element that contains each player&#039;s information and avatar. By initially placing the token here, it gives the effect that the player&#039;s avatar is throwing the token onto the board.&lt;br /&gt;
&lt;br /&gt;
Note: don&#039;t forget to call the &amp;lt;code&amp;gt;play()&amp;lt;/code&amp;gt;, otherwise the token will remain at its original location.&lt;br /&gt;
&lt;br /&gt;
Note: during this process, the parent of the new token HTML element will stay &amp;lt;code&amp;gt;tokens&amp;lt;/code&amp;gt;. &amp;lt;code&amp;gt;placeOnObject&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;slideToObject&amp;lt;/code&amp;gt; methods are &#039;&#039;only&#039;&#039; moving the position of elements on screen, and they are &#039;&#039;not&#039;&#039; modifying the HTML tree.&lt;br /&gt;
&lt;br /&gt;
==== Set Token Colors in setupNewGame in .game.php file ====&lt;br /&gt;
Before we can show a token, we need to set the player colors in the &amp;lt;code&amp;gt;setupNewGame&amp;lt;/code&amp;gt; function in &amp;lt;code&amp;gt;reversi.game.php&amp;lt;/code&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
Replace &amp;lt;code&amp;gt;$default_colors = $gameinfos[&#039;player_colors&#039;];&amp;lt;/code&amp;gt; with the following line:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        $default_colors = array( &amp;quot;ffffff&amp;quot;, &amp;quot;000000&amp;quot; );&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note: A few lines below, you may have to remove the line &amp;lt;code&amp;gt;this-&amp;gt;reattributeColorsBasedOnPreferences( $players, $gameinfos[&#039;player_colors&#039;] );&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Test the Token ===&lt;br /&gt;
Now, to test if everything works fine&lt;br /&gt;
&lt;br /&gt;
==== addTokenOnBoard() in .js file to Test ====&lt;br /&gt;
In &amp;lt;code&amp;gt;reversi.js&amp;lt;/code&amp;gt;, in &amp;lt;code&amp;gt;setup: function&amp;lt;/code&amp;gt;, under the code we added to generate the squares. &lt;br /&gt;
 this.addDiscOnBoard( 2, 2, this.player_id );&lt;br /&gt;
Now restart the game.&lt;br /&gt;
&lt;br /&gt;
A token should appear and slide immediately to its position, like this:&lt;br /&gt;
&lt;br /&gt;
[[File:reversi3.jpg]]&lt;br /&gt;
&lt;br /&gt;
== The database ==&lt;br /&gt;
&lt;br /&gt;
We did most of the client-side programming, so let&#039;s have a look on the other side now. To design the database model of our game, you will need to access the database. You won&#039;t need to do anything in database UI, yet.&lt;br /&gt;
&lt;br /&gt;
=== Accessing the Database ===&lt;br /&gt;
To access the database, start a game, then click &amp;quot;Go to game database&amp;quot; link at the bottom of our game, to access the database directly with a PhpMyAdmin instance.&lt;br /&gt;
&lt;br /&gt;
After the first time you&#039;ve acess the database, you could skip opening a game and instead, go to https://studio.boardgamearena.com/db/ . Your PhpMyAdmin username/password is in your welcome email.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note&#039;&#039;&#039;: do not remove existing tables&lt;br /&gt;
&lt;br /&gt;
=== Create Table in .sql file ===&lt;br /&gt;
Now, you are able to create the table(s) you need for your game, and report every SQL command used in your &amp;lt;code&amp;gt;dbmodel.sql&amp;lt;/code&amp;gt; file. &lt;br /&gt;
&lt;br /&gt;
The database model of Reversi is short: just one table with the squares of the board. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
CREATE TABLE IF NOT EXISTS `board` (&lt;br /&gt;
  `board_x` smallint(5) unsigned NOT NULL,&lt;br /&gt;
  `board_y` smallint(5) unsigned NOT NULL,&lt;br /&gt;
  `board_player` int(10) unsigned DEFAULT NULL,&lt;br /&gt;
  PRIMARY KEY (`board_x`,`board_y`)&lt;br /&gt;
) ENGINE=InnoDB DEFAULT CHARSET=utf8;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Add the above SQL to &amp;lt;code&amp;gt;dbmodel.sql&amp;lt;/code&amp;gt;. Pay special attention to the backtick &amp;lt;code&amp;gt;`&amp;lt;/code&amp;gt; character vs. the single quote &amp;lt;code&amp;gt;&#039;&amp;lt;/code&amp;gt; when working with SQL. &lt;br /&gt;
&lt;br /&gt;
=== Test the Table ===&lt;br /&gt;
Now, a new database with a &amp;lt;code&amp;gt;board&amp;lt;/code&amp;gt; table will be created each time we start a Reversi game. This is why after modifying our &amp;lt;code&amp;gt;dbmodel.sql&amp;lt;/code&amp;gt; it&#039;s a good time to stop your current game &amp;amp; start a new game.&lt;br /&gt;
&lt;br /&gt;
Start a new game and verify a table is created.&lt;br /&gt;
&lt;br /&gt;
== Setup the initial game position ==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note&#039;&#039;&#039;: From now on, you must launch the game with &#039;&#039;&#039;two players&#039;&#039;&#039; to get two &amp;lt;code&amp;gt;player_id&amp;lt;/code&amp;gt;s within the database. Otherwise, the game will crash.&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;setupNewGame&amp;lt;/code&amp;gt; method of our &amp;lt;code&amp;gt;reversi.game.php&amp;lt;/code&amp;gt; is called during initial setup. This initializes our data and places the starting tokens on the board. At the beginning of the game, there should be 4 tokens on the board.&lt;br /&gt;
&lt;br /&gt;
=== Initialize the Board in .game.php file ===&lt;br /&gt;
Under &amp;lt;code&amp;gt;// TODO: setup the initial game situation here&amp;lt;/code&amp;gt;, initialize the board&amp;lt;pre&amp;gt;&lt;br /&gt;
        // Init the board&lt;br /&gt;
        $sql = &amp;quot;INSERT INTO board (board_x,board_y,board_player) VALUES &amp;quot;;&lt;br /&gt;
        $sql_values = array();&lt;br /&gt;
        list( $blackplayer_id, $whiteplayer_id ) = array_keys( $players );&lt;br /&gt;
        for( $x=1; $x&amp;lt;=8; $x++ )&lt;br /&gt;
        {&lt;br /&gt;
            for( $y=1; $y&amp;lt;=8; $y++ )&lt;br /&gt;
            {&lt;br /&gt;
                $token_value = &amp;quot;NULL&amp;quot;;&lt;br /&gt;
                if( ($x==4 &amp;amp;&amp;amp; $y==4) || ($x==5 &amp;amp;&amp;amp; $y==5) )  // Initial positions of white player&lt;br /&gt;
                    $token_value = &amp;quot;&#039;$whiteplayer_id&#039;&amp;quot;;&lt;br /&gt;
                else if( ($x==4 &amp;amp;&amp;amp; $y==5) || ($x==5 &amp;amp;&amp;amp; $y==4) )  // Initial positions of black player&lt;br /&gt;
                    $token_value = &amp;quot;&#039;$blackplayer_id&#039;&amp;quot;;&lt;br /&gt;
                    &lt;br /&gt;
                $sql_values[] = &amp;quot;(&#039;$x&#039;,&#039;$y&#039;,$token_value)&amp;quot;;&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
        $sql .= implode( &#039;,&#039;, $sql_values );&lt;br /&gt;
        $this-&amp;gt;DbQuery( $sql );&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Board Initialization Explanation ====&lt;br /&gt;
&lt;br /&gt;
* We create one table entry for each square, with a &amp;lt;code&amp;gt;NULL&amp;lt;/code&amp;gt; value which means &amp;quot;empty square&amp;quot;&lt;br /&gt;
* On 4 of the squares, we place an initial token.&lt;br /&gt;
&lt;br /&gt;
After this, we set &amp;lt;code&amp;gt;activeNextPlayer&amp;lt;/code&amp;gt; to make the first player active at the beginning of the game (this line is already present in the default code template).&lt;br /&gt;
&lt;br /&gt;
If you didn&#039;t do it earlier, you need to remove the call to &amp;lt;code&amp;gt;this-&amp;gt;reattributeColorsBasedOnPreferences()&amp;lt;/code&amp;gt; in &amp;lt;code&amp;gt;SetupNewGame()&amp;lt;/code&amp;gt;. If you don&#039;t, player color preferences will try (and fail) to override the two colors supported here.&lt;br /&gt;
&lt;br /&gt;
=== Show the Initial Token Setup ===&lt;br /&gt;
Now, we need to make these tokens appear on the client side. The first step is to return the token positions with our &amp;lt;code&amp;gt;getAllDatas()&amp;lt;/code&amp;gt; PHP method. &amp;lt;code&amp;gt;getAllDatas()&amp;lt;/code&amp;gt; is called during each page reload.&lt;br /&gt;
&lt;br /&gt;
In the &amp;lt;code&amp;gt;getAllDatas()&amp;lt;/code&amp;gt; method, after &amp;lt;code&amp;gt;// TODO: Gather all information about current game situation (visible by player $current_player_id)&amp;lt;/code&amp;gt;, add the following lines:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        // Get reversi board token&lt;br /&gt;
        $result[&#039;board&#039;] = self::getObjectListFromDB( &amp;quot;SELECT board_x x, board_y y, board_player player&lt;br /&gt;
                                                       FROM board&lt;br /&gt;
                                                       WHERE board_player IS NOT NULL&amp;quot; );&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Next, you may need to modify the query that gets player information to also get the player&#039;s colors. This is in the variable &amp;lt;code&amp;gt;$sql&amp;lt;/code&amp;gt;, above the lines you just inserted in &amp;lt;code&amp;gt;getAllDatas()&amp;lt;/code&amp;gt;. Below is what the line will look like. Notice how we&#039;ve added &amp;lt;code&amp;gt;player_color color&amp;lt;/code&amp;gt; to the sql query.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$sql = &amp;quot;SELECT player_id id, player_score score, player_color color FROM player &amp;quot;;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
We are using the BGA framework&#039;s &amp;lt;code&amp;gt;getObjectListFromDB()&amp;lt;/code&amp;gt; that formats the result of this SQL query in a PHP array with x, y and player attributes. We add it to the result associative array with the key &amp;lt;code&amp;gt;board&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Last, we process this array client side. Let&#039;s place a token on the board for each array item. We&#039;ll do this in our Javascript &amp;lt;code&amp;gt;setup&amp;lt;/code&amp;gt; method under the code we added to generate the squares. &lt;br /&gt;
&lt;br /&gt;
This will result in a removal or edit of the previously added line &amp;lt;code&amp;gt;this.addDiscOnBoard(2, 2, this.player_id);&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
for( var i in gamedatas.board )&lt;br /&gt;
{&lt;br /&gt;
    var square = gamedatas.board[i];&lt;br /&gt;
    &lt;br /&gt;
    if( square.player !== null )&lt;br /&gt;
    {&lt;br /&gt;
        this.addDiscOnBoard( square.x, square.y, square.player );&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;board&amp;lt;/code&amp;gt; entry created in &amp;lt;code&amp;gt;getAllDatas()&amp;lt;/code&amp;gt; is used here as &amp;lt;code&amp;gt;gamedatas.board&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Test the Game Start ===&lt;br /&gt;
Reload... and here we are:&lt;br /&gt;
&lt;br /&gt;
[[File:reversi5.jpg]]&lt;br /&gt;
&lt;br /&gt;
It starts to feel like Reversi here...&lt;br /&gt;
&lt;br /&gt;
== The game state machine ==&lt;br /&gt;
&lt;br /&gt;
Stop your game, again. You&#039;re about to start the core game logic.&lt;br /&gt;
&lt;br /&gt;
You already read [http://www.slideshare.net/boardgamearena/bga-studio-focus-on-bga-game-state-machine Focus on BGA game state machine], so you know that this is the heart of your game logic. For reversi, it&#039;s relatively simple. Here&#039;s a diagram of our game state machine:&lt;br /&gt;
&lt;br /&gt;
[[File:reversi6.jpg]]&lt;br /&gt;
&lt;br /&gt;
=== Build your States ===&lt;br /&gt;
And here&#039;s our &amp;lt;code&amp;gt;states.inc.php&amp;lt;/code&amp;gt;, according to this diagram:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$machinestates = array(&lt;br /&gt;
&lt;br /&gt;
    ST_BGA_GAME_SETUP =&amp;gt; array(&lt;br /&gt;
        &amp;quot;name&amp;quot; =&amp;gt; &amp;quot;gameSetup&amp;quot;,&lt;br /&gt;
        &amp;quot;description&amp;quot; =&amp;gt; clienttranslate(&amp;quot;Game setup&amp;quot;),&lt;br /&gt;
        &amp;quot;type&amp;quot; =&amp;gt; &amp;quot;manager&amp;quot;,&lt;br /&gt;
        &amp;quot;action&amp;quot; =&amp;gt; &amp;quot;stGameSetup&amp;quot;,&lt;br /&gt;
        &amp;quot;transitions&amp;quot; =&amp;gt; array( &amp;quot;&amp;quot; =&amp;gt; ST_PLAYER_PLAY_DISC )&lt;br /&gt;
    ),&lt;br /&gt;
    &lt;br /&gt;
    ST_PLAYER_PLAY_DISC =&amp;gt; array(&lt;br /&gt;
        &amp;quot;name&amp;quot; =&amp;gt; &amp;quot;playerTurn&amp;quot;,&lt;br /&gt;
		&amp;quot;description&amp;quot; =&amp;gt; clienttranslate(&#039;${actplayer} must play a disc&#039;),&lt;br /&gt;
		&amp;quot;descriptionmyturn&amp;quot; =&amp;gt; clienttranslate(&#039;${you} must play a disc&#039;),&lt;br /&gt;
        &amp;quot;type&amp;quot; =&amp;gt; &amp;quot;activeplayer&amp;quot;,&lt;br /&gt;
        &amp;quot;args&amp;quot; =&amp;gt; &amp;quot;argPlayerTurn&amp;quot;,&lt;br /&gt;
        &amp;quot;possibleactions&amp;quot; =&amp;gt; array( &#039;actPlayDisc&#039; ),&lt;br /&gt;
        &amp;quot;transitions&amp;quot; =&amp;gt; array( &amp;quot;playDisc&amp;quot; =&amp;gt; ST_NEXT_PLAYER, &amp;quot;zombiePass&amp;quot; =&amp;gt; ST_NEXT_PLAYER )&lt;br /&gt;
    ),&lt;br /&gt;
    &lt;br /&gt;
    ST_NEXT_PLAYER =&amp;gt; array(&lt;br /&gt;
        &amp;quot;name&amp;quot; =&amp;gt; &amp;quot;nextPlayer&amp;quot;,&lt;br /&gt;
        &amp;quot;type&amp;quot; =&amp;gt; &amp;quot;game&amp;quot;,&lt;br /&gt;
        &amp;quot;action&amp;quot; =&amp;gt; &amp;quot;stNextPlayer&amp;quot;,&lt;br /&gt;
        &amp;quot;updateGameProgression&amp;quot; =&amp;gt; true,        &lt;br /&gt;
        &amp;quot;transitions&amp;quot; =&amp;gt; array( &amp;quot;nextTurn&amp;quot; =&amp;gt; ST_PLAYER_PLAY_DISC, &amp;quot;cantPlay&amp;quot; =&amp;gt; ST_NEXT_PLAYER, &amp;quot;endGame&amp;quot; =&amp;gt; ST_END_GAME )&lt;br /&gt;
    ),&lt;br /&gt;
   &lt;br /&gt;
    ST_END_GAME =&amp;gt; array(&lt;br /&gt;
        &amp;quot;name&amp;quot; =&amp;gt; &amp;quot;gameEnd&amp;quot;,&lt;br /&gt;
        &amp;quot;description&amp;quot; =&amp;gt; clienttranslate(&amp;quot;End of game&amp;quot;),&lt;br /&gt;
        &amp;quot;type&amp;quot; =&amp;gt; &amp;quot;manager&amp;quot;,&lt;br /&gt;
        &amp;quot;action&amp;quot; =&amp;gt; &amp;quot;stGameEnd&amp;quot;,&lt;br /&gt;
        &amp;quot;args&amp;quot; =&amp;gt; &amp;quot;argGameEnd&amp;quot;&lt;br /&gt;
    )&lt;br /&gt;
&lt;br /&gt;
);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We used constants to give an index to the different states. This is to avoid mistakes when we reuse these indexes on the transitions array.&lt;br /&gt;
&lt;br /&gt;
Let&#039;s create a file you&#039;ll put in &amp;lt;code&amp;gt;modules/php/constants.inc.php&amp;lt;/code&amp;gt; :&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;?php&lt;br /&gt;
&lt;br /&gt;
/*&lt;br /&gt;
 * State constants&lt;br /&gt;
 */&lt;br /&gt;
const ST_BGA_GAME_SETUP = 1;&lt;br /&gt;
&lt;br /&gt;
const ST_PLAYER_PLAY_DISC = 10;&lt;br /&gt;
const ST_NEXT_PLAYER = 11;&lt;br /&gt;
&lt;br /&gt;
const ST_END_GAME = 99;&lt;br /&gt;
&lt;br /&gt;
?&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You will also need to add &amp;lt;code&amp;gt;require_once(&amp;quot;modules/php/constants.inc.php&amp;quot;);&amp;lt;/code&amp;gt; at the beginning of the state.inc.php to load these constants.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Now, in &amp;lt;code&amp;gt;reversi.game.php&amp;lt;/code&amp;gt; let&#039;s create the methods that are declared in this game states description file:&lt;br /&gt;
* &amp;lt;code&amp;gt;argPlayerTurn&amp;lt;/code&amp;gt;: referenced in the &amp;lt;code&amp;gt;args&amp;lt;/code&amp;gt; property of the &amp;lt;code&amp;gt;playerTurn&amp;lt;/code&amp;gt; state; this is the name of the method to call to retrieve arguments for this gamestate. Arguments are sent to the client side to be used on &amp;lt;code&amp;gt;onEnteringState&amp;lt;/code&amp;gt; or to set arguments in the gamestate description.&lt;br /&gt;
* &amp;lt;code&amp;gt;stNextPlayer&amp;lt;/code&amp;gt;: referenced in the &amp;lt;code&amp;gt;action&amp;lt;/code&amp;gt; property of the &amp;lt;code&amp;gt;nextPlayer&amp;lt;/code&amp;gt; state; this is the name of the method to call when this game state become the current game state.&lt;br /&gt;
&lt;br /&gt;
=== Test Your States ===&lt;br /&gt;
... and start a new Reversi game.&lt;br /&gt;
&lt;br /&gt;
As you can see on the screen capture below, the BGA framework makes the game jump to our first game state &amp;lt;code&amp;gt;playerTurn&amp;lt;/code&amp;gt; right after the initial setup. That&#039;s why the status bar contains the description of &amp;lt;code&amp;gt;playerTurn&amp;lt;/code&amp;gt; state (&amp;quot;XXXX must play a disc&amp;quot;):&lt;br /&gt;
&lt;br /&gt;
[[File:reversi7.jpg]]&lt;br /&gt;
&lt;br /&gt;
== The rules ==&lt;br /&gt;
&lt;br /&gt;
We will use the &amp;lt;code&amp;gt;getPossibleMoves&amp;lt;/code&amp;gt; PHP method to:&lt;br /&gt;
* Indicate to the current player where she is allowed to play by returning a list of coordinates&lt;br /&gt;
* Check if the player has the right to play in the spot they choose&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;&lt;br /&gt;
Example of getPossibleMoves here https://gist.github.com/leocaseiro/a8bc2851bd0caddd06685b5035937d15&lt;br /&gt;
&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This is pure PHP programming here, and there are no special things from the BGA framework that can be used. This is why we won&#039;t go into details here. The overall idea is:&lt;br /&gt;
* Create a &amp;lt;code&amp;gt;getTurnedOverDiscs(x,y)&amp;lt;/code&amp;gt; method that returns coordinates of discs that would be turned over if a token would be played at &amp;lt;code&amp;gt;x&amp;lt;/code&amp;gt;,&amp;lt;code&amp;gt;y&amp;lt;/code&amp;gt;.&lt;br /&gt;
* Loop through all free squares of the board and call the &amp;lt;code&amp;gt;getTurnedOverDiscs&amp;lt;/code&amp;gt; method on each of them. If at least 1 token is turned over, this is a valid move.&lt;br /&gt;
&lt;br /&gt;
IMPORTANT: Making a database query is slow! Please don&#039;t load the entire game board with a SQL query multiple times. In our implementation, we load the entire board once at the beginning of &amp;lt;code&amp;gt;getPossibleMoves&amp;lt;/code&amp;gt;, and then pass the board as an argument to all methods.&lt;br /&gt;
&lt;br /&gt;
If you want to look into details, please look at the &amp;quot;utility method&amp;quot; sections of &amp;lt;code&amp;gt;reversi.game.php&amp;lt;/code&amp;gt;. If building the tutorial yourself, copy the functions under &amp;quot;Utility functions&amp;quot; comment from the Reversi tutorial.&lt;br /&gt;
&lt;br /&gt;
== Display allowed moves ==&lt;br /&gt;
&lt;br /&gt;
Now we want to highlight the squares where the player can place a disc.&lt;br /&gt;
&lt;br /&gt;
To do this, we add a &amp;lt;code&amp;gt;argPlayerTurn&amp;lt;/code&amp;gt; method in &amp;lt;code&amp;gt;reversi.game.php&amp;lt;/code&amp;gt;. This method is called on the server each time we enter into &amp;lt;code&amp;gt;playerTurn&amp;lt;/code&amp;gt; game state, and its result is transferred automatically to the client-side:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
function argPlayerTurn(): array&lt;br /&gt;
{&lt;br /&gt;
    return [&lt;br /&gt;
        &#039;possibleMoves&#039; =&amp;gt; $this-&amp;gt;getPossibleMoves( intval($this-&amp;gt;getActivePlayerId()) )&lt;br /&gt;
    ];&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We use the &amp;lt;code&amp;gt;getPossibleMoves&amp;lt;/code&amp;gt; method we just developed.&lt;br /&gt;
&lt;br /&gt;
Each time we enter into a new game state, we use the &amp;lt;code&amp;gt;onEnteringState&amp;lt;/code&amp;gt; Javascript method (in the &amp;lt;code&amp;gt;reversi.js&amp;lt;/code&amp;gt; file, under &amp;quot;Game &amp;amp; client states&amp;quot;). This lets us use the data returned by the method above on the client side.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        onEnteringState: function( stateName, args )&lt;br /&gt;
        {&lt;br /&gt;
           console.log( &#039;Entering state: &#039;+stateName );&lt;br /&gt;
            &lt;br /&gt;
            switch( stateName )&lt;br /&gt;
            {&lt;br /&gt;
            case &#039;playerTurn&#039;:&lt;br /&gt;
                this.updatePossibleMoves( args.args.possibleMoves );&lt;br /&gt;
                break;&lt;br /&gt;
            }&lt;br /&gt;
        },&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
So, when we enter into &amp;lt;code&amp;gt;playerTurn&amp;lt;/code&amp;gt; game state, we call our &amp;lt;code&amp;gt;updatePossibleMoves&amp;lt;/code&amp;gt; method (under the &amp;quot;Utility methods&amp;quot; section). This method looks like this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
updatePossibleMoves: function( possibleMoves )&lt;br /&gt;
{&lt;br /&gt;
    // Remove current possible moves&lt;br /&gt;
    document.querySelectorAll(&#039;.possibleMove&#039;).forEach(div =&amp;gt; div.classList.remove(&#039;possibleMove&#039;));&lt;br /&gt;
&lt;br /&gt;
    for( var x in possibleMoves )&lt;br /&gt;
    {&lt;br /&gt;
        for( var y in possibleMoves[ x ] )&lt;br /&gt;
        {&lt;br /&gt;
            // x,y is a possible move&lt;br /&gt;
            document.getElementById(`square_${x}_${y}`).classList.add(&#039;possibleMove&#039;);&lt;br /&gt;
        }            &lt;br /&gt;
    }&lt;br /&gt;
                &lt;br /&gt;
    this.addTooltipToClass( &#039;possibleMove&#039;, &#039;&#039;, _(&#039;Place a disc here&#039;) );&lt;br /&gt;
},&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Here&#039;s what this does. At first, it removes all &amp;lt;code&amp;gt;possibleMove&amp;lt;/code&amp;gt; classes currently applied with the very useful &amp;lt;code&amp;gt;document.querySelectorAll&amp;lt;/code&amp;gt; method.&lt;br /&gt;
&lt;br /&gt;
Then it loops through all possible moves our PHP &amp;lt;code&amp;gt;updatePossibleMoves&amp;lt;/code&amp;gt; function created for us, and adds the &amp;lt;code&amp;gt;possibleMove&amp;lt;/code&amp;gt; class to each corresponding square.&lt;br /&gt;
&lt;br /&gt;
Finally, it uses the BGA framework &amp;lt;code&amp;gt;addTooltipToClass&amp;lt;/code&amp;gt; method to associate a tooltip to all those highlighted squares so that players can understand their meaning.&lt;br /&gt;
&lt;br /&gt;
To see the possible moves we need to create a CSS class (&amp;lt;code&amp;gt;possibleMove&amp;lt;/code&amp;gt;) that can be applied to a &amp;lt;code&amp;gt;square&amp;lt;/code&amp;gt; element to highlight it:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
.possibleMove {&lt;br /&gt;
    background-color: white;&lt;br /&gt;
    opacity: 0.2; &lt;br /&gt;
    cursor: pointer;  &lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
And here we are:&lt;br /&gt;
&lt;br /&gt;
[[File:reversi8.jpg.jpg]]&lt;br /&gt;
&lt;br /&gt;
== Let&#039;s play ==&lt;br /&gt;
&lt;br /&gt;
From now, it&#039;s better to restart a game with 2 players, because we are going to implement a complete Reversi turn. The summary of what we are going to do is:&lt;br /&gt;
* When we click on a &amp;lt;code&amp;gt;possibleMove&amp;lt;/code&amp;gt; square, send the move to the server.&lt;br /&gt;
* Server side, check the move is correct, apply Reversi rules and jump to next player.&lt;br /&gt;
* Client side, change the token position to reflect the move.&lt;br /&gt;
&lt;br /&gt;
First we associate each click on a square to one of our methods using our Javascript &amp;lt;code&amp;gt;setup&amp;lt;/code&amp;gt; method:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
document.querySelectorAll(&#039;.square&#039;).forEach(square =&amp;gt; square.addEventListener(&#039;click&#039;, e =&amp;gt; this.onPlayDisc(e)));&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note the use of the &amp;quot;dojo.query&amp;quot; method to get all HTML elements with &amp;quot;square&amp;quot; class in just one function call. Now, our &amp;quot;onPlayDisc&amp;quot; method is called each time someone clicks on a square.&lt;br /&gt;
&lt;br /&gt;
Here&#039;s our &amp;quot;onPlayDisc&amp;quot; method below:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
onPlayDisc: function( evt )&lt;br /&gt;
{&lt;br /&gt;
    // Stop this event propagation&lt;br /&gt;
    evt.preventDefault();&lt;br /&gt;
    evt.stopPropagation();&lt;br /&gt;
&lt;br /&gt;
    // Get the cliqued square x and y&lt;br /&gt;
    // Note: square id format is &amp;quot;square_X_Y&amp;quot;&lt;br /&gt;
    var coords = evt.currentTarget.id.split(&#039;_&#039;);&lt;br /&gt;
    var x = coords[1];&lt;br /&gt;
    var y = coords[2];&lt;br /&gt;
&lt;br /&gt;
    if(!document.getElementById(`square_${x}_${y}`).classList.contains(&#039;possibleMove&#039;)) {&lt;br /&gt;
        // This is not a possible move =&amp;gt; the click does nothing&lt;br /&gt;
        return ;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    this.bgaPerformAction(&amp;quot;actPlayDisc&amp;quot;, {&lt;br /&gt;
        x:x,&lt;br /&gt;
        y:y&lt;br /&gt;
    });&lt;br /&gt;
},&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
What we do here is:&lt;br /&gt;
* We stop the propagation of the Javascript &amp;lt;code&amp;gt;onclick&amp;lt;/code&amp;gt; event. Otherwise, it can lead to random behavior so it&#039;s always a good idea.&lt;br /&gt;
* We get the x/y coordinates of the square by using &amp;lt;code&amp;gt;evt.currentTarget.id&amp;lt;/code&amp;gt;&lt;br /&gt;
* We check that clicked square has the &amp;lt;code&amp;gt;possibleMove&amp;lt;/code&amp;gt; class, otherwise we know for sure that we can&#039;t play there.&lt;br /&gt;
* Finally, we make a call to the server using BGA &amp;lt;code&amp;gt;bgaPerformAction&amp;lt;/code&amp;gt; method with argument x and y. This call will check that &amp;lt;code&amp;gt;actPlayDisc&amp;lt;/code&amp;gt; action is possible, according to current game state (see &amp;lt;code&amp;gt;possibleactions&amp;lt;/code&amp;gt; entry in our &amp;lt;code&amp;gt;playerTurn&amp;lt;/code&amp;gt; game state defined above). This check is important to avoid issues if a player double clicks on a square.&lt;br /&gt;
&lt;br /&gt;
Now, we have to manage this &amp;lt;code&amp;gt;actPlayDisc&amp;lt;/code&amp;gt; action on the server side. At first, we introduce a &amp;lt;code&amp;gt;actPlayDisc&amp;lt;/code&amp;gt; entry point in our &amp;lt;code&amp;gt;reversi.action.php&amp;lt;/code&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
public function actPlayDisc()&lt;br /&gt;
{&lt;br /&gt;
    $this-&amp;gt;setAjaxMode();&lt;br /&gt;
    $x = (int)$this-&amp;gt;getArg( &amp;quot;x&amp;quot;, AT_posint, true );&lt;br /&gt;
    $y = (int)$this-&amp;gt;getArg( &amp;quot;y&amp;quot;, AT_posint, true );&lt;br /&gt;
    $result = $this-&amp;gt;game-&amp;gt;actPlayDisc( $x, $y );&lt;br /&gt;
    $this-&amp;gt;ajaxResponse( );&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
As you can see, we get the 2 arguments x and y from the javascript call, and call a corresponding &amp;lt;code&amp;gt;actPlayDisc&amp;lt;/code&amp;gt; method in our game logic (&amp;lt;code&amp;gt;reversi.game.php&amp;lt;/code&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
Now, let&#039;s have a look of this &amp;lt;code&amp;gt;actPlayDisc&amp;lt;/code&amp;gt; method:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
function actPlayDisc( int $x, int $y )&lt;br /&gt;
{&lt;br /&gt;
    // Check that this player is active and that this action is possible at this moment&lt;br /&gt;
    $this-&amp;gt;checkAction( &#039;actPlayDisc&#039; );  &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
... at first, we check that this action is possible according to current game state (see &amp;quot;possible action&amp;quot;). We already did it on client side, but it&#039;s important to do it on server side too (otherwise it would be possible to cheat).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        $player_id = intval($this-&amp;gt;getActivePlayerId()); &lt;br /&gt;
        &lt;br /&gt;
        // Now, check if this is a possible move&lt;br /&gt;
        $board = $this-&amp;gt;getBoard();&lt;br /&gt;
        $turnedOverDiscs = $this-&amp;gt;getTurnedOverDiscs( $x, $y, $player_id, $board );&lt;br /&gt;
        &lt;br /&gt;
        if( count( $turnedOverDiscs ) &amp;gt; 0 )&lt;br /&gt;
        {&lt;br /&gt;
            // This move is possible!&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
...now, we are using the &amp;lt;code&amp;gt;getTurnedOverDiscs&amp;lt;/code&amp;gt; method again to check that this move is possible.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
            // Let&#039;s place a disc at x,y and return all &amp;quot;$returned&amp;quot; discs to the active player&lt;br /&gt;
            &lt;br /&gt;
            $sql = &amp;quot;UPDATE board SET board_player=&#039;$player_id&#039;&lt;br /&gt;
                    WHERE ( board_x, board_y) IN ( &amp;quot;;&lt;br /&gt;
            &lt;br /&gt;
            foreach( $turnedOverDiscs as $turnedOver )&lt;br /&gt;
            {&lt;br /&gt;
                $sql .= &amp;quot;(&#039;&amp;quot;.$turnedOver[&#039;x&#039;].&amp;quot;&#039;,&#039;&amp;quot;.$turnedOver[&#039;y&#039;].&amp;quot;&#039;),&amp;quot;;&lt;br /&gt;
            }&lt;br /&gt;
            $sql .= &amp;quot;(&#039;$x&#039;,&#039;$y&#039;) ) &amp;quot;;&lt;br /&gt;
                       &lt;br /&gt;
            $this-&amp;gt;DbQuery( $sql );&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
... we update the database to change the color of all turned over disc + the disc we just placed.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
            // Update scores according to the number of disc on board&lt;br /&gt;
            $sql = &amp;quot;UPDATE player&lt;br /&gt;
                    SET player_score = (&lt;br /&gt;
                    SELECT COUNT( board_x ) FROM board WHERE board_player=player_id&lt;br /&gt;
                    )&amp;quot;;&lt;br /&gt;
            $this-&amp;gt;DbQuery( $sql );&lt;br /&gt;
            &lt;br /&gt;
            // Statistics&lt;br /&gt;
            $this-&amp;gt;incStat( count( $turnedOverDiscs ), &amp;quot;turnedOver&amp;quot;, $player_id );&lt;br /&gt;
            if( ($x==1 &amp;amp;&amp;amp; $y==1) || ($x==8 &amp;amp;&amp;amp; $y==1) || ($x==1 &amp;amp;&amp;amp; $y==8) || ($x==8 &amp;amp;&amp;amp; $y==8) )&lt;br /&gt;
                $this-&amp;gt;incStat( 1, &#039;discPlayedOnCorner&#039;, $player_id );&lt;br /&gt;
            else if( $x==1 || $x==8 || $y==1 || $y==8 )&lt;br /&gt;
                $this-&amp;gt;incStat( 1, &#039;discPlayedOnBorder&#039;, $player_id );&lt;br /&gt;
            else if( $x&amp;gt;=3 &amp;amp;&amp;amp; $x&amp;lt;=6 &amp;amp;&amp;amp; $y&amp;gt;=3 &amp;amp;&amp;amp; $y&amp;lt;=6 )&lt;br /&gt;
                $this-&amp;gt;incStat( 1, &#039;discPlayedOnCenter&#039;, $player_id );&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
... now, we update both player score by counting all disc, and we manage game statistics.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
            // Notify&lt;br /&gt;
            $this-&amp;gt;notifyAllPlayers( &amp;quot;playDisc&amp;quot;, clienttranslate( &#039;${player_name} plays a disc and turns over ${returned_nbr} disc(s)&#039; ), array(&lt;br /&gt;
                &#039;player_id&#039; =&amp;gt; $player_id,&lt;br /&gt;
                &#039;player_name&#039; =&amp;gt; $this-&amp;gt;getActivePlayerName(),&lt;br /&gt;
                &#039;returned_nbr&#039; =&amp;gt; count( $turnedOverDiscs ),&lt;br /&gt;
                &#039;x&#039; =&amp;gt; $x,&lt;br /&gt;
                &#039;y&#039; =&amp;gt; $y&lt;br /&gt;
            ) );&lt;br /&gt;
&lt;br /&gt;
            $this-&amp;gt;notifyAllPlayers( &amp;quot;turnOverDiscs&amp;quot;, &#039;&#039;, array(&lt;br /&gt;
                &#039;player_id&#039; =&amp;gt; $player_id,&lt;br /&gt;
                &#039;turnedOver&#039; =&amp;gt; $turnedOverDiscs&lt;br /&gt;
            ) );&lt;br /&gt;
            &lt;br /&gt;
            $newScores = $this-&amp;gt;getCollectionFromDb( &amp;quot;SELECT player_id, player_score FROM player&amp;quot;, true );&lt;br /&gt;
            $this-&amp;gt;notifyAllPlayers( &amp;quot;newScores&amp;quot;, &amp;quot;&amp;quot;, array(&lt;br /&gt;
                &amp;quot;scores&amp;quot; =&amp;gt; $newScores&lt;br /&gt;
            ) );&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
... then we notify about all these changes. We are using for that 3 notifications (&amp;lt;code&amp;gt;playDisc&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;turnOverDiscs&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;newScores&amp;lt;/code&amp;gt; that we are going to implement on client side later). Note that the description of the &amp;lt;code&amp;gt;playDisc&amp;lt;/code&amp;gt; notification will be logged in the game log.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
            // Then, go to the next state&lt;br /&gt;
            $this-&amp;gt;gamestate-&amp;gt;nextState( &#039;playDisc&#039; );&lt;br /&gt;
        }&lt;br /&gt;
        else&lt;br /&gt;
            throw new BgaSystemException( &amp;quot;Impossible move&amp;quot; );&lt;br /&gt;
    }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
... finally, we jump to the next game state if everything goes fine (&amp;lt;code&amp;gt;playDisc&amp;lt;/code&amp;gt; is the name of a transition in the &amp;lt;code&amp;gt;playerTurn&amp;lt;/code&amp;gt; game state description above which leads to state 11 which is &amp;lt;code&amp;gt;nextPlayer&amp;lt;/code&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
To make the statistics work, we have to initialize them in &amp;lt;code&amp;gt;stats.json&amp;lt;/code&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
  &amp;quot;player&amp;quot;: {&lt;br /&gt;
    &amp;quot;discPlayedOnCorner&amp;quot;: {&lt;br /&gt;
      &amp;quot;id&amp;quot;: 10,&lt;br /&gt;
      &amp;quot;name&amp;quot;: &amp;quot;Discs played on a corner&amp;quot;,&lt;br /&gt;
      &amp;quot;type&amp;quot;: &amp;quot;int&amp;quot;&lt;br /&gt;
    },&lt;br /&gt;
    &amp;quot;discPlayedOnBorder&amp;quot;: {&lt;br /&gt;
      &amp;quot;id&amp;quot;: 11,&lt;br /&gt;
      &amp;quot;name&amp;quot;: &amp;quot;Discs played on a border&amp;quot;,&lt;br /&gt;
      &amp;quot;type&amp;quot;: &amp;quot;int&amp;quot;&lt;br /&gt;
    },&lt;br /&gt;
    &amp;quot;discPlayedOnCenter&amp;quot;: {&lt;br /&gt;
      &amp;quot;id&amp;quot;: 12,&lt;br /&gt;
      &amp;quot;name&amp;quot;: &amp;quot;Discs played on board center part&amp;quot;,&lt;br /&gt;
      &amp;quot;type&amp;quot;: &amp;quot;int&amp;quot;&lt;br /&gt;
    },&lt;br /&gt;
    &amp;quot;turnedOver&amp;quot;: {&lt;br /&gt;
      &amp;quot;id&amp;quot;: 13,&lt;br /&gt;
      &amp;quot;name&amp;quot;: &amp;quot;Number of discs turned over&amp;quot;,&lt;br /&gt;
      &amp;quot;type&amp;quot;: &amp;quot;int&amp;quot;&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
A last thing to do on the server side is to activate the next player when we enter the &amp;lt;code&amp;gt;nextPlayer&amp;lt;/code&amp;gt; game state (in the &amp;lt;code&amp;gt;reversi.game.php&amp;lt;/code&amp;gt; file, under &amp;quot;Game state reactions&amp;quot;):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    function stNextPlayer(): void&lt;br /&gt;
    {&lt;br /&gt;
        // Active next player&lt;br /&gt;
        $player_id = intval($this-&amp;gt;activeNextPlayer());&lt;br /&gt;
&lt;br /&gt;
        // Check if both player has at least 1 discs, and if there are free squares to play&lt;br /&gt;
        $player_to_discs = $this-&amp;gt;getCollectionFromDb( &amp;quot;SELECT board_player, COUNT( board_x )&lt;br /&gt;
                                                       FROM board&lt;br /&gt;
                                                       GROUP BY board_player&amp;quot;, true );&lt;br /&gt;
&lt;br /&gt;
        if( ! isset( $player_to_discs[ null ] ) )&lt;br /&gt;
        {&lt;br /&gt;
            // Index 0 has not been set =&amp;gt; there&#039;s no more free place on the board !&lt;br /&gt;
            // =&amp;gt; end of the game&lt;br /&gt;
            $this-&amp;gt;gamestate-&amp;gt;nextState( &#039;endGame&#039; );&lt;br /&gt;
            return ;&lt;br /&gt;
        }&lt;br /&gt;
        else if( ! isset( $player_to_discs[ $player_id ] ) )&lt;br /&gt;
        {&lt;br /&gt;
            // Active player has no more disc on the board =&amp;gt; he looses immediately&lt;br /&gt;
            $this-&amp;gt;gamestate-&amp;gt;nextState( &#039;endGame&#039; );&lt;br /&gt;
            return ;&lt;br /&gt;
        }&lt;br /&gt;
        &lt;br /&gt;
        // Can this player play?&lt;br /&gt;
&lt;br /&gt;
        $possibleMoves = $this-&amp;gt;getPossibleMoves( $player_id );&lt;br /&gt;
        if( count( $possibleMoves ) == 0 )&lt;br /&gt;
        {&lt;br /&gt;
&lt;br /&gt;
            // This player can&#039;t play&lt;br /&gt;
            // Can his opponent play ?&lt;br /&gt;
            $opponent_id = (int)$this-&amp;gt;getUniqueValueFromDb( &amp;quot;SELECT player_id FROM player WHERE player_id!=&#039;$player_id&#039; &amp;quot; );&lt;br /&gt;
            if( count( $this-&amp;gt;getPossibleMoves( $opponent_id ) ) == 0 )&lt;br /&gt;
            {&lt;br /&gt;
                // Nobody can move =&amp;gt; end of the game&lt;br /&gt;
                $this-&amp;gt;gamestate-&amp;gt;nextState( &#039;endGame&#039; );&lt;br /&gt;
            }&lt;br /&gt;
            else&lt;br /&gt;
            {            &lt;br /&gt;
                // =&amp;gt; pass his turn&lt;br /&gt;
                $this-&amp;gt;gamestate-&amp;gt;nextState( &#039;cantPlay&#039; );&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
        else&lt;br /&gt;
        {&lt;br /&gt;
            // This player can play. Give him some extra time&lt;br /&gt;
            $this-&amp;gt;giveExtraTime( $player_id );&lt;br /&gt;
            $this-&amp;gt;gamestate-&amp;gt;nextState( &#039;nextTurn&#039; );&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Now, when we play a token, the rules are checked and the token appears in the database.&lt;br /&gt;
&lt;br /&gt;
[[File:reversi9.jpg]]&lt;br /&gt;
&lt;br /&gt;
Of course, as we don&#039;t manage notifications on client side, we need to press F5 after each move to see the changes on the board.&lt;br /&gt;
&lt;br /&gt;
== Make the move appear automatically ==&lt;br /&gt;
&lt;br /&gt;
Now, what we have to do is process the notifications sent by the server and make the move appear on the interface.&lt;br /&gt;
&lt;br /&gt;
In our &amp;lt;code&amp;gt;setupNotifications&amp;lt;/code&amp;gt; method in &amp;lt;code&amp;gt;reversi.js&amp;lt;/code&amp;gt;, we register 2 methods for the 2 notifications we created at the previous step (&amp;lt;code&amp;gt;playDisc&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;turnOverDiscs&amp;lt;/code&amp;gt;):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
            const notifs = [&lt;br /&gt;
                [&#039;playDisc&#039;, 500],&lt;br /&gt;
                [&#039;turnOverDiscs&#039;, 1500],&lt;br /&gt;
                [&#039;newScores&#039;, 1],&lt;br /&gt;
            ];&lt;br /&gt;
    &lt;br /&gt;
            notifs.forEach((notif) =&amp;gt; {&lt;br /&gt;
                dojo.subscribe(notif[0], this, `notif_${notif[0]}`);&lt;br /&gt;
                this.notifqueue.setSynchronous(notif[0], notif[1]);&lt;br /&gt;
            });&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We will associate each of our 3 notifications with a method prefixed with &amp;lt;code&amp;gt;notif_&amp;lt;/code&amp;gt;. We also define these notifications as &amp;quot;synchronous&amp;quot;, with a duration in millisecond. It tells the user interface to wait some time after executing the notification, to let the animation end before starting the next notification. In our specific case, the animation will be the following:&lt;br /&gt;
* Make a disc slide from the player panel to its place on the board&lt;br /&gt;
* (wait 500ms)&lt;br /&gt;
* Make all turned over discs blink (and of course turned them over)&lt;br /&gt;
* (wait 1500ms)&lt;br /&gt;
* Update the player scores&lt;br /&gt;
* (no real delay on this one)&lt;br /&gt;
&lt;br /&gt;
The second part of the code is a generic thing to automatically bind the notifs we configured to the &amp;lt;code&amp;gt;notif_&amp;lt;notifName&amp;gt;&amp;lt;/code&amp;gt; functions we are about to create.&lt;br /&gt;
&lt;br /&gt;
Let&#039;s have a look now on the &amp;lt;code&amp;gt;playDisc&amp;lt;/code&amp;gt; notification handler method:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
notif_playDisc: function( notif )&lt;br /&gt;
{&lt;br /&gt;
    // Remove current possible moves (makes the board more clear)&lt;br /&gt;
    document.querySelectorAll(&#039;.possibleMove&#039;).forEach(div =&amp;gt; div.classList.remove(&#039;possibleMove&#039;));&lt;br /&gt;
&lt;br /&gt;
    this.addDiscOnBoard( notif.args.x, notif.args.y, notif.args.player_id );&lt;br /&gt;
},&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
No surprise here, we re-used some existing stuff to:&lt;br /&gt;
* Remove the highlighted squares.&lt;br /&gt;
* Add a new disc on board, coming from player panel.&lt;br /&gt;
&lt;br /&gt;
Now, here&#039;s the method that handles the &amp;lt;code&amp;gt;turnOverDiscs&amp;lt;/code&amp;gt; notification:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
notif_turnOverDiscs: function( notif )&lt;br /&gt;
{&lt;br /&gt;
    // Get the color of the player who is returning the discs&lt;br /&gt;
    var targetColor = this.gamedatas.players[ notif.args.player_id ].color;&lt;br /&gt;
&lt;br /&gt;
    // Made these discs blinking and set them to the specified color&lt;br /&gt;
    for( var i in notif.args.turnedOver )&lt;br /&gt;
    {&lt;br /&gt;
        var disc = notif.args.turnedOver[ i ];&lt;br /&gt;
        &lt;br /&gt;
        // Make the disc blink 2 times&lt;br /&gt;
        var anim = dojo.fx.chain( [&lt;br /&gt;
            dojo.fadeOut( { node: &#039;disc_&#039;+disc.x+&#039;&#039;+disc.y } ),&lt;br /&gt;
            dojo.fadeIn( { node: &#039;disc_&#039;+disc.x+&#039;&#039;+disc.y } ),&lt;br /&gt;
            dojo.fadeOut( { &lt;br /&gt;
                            node: &#039;disc_&#039;+disc.x+&#039;&#039;+disc.y,&lt;br /&gt;
                            onEnd: node =&amp;gt; $(node).dataset.color = targetColor,&lt;br /&gt;
                            } ),&lt;br /&gt;
            dojo.fadeIn( { node: &#039;disc_&#039;+disc.x+&#039;&#039;+disc.y  } )&lt;br /&gt;
                            &lt;br /&gt;
        ] ); // end of dojo.fx.chain&lt;br /&gt;
&lt;br /&gt;
        // ... and launch the animation&lt;br /&gt;
        anim.play();                &lt;br /&gt;
    }&lt;br /&gt;
},&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The list of the discs to be turned over has been made available by our server side code in &amp;lt;code&amp;gt;notif.args.turnedOver&amp;lt;/code&amp;gt; (see previous paragraph). We loop through all these discs, and create a complex animation using &amp;lt;code&amp;gt;dojo.Animation&amp;lt;/code&amp;gt; for each of them. The complete documentation on dojo animations [http://dojotoolkit.org/documentation/tutorials/1.6/animation/ can be found here].&lt;br /&gt;
&lt;br /&gt;
In few words: we create a chain of 4 animations to make the disc fade out, fade in, fade out again, and fade in again. At the end of the second fade out, we change the color of the disc. Finally, we launch the animation with &amp;lt;code&amp;gt;play()&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
And Also the notification to update the scores:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
notif_newScores: function( notif )&lt;br /&gt;
        {&lt;br /&gt;
            for( var player_id in notif.args.scores )&lt;br /&gt;
            {&lt;br /&gt;
                var newScore = notif.args.scores[ player_id ];&lt;br /&gt;
                this.scoreCtrl[ player_id ].toValue( newScore );&lt;br /&gt;
            }&lt;br /&gt;
        },&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Category:Studio]]&lt;/div&gt;</summary>
		<author><name>Sguzzer Gunayer</name></author>
	</entry>
	<entry>
		<id>https://en.doc.boardgamearena.com/index.php?title=Tutorial_reversi&amp;diff=22418</id>
		<title>Tutorial reversi</title>
		<link rel="alternate" type="text/html" href="https://en.doc.boardgamearena.com/index.php?title=Tutorial_reversi&amp;diff=22418"/>
		<updated>2024-09-03T14:59:15Z</updated>

		<summary type="html">&lt;p&gt;Sguzzer Gunayer: /* Board Initialization Explanation */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&#039;&#039;&#039;Check out an update version&#039;&#039;&#039; of the [[BGA Type Safe Template: Reversi|Reversi Tutorial]] which uses the [[BGA Type Safe Template]]. {{Studio_Framework_Navigation}}&lt;br /&gt;
&lt;br /&gt;
== Introduction ==&lt;br /&gt;
&lt;br /&gt;
Using this tutorial, you can build a complete working game on the BGA environment: Reversi.&lt;br /&gt;
&lt;br /&gt;
Before you read this tutorial, you must:&lt;br /&gt;
* Read the overall presentations of the BGA Framework ([[Studio|see here]]).&lt;br /&gt;
* Know the [http://en.wikipedia.org/wiki/Reversi#Rules rules of Reversi].&lt;br /&gt;
* Know the languages used on BGA: PHP, SQL, HTML, CSS, Javascript&lt;br /&gt;
* &#039;&#039;&#039;Setup your development environment&#039;&#039;&#039; [http://en.doc.boardgamearena.com/First_steps_with_BGA_Studio First Steps with BGA Studio]&lt;br /&gt;
&lt;br /&gt;
== Create your first game ==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Note: you should already have created a project following instructions in [[First_steps_with_BGA_Studio#Create_a_new_game_project|Create a new game project]]. While you will find a &#039;&#039;&#039;reversi&#039;&#039;&#039; directory in your SFTP folder, do not use it for this tutorial. Instead, use the project you have created as an (empty) starting point.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
With the initial skeleton of code provided in your project, you can already start a game from the BGA Studio:&lt;br /&gt;
* Go to your [https://studio.boardgamearena.com/controlpanel studio Control panel], then Manage games and select your initial project. &#039;&#039;Note: there are warnings displayed about a missing BGG_ID and presentation text. You can ignore that for now.&#039;&#039;&lt;br /&gt;
* Click the Play link next to your project name. This will open the Play page and offer to create a new table for your project. &#039;&#039;Optional: click the Heart icon to add your project to your favorite games list.&#039;&#039;&lt;br /&gt;
* On the Play page, on the top of the page, make sure that your settings are &amp;quot;Simple game&amp;quot;, &amp;quot;Real time&amp;quot; and &amp;quot;Manual&amp;quot;.&lt;br /&gt;
* Click &amp;quot;Create table&amp;quot; to create a table of your project. &lt;br /&gt;
* For now, we are going to work with one player only, so use the (-) button to set the number of players to 1. Most of the time it is simpler to proceed with only one player during the early phase of development of your game, as it&#039;s easy and fast to start/stop games. If you choose to start with 2 players, you should see two names on the right: testdude0 and testdude1. To switch between them, press the red arrow button near their names; it will open another tab. This way you don&#039;t need to login and logout from multiple accounts.) &lt;br /&gt;
* Reminder: Always use the &amp;quot;Express Start&amp;quot; button to start the game.&lt;br /&gt;
&lt;br /&gt;
Thus, you can start a &amp;quot;Reversi&amp;quot; game, and arrive on a void, empty game. Yeah.&lt;br /&gt;
&lt;br /&gt;
End the game by clicking on the game options icon on the top right, and then on &amp;quot;Express Stop&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
== Editing the game information (Optional) ==&lt;br /&gt;
&lt;br /&gt;
This step is optional and will fix the warnings on the project page (missing BGG_ID and presentation).&lt;br /&gt;
&lt;br /&gt;
==== Edits to fix Errors ====&lt;br /&gt;
* Edit your local copy of the &amp;lt;code&amp;gt;gameinfos.inc.php&amp;lt;/code&amp;gt; file:&lt;br /&gt;
** Change the &amp;lt;code&amp;gt;bgg_id&amp;lt;/code&amp;gt; value from &amp;lt;code&amp;gt;0&amp;lt;/code&amp;gt; to &amp;lt;code&amp;gt;2389&amp;lt;/code&amp;gt; - that&#039;s around line 37.&lt;br /&gt;
** Add &amp;lt;code&amp;gt;1,&amp;lt;/code&amp;gt; to the players array - that&#039;s around line 41.&lt;br /&gt;
** Change the presentation array content - that&#039;s around line 134. Uncomment one line and change the text. Remove the final comma if you keep only one line!&lt;br /&gt;
* Upload the &amp;lt;code&amp;gt;gameinfos.inc.php&amp;lt;/code&amp;gt; file to the SFTP server (see [[First_steps_with_BGA_Studio#Connect_to_your_SFTP_folder|Connect to your SFTP folder]]).&lt;br /&gt;
&lt;br /&gt;
==== Test your Edits ====&lt;br /&gt;
* Go back to your project page, and in the &amp;quot;Game Information&amp;quot; section, click &amp;quot;Reload game informations&amp;quot;.&lt;br /&gt;
* Finally, refresh the project page in your browser (usually CTRL-F5).&lt;br /&gt;
&lt;br /&gt;
===== Not working? =====&lt;br /&gt;
Some changes will require bypassing the cache. It is often worth doing a hard refresh to make sure the&lt;br /&gt;
&lt;br /&gt;
Sometimes the cache will keep your changes from showing. Since this is a possibility, it will be useful to know how to bypass the cache. To do so you may manually clear cache or use a shortcut to refresh and ignore the cached version of the page. Here&#039;s how&lt;br /&gt;
&lt;br /&gt;
====== Windows ======&lt;br /&gt;
Chrome, Firefox, or Edge: Press &amp;lt;code&amp;gt;Ctrl+F5&amp;lt;/code&amp;gt; or &amp;lt;code&amp;gt;Shift+F5&amp;lt;/code&amp;gt; or &amp;lt;code&amp;gt;Ctrl+Shift+R&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====== Mac ======&lt;br /&gt;
Chrome or Firefox: Press &amp;lt;code&amp;gt;Shift+Command+R&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Safari for Mac: Press &amp;lt;code&amp;gt;Command+Option+E&amp;lt;/code&amp;gt; to empty the cache, then hold down Shift and click Reload in the toolbar&lt;br /&gt;
&lt;br /&gt;
== Make it look like Reversi ==&lt;br /&gt;
&lt;br /&gt;
Let&#039;s start with the board. This will give you a good idea of how things will look and where tokens should go.&lt;br /&gt;
&lt;br /&gt;
Be careful designing the layout of your game: you must always keep in mind that players with a 1024px screen width must be able to play. Usually, it means that the width of the play area can be 750px (in the worst case).&lt;br /&gt;
&lt;br /&gt;
For Reversi, it&#039;s useless to have a 750x750px board - much too big, so we chose this one which fit perfectly (536x528):&lt;br /&gt;
&lt;br /&gt;
[[File:Board.jpg]]&lt;br /&gt;
&lt;br /&gt;
Note that we are using a jpg file. Jpg files are lighter than png, so they are faster to load. Later, we are going to use PNGs for tokens because they allow for transparency.&lt;br /&gt;
&lt;br /&gt;
==== Add the board ====&lt;br /&gt;
use lowercase file names&lt;br /&gt;
* upload &amp;lt;code&amp;gt;board.jpg&amp;lt;/code&amp;gt; in your &amp;lt;code&amp;gt;img/&amp;lt;/code&amp;gt; directory. &lt;br /&gt;
* edit &amp;lt;code&amp;gt;reversi_reversi.tpl&amp;lt;/code&amp;gt; to add a &amp;lt;code&amp;gt;div&amp;lt;/code&amp;gt; for your board.&lt;br /&gt;
&lt;br /&gt;
Note: If you are building this game by following the tutorial, you will have a different project name than &amp;lt;code&amp;gt;reversi&amp;lt;/code&amp;gt; (i.e. &amp;lt;code&amp;gt;mygame_mygame.tpl&amp;lt;/code&amp;gt;). The file names in your project will be different than shown in this tutorial, replacing &amp;lt;code&amp;gt;reversi&amp;lt;/code&amp;gt; with your project name. Be sure that any code (other than comments) that references &amp;lt;code&amp;gt;reversi&amp;lt;/code&amp;gt; is changed to your actual project name.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;div id=&amp;quot;board&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* edit your &amp;lt;code&amp;gt;reversi.css&amp;lt;/code&amp;gt; file to transform it into a visible board:&lt;br /&gt;
&lt;br /&gt;
 #board {&lt;br /&gt;
    width: 536px;&lt;br /&gt;
    height: 528px;&lt;br /&gt;
    background-image: url(&#039;img/board.jpg&#039;);&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Important: refresh your page.&#039;&#039;&#039; Here&#039;s your board:[[File:reversi1.jpg]]&lt;br /&gt;
&lt;br /&gt;
If the board does not appear, refresh the page (always do this when you update the CSS file), and check the image filename. Remember file names are case sensitive!&lt;br /&gt;
&lt;br /&gt;
==== Code the Grid ====&lt;br /&gt;
Now, we need to create some invisible HTML elements where squares are. These elements will be used as position references for the white and black tokens. &lt;br /&gt;
&lt;br /&gt;
===== Build the grid of squares =====&lt;br /&gt;
The board is 8 squares by 8 squares. This means we need 64 squares. To avoid writing 64 individual &amp;lt;code&amp;gt;div&amp;lt;/code&amp;gt; elements on our template, we are going to generate the squares on JS setup.&lt;br /&gt;
&lt;br /&gt;
We&#039;ll do this in our Javascript &amp;lt;code&amp;gt;setup&amp;lt;/code&amp;gt; method under &amp;lt;code&amp;gt;// TODO: Set up your game interface here, according to &amp;quot;gamedatas&amp;quot;&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
const board = document.getElementById(&#039;board&#039;);&lt;br /&gt;
const hor_scale = 64.8;&lt;br /&gt;
const ver_scale = 64.4;&lt;br /&gt;
for (let x=1; x&amp;lt;=8; x++) {&lt;br /&gt;
    for (let y=1; y&amp;lt;=8; y++) {&lt;br /&gt;
        const left = Math.round((x - 1) * hor_scale + 10);&lt;br /&gt;
        const top = Math.round((y - 1) * ver_scale + 7);&lt;br /&gt;
        // we use afterbegin to make sure squares are placed before discs&lt;br /&gt;
        board.insertAdjacentHTML(`afterbegin`, `&amp;lt;div id=&amp;quot;square_${x}_${y}&amp;quot; class=&amp;quot;square&amp;quot; style=&amp;quot;left: ${left}px; top: ${top}px;&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;`);&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note: as you can see, squares in our &amp;lt;code&amp;gt;board.jpg&amp;lt;/code&amp;gt; files do not have an exact width/height in pixels, and that&#039;s the reason we are using floating point numbers here.&lt;br /&gt;
&lt;br /&gt;
===== Style Those Squares =====&lt;br /&gt;
Now, to finish our work and check if everything works fine, we are going to style our square a little bit in our CSS stylesheet:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#board {&lt;br /&gt;
    width: 536px;&lt;br /&gt;
    height: 528px;&lt;br /&gt;
    background-image: url(&#039;img/board.jpg&#039;);&lt;br /&gt;
    position: relative;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.square {&lt;br /&gt;
    width: 62px;&lt;br /&gt;
    height: 62px;&lt;br /&gt;
    position: absolute;&lt;br /&gt;
    background-color: red;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Explanations:&lt;br /&gt;
* With &amp;quot;position: relative&amp;quot; on board, we ensure square elements are positioned relatively to board.&lt;br /&gt;
* &amp;lt;code&amp;gt;background-color: red;&amp;lt;/code&amp;gt; is used for testing. This allows us to see the invisible elements. (You could instead do something like &amp;lt;code&amp;gt;outline: 2px solid orange;&amp;lt;/code&amp;gt; have fun and be creative)&lt;br /&gt;
&lt;br /&gt;
Let&#039;s refresh and check our (beautiful) squares:&lt;br /&gt;
&lt;br /&gt;
[[File:reversi2.jpg]]&lt;br /&gt;
&lt;br /&gt;
Now that you know the squares are there, you can remove the test line &amp;lt;code&amp;gt;background-color: red;&amp;lt;/code&amp;gt;  from your &amp;lt;code&amp;gt;.square&amp;lt;/code&amp;gt; class in the CSS stylesheet.&lt;br /&gt;
&lt;br /&gt;
===== Not Working? =====&lt;br /&gt;
If the styled squares do not appear, inspect and check your css (Chrome DevTools: Application &amp;gt; Frames &amp;gt; top &amp;gt; Stylesheets &amp;gt; reversi.css). &lt;br /&gt;
&lt;br /&gt;
== The Tokens ==&lt;br /&gt;
&lt;br /&gt;
Now, our board is ready for some tokens!&lt;br /&gt;
&lt;br /&gt;
[Note: Throughout this tutorial, sometimes &amp;quot;tokens&amp;quot; is used, and sometimes &amp;quot;discs&amp;quot; is used. They are often swapped if you&#039;re looking at code in the reversi example project.]&lt;br /&gt;
&lt;br /&gt;
=== Build the Token ===&lt;br /&gt;
There are quite a few steps before the tokens will appear. You may be used to testing after every change, but that won&#039;t work well here. The token will &#039;&#039;&#039;not&#039;&#039;&#039; show until you have add styles to the css, js template to the tpl, utility method in the js,  adjusted the php file, and added the token to the board in the js file.&lt;br /&gt;
&lt;br /&gt;
==== HTML in the .tpl file ====&lt;br /&gt;
At first, we introduce a new &#039;div&#039; element as a child of &amp;quot;board&amp;quot; to host all these tokens (in our template):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;div id=&amp;quot;board&amp;quot;&amp;gt;&lt;br /&gt;
    &lt;br /&gt;
    &amp;lt;div id=&amp;quot;discs&amp;quot;&amp;gt;&lt;br /&gt;
    &amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note: &amp;lt;code&amp;gt;discs&amp;lt;/code&amp;gt; is plural. This div will be used to hold the token divs. Shortly, we will use javascript to add individual tokens to the board.&lt;br /&gt;
&lt;br /&gt;
==== Add Token to img directory ====&lt;br /&gt;
Here&#039;s a new piece of art with the tokens. We need transparency here so we are using a png file:&lt;br /&gt;
&lt;br /&gt;
[[File:tokens.png]]&lt;br /&gt;
&lt;br /&gt;
Upload this image file &amp;lt;code&amp;gt;tokens.png&amp;lt;/code&amp;gt; in your &amp;lt;code&amp;gt;img/&amp;lt;/code&amp;gt; directory.&lt;br /&gt;
&lt;br /&gt;
Important Fun Fact: we are using ONE file for both tokens. It is really important to use a minimum number of graphic files for your game. This is called the &amp;quot;CSS sprite&amp;quot; technique, because it makes the game load faster and more reliable. [http://www.w3schools.com/css/css_image_sprites.asp Read more about CSS sprites].&lt;br /&gt;
&lt;br /&gt;
==== Style the Tokens in .css file ====&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
.disc {&lt;br /&gt;
    width: 56px;&lt;br /&gt;
    height: 56px;&lt;br /&gt;
    position: absolute;&lt;br /&gt;
    background-image: url(&#039;img/tokens.png&#039;);&lt;br /&gt;
    background-size: auto 100%;&lt;br /&gt;
}&lt;br /&gt;
.disc[data-color=&amp;quot;ffffff&amp;quot;] { background-position-x: 0%; }&lt;br /&gt;
.disc[data-color=&amp;quot;000000&amp;quot;] { background-position-x: 100%; }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
With this CSS code, we can set and change the token color by changing the data-color attribute. Using data instead of a class ensures it can be only one of them (the disc cannot be black and white at the same time).&lt;br /&gt;
&lt;br /&gt;
Note the &amp;quot;&amp;lt;code&amp;gt;position: absolute&amp;lt;/code&amp;gt;&amp;quot; which allows us to position tokens on the board and make them &amp;quot;slide&amp;quot; to their positions.&lt;br /&gt;
&lt;br /&gt;
==== Add Token Utility Method in .js file ====&lt;br /&gt;
Now, let&#039;s make the first token appear on our board. Tokens are not visible at the beginning of the game: they appear dynamically during the game. For this reason, we are going to make them appear from our Javascript code, using a template string&lt;br /&gt;
&lt;br /&gt;
Let&#039;s create a method in our Javascript code (in the &amp;lt;code&amp;gt;reversi.js&amp;lt;/code&amp;gt; file) that will make a token appear on the board, using this template. Add under the section //// Utility methods:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
addDiscOnBoard: function( x, y, player )&lt;br /&gt;
{&lt;br /&gt;
    var color = this.gamedatas.players[ player ].color;&lt;br /&gt;
    &lt;br /&gt;
    document.getElementById(&#039;discs&#039;).insertAdjacentHTML(&#039;beforeend&#039;, `&amp;lt;div class=&amp;quot;disc&amp;quot; data-color=&amp;quot;${color}&amp;quot; id=&amp;quot;disc_${x}${y}&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;`);&lt;br /&gt;
    &lt;br /&gt;
    this.placeOnObject( `disc_${x}${y}`, &#039;overall_player_board_&#039;+player );&lt;br /&gt;
    this.slideToObject( `disc_${x}${y}`, &#039;square_&#039;+x+&#039;_&#039;+y ).play();&lt;br /&gt;
},  &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===== Utility Method Explanation =====&lt;br /&gt;
* with &amp;lt;code&amp;gt;element.insertAdjacentHTML&amp;lt;/code&amp;gt; method, we create a HTML piece of code and insert it as a new child of &amp;lt;code&amp;gt;tokens&amp;lt;/code&amp;gt; div element.&lt;br /&gt;
* with &amp;lt;code&amp;gt;this.placeOnObject&amp;lt;/code&amp;gt; BGA method, we place this element over the panel of some player. &lt;br /&gt;
* Immediately after, using &amp;lt;code&amp;gt;this.slideToObject&amp;lt;/code&amp;gt; BGA method, we make the token slide to the &amp;lt;code&amp;gt;square&amp;lt;/code&amp;gt; element, its final destination.&lt;br /&gt;
* &amp;lt;code&amp;gt;&#039;overall_player_board_&#039;+player&amp;lt;/code&amp;gt; refers to the div element that contains each player&#039;s information and avatar. By initially placing the token here, it gives the effect that the player&#039;s avatar is throwing the token onto the board.&lt;br /&gt;
&lt;br /&gt;
Note: don&#039;t forget to call the &amp;lt;code&amp;gt;play()&amp;lt;/code&amp;gt;, otherwise the token will remain at its original location.&lt;br /&gt;
&lt;br /&gt;
Note: during this process, the parent of the new token HTML element will stay &amp;lt;code&amp;gt;tokens&amp;lt;/code&amp;gt;. &amp;lt;code&amp;gt;placeOnObject&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;slideToObject&amp;lt;/code&amp;gt; methods are &#039;&#039;only&#039;&#039; moving the position of elements on screen, and they are &#039;&#039;not&#039;&#039; modifying the HTML tree.&lt;br /&gt;
&lt;br /&gt;
==== Set Token Colors in setupNewGame in .game.php file ====&lt;br /&gt;
Before we can show a token, we need to set the player colors in the &amp;lt;code&amp;gt;setupNewGame&amp;lt;/code&amp;gt; function in &amp;lt;code&amp;gt;reversi.game.php&amp;lt;/code&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
Replace &amp;lt;code&amp;gt;$default_colors = $gameinfos[&#039;player_colors&#039;];&amp;lt;/code&amp;gt; with the following line:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        $default_colors = array( &amp;quot;ffffff&amp;quot;, &amp;quot;000000&amp;quot; );&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note: A few lines below, you may have to remove the line &amp;lt;code&amp;gt;this-&amp;gt;reattributeColorsBasedOnPreferences( $players, $gameinfos[&#039;player_colors&#039;] );&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Test the Token ===&lt;br /&gt;
Now, to test if everything works fine&lt;br /&gt;
&lt;br /&gt;
==== addTokenOnBoard() in .js file to Test ====&lt;br /&gt;
In &amp;lt;code&amp;gt;reversi.js&amp;lt;/code&amp;gt;, in &amp;lt;code&amp;gt;setup: function&amp;lt;/code&amp;gt;, under the code we added to generate the squares. &lt;br /&gt;
 this.addDiscOnBoard( 2, 2, this.player_id );&lt;br /&gt;
Now restart the game.&lt;br /&gt;
&lt;br /&gt;
A token should appear and slide immediately to its position, like this:&lt;br /&gt;
&lt;br /&gt;
[[File:reversi3.jpg]]&lt;br /&gt;
&lt;br /&gt;
== The database ==&lt;br /&gt;
&lt;br /&gt;
We did most of the client-side programming, so let&#039;s have a look on the other side now. To design the database model of our game, you will need to access the database. You won&#039;t need to do anything in database UI, yet.&lt;br /&gt;
&lt;br /&gt;
=== Accessing the Database ===&lt;br /&gt;
To access the database, start a game, then click &amp;quot;Go to game database&amp;quot; link at the bottom of our game, to access the database directly with a PhpMyAdmin instance.&lt;br /&gt;
&lt;br /&gt;
After the first time you&#039;ve acess the database, you could skip opening a game and instead, go to https://studio.boardgamearena.com/db/ . Your PhpMyAdmin username/password is in your welcome email.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note&#039;&#039;&#039;: do not remove existing tables&lt;br /&gt;
&lt;br /&gt;
=== Create Table in .sql file ===&lt;br /&gt;
Now, you are able to create the table(s) you need for your game, and report every SQL command used in your &amp;lt;code&amp;gt;dbmodel.sql&amp;lt;/code&amp;gt; file. &lt;br /&gt;
&lt;br /&gt;
The database model of Reversi is short: just one table with the squares of the board. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
CREATE TABLE IF NOT EXISTS `board` (&lt;br /&gt;
  `board_x` smallint(5) unsigned NOT NULL,&lt;br /&gt;
  `board_y` smallint(5) unsigned NOT NULL,&lt;br /&gt;
  `board_player` int(10) unsigned DEFAULT NULL,&lt;br /&gt;
  PRIMARY KEY (`board_x`,`board_y`)&lt;br /&gt;
) ENGINE=InnoDB DEFAULT CHARSET=utf8;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Add the above SQL to &amp;lt;code&amp;gt;dbmodel.sql&amp;lt;/code&amp;gt;. Pay special attention to the backtick &amp;lt;code&amp;gt;`&amp;lt;/code&amp;gt; character vs. the single quote &amp;lt;code&amp;gt;&#039;&amp;lt;/code&amp;gt; when working with SQL. &lt;br /&gt;
&lt;br /&gt;
=== Test the Table ===&lt;br /&gt;
Now, a new database with a &amp;lt;code&amp;gt;board&amp;lt;/code&amp;gt; table will be created each time we start a Reversi game. This is why after modifying our &amp;lt;code&amp;gt;dbmodel.sql&amp;lt;/code&amp;gt; it&#039;s a good time to stop your current game &amp;amp; start a new game.&lt;br /&gt;
&lt;br /&gt;
Start a new game and verify a table is created.&lt;br /&gt;
&lt;br /&gt;
== Setup the initial game position ==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note&#039;&#039;&#039;: From now on, you must launch the game with &#039;&#039;&#039;two players&#039;&#039;&#039; to get two &amp;lt;code&amp;gt;player_id&amp;lt;/code&amp;gt;s within the database. Otherwise, the game will crash.&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;setupNewGame&amp;lt;/code&amp;gt; method of our &amp;lt;code&amp;gt;reversi.game.php&amp;lt;/code&amp;gt; is called during initial setup. This initializes our data and places the starting tokens on the board. At the beginning of the game, there should be 4 tokens on the board.&lt;br /&gt;
&lt;br /&gt;
=== Initialize the Board in .game.php file ===&lt;br /&gt;
Under &amp;lt;code&amp;gt;// TODO: setup the initial game situation here&amp;lt;/code&amp;gt;, initialize the board&amp;lt;pre&amp;gt;&lt;br /&gt;
        // Init the board&lt;br /&gt;
        $sql = &amp;quot;INSERT INTO board (board_x,board_y,board_player) VALUES &amp;quot;;&lt;br /&gt;
        $sql_values = array();&lt;br /&gt;
        list( $blackplayer_id, $whiteplayer_id ) = array_keys( $players );&lt;br /&gt;
        for( $x=1; $x&amp;lt;=8; $x++ )&lt;br /&gt;
        {&lt;br /&gt;
            for( $y=1; $y&amp;lt;=8; $y++ )&lt;br /&gt;
            {&lt;br /&gt;
                $token_value = &amp;quot;NULL&amp;quot;;&lt;br /&gt;
                if( ($x==4 &amp;amp;&amp;amp; $y==4) || ($x==5 &amp;amp;&amp;amp; $y==5) )  // Initial positions of white player&lt;br /&gt;
                    $token_value = &amp;quot;&#039;$whiteplayer_id&#039;&amp;quot;;&lt;br /&gt;
                else if( ($x==4 &amp;amp;&amp;amp; $y==5) || ($x==5 &amp;amp;&amp;amp; $y==4) )  // Initial positions of black player&lt;br /&gt;
                    $token_value = &amp;quot;&#039;$blackplayer_id&#039;&amp;quot;;&lt;br /&gt;
                    &lt;br /&gt;
                $sql_values[] = &amp;quot;(&#039;$x&#039;,&#039;$y&#039;,$token_value)&amp;quot;;&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
        $sql .= implode( &#039;,&#039;, $sql_values );&lt;br /&gt;
        $this-&amp;gt;DbQuery( $sql );&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Board Initialization Explanation ====&lt;br /&gt;
&lt;br /&gt;
* We create one table entry for each square, with a &amp;lt;code&amp;gt;NULL&amp;lt;/code&amp;gt; value which means &amp;quot;empty square&amp;quot;&lt;br /&gt;
* On 4 of the squares, we place an initial token.&lt;br /&gt;
&lt;br /&gt;
After this, we set &amp;lt;code&amp;gt;activeNextPlayer&amp;lt;/code&amp;gt; to make the first player active at the beginning of the game (this line is already present in the default code template).&lt;br /&gt;
&lt;br /&gt;
If you didn&#039;t do it earlier, you need to remove the call to &amp;lt;code&amp;gt;this-&amp;gt;reattributeColorsBasedOnPreferences()&amp;lt;/code&amp;gt; in &amp;lt;code&amp;gt;SetupNewGame()&amp;lt;/code&amp;gt;. If you don&#039;t, player color preferences will try (and fail) to override the two colors supported here.&lt;br /&gt;
&lt;br /&gt;
=== Show the Initial Token Setup ===&lt;br /&gt;
Now, we need to make these tokens appear on the client side. The first step is to return the token positions with our &amp;lt;code&amp;gt;getAllDatas()&amp;lt;/code&amp;gt; PHP method. &amp;lt;code&amp;gt;getAllDatas()&amp;lt;/code&amp;gt; is called during each page reload.&lt;br /&gt;
&lt;br /&gt;
In the &amp;lt;code&amp;gt;getAllDatas()&amp;lt;/code&amp;gt; method, after &amp;lt;code&amp;gt;// TODO: Gather all information about current game situation (visible by player $current_player_id)&amp;lt;/code&amp;gt;, add the following lines:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        // Get reversi board token&lt;br /&gt;
        $result[&#039;board&#039;] = self::getObjectListFromDB( &amp;quot;SELECT board_x x, board_y y, board_player player&lt;br /&gt;
                                                       FROM board&lt;br /&gt;
                                                       WHERE board_player IS NOT NULL&amp;quot; );&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Next, you may need to modify the query that gets player information to also get the player&#039;s colors. This is in the variable &amp;lt;code&amp;gt;$sql&amp;lt;/code&amp;gt;, above the lines you just inserted in &amp;lt;code&amp;gt;getAllDatas()&amp;lt;/code&amp;gt;. Below is what the line will look like. Notice how we&#039;ve added &amp;lt;code&amp;gt;player_color color&amp;lt;/code&amp;gt; to the sql query.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$sql = &amp;quot;SELECT player_id id, player_score score, player_color color FROM player &amp;quot;;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
We are using the BGA framework&#039;s &amp;lt;code&amp;gt;getObjectListFromDB()&amp;lt;/code&amp;gt; that formats the result of this SQL query in a PHP array with x, y and player attributes. We add it to the result associative array with the key &amp;lt;code&amp;gt;board&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Last, we process this array client side. Let&#039;s place a token on the board for each array item. We&#039;ll do this in our Javascript &amp;lt;code&amp;gt;setup&amp;lt;/code&amp;gt; method under the code we added to generate the squares. &lt;br /&gt;
&lt;br /&gt;
This will result in a removal or edit of the previously added line &amp;lt;code&amp;gt;this.addDiscOnBoard(2, 2, this.player_id);&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
for( var i in gamedatas.board )&lt;br /&gt;
{&lt;br /&gt;
    var square = gamedatas.board[i];&lt;br /&gt;
    &lt;br /&gt;
    if( square.player !== null )&lt;br /&gt;
    {&lt;br /&gt;
        this.addDiscOnBoard( square.x, square.y, square.player );&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;board&amp;lt;/code&amp;gt; entry created in &amp;lt;code&amp;gt;getAllDatas()&amp;lt;/code&amp;gt; is used here as &amp;lt;code&amp;gt;gamedatas.board&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Test the Game Start ===&lt;br /&gt;
Reload... and here we are:&lt;br /&gt;
&lt;br /&gt;
[[File:reversi5.jpg]]&lt;br /&gt;
&lt;br /&gt;
It starts to feel like Reversi here...&lt;br /&gt;
&lt;br /&gt;
== The game state machine ==&lt;br /&gt;
&lt;br /&gt;
Stop your game, again. You&#039;re about to start the core game logic.&lt;br /&gt;
&lt;br /&gt;
You already read [http://www.slideshare.net/boardgamearena/bga-studio-focus-on-bga-game-state-machine Focus on BGA game state machine], so you know that this is the heart of your game logic. For reversi, it&#039;s relatively simple. Here&#039;s a diagram of our game state machine:&lt;br /&gt;
&lt;br /&gt;
[[File:reversi6.jpg]]&lt;br /&gt;
&lt;br /&gt;
=== Build your States ===&lt;br /&gt;
And here&#039;s our &amp;lt;code&amp;gt;states.inc.php&amp;lt;/code&amp;gt;, according to this diagram:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$machinestates = array(&lt;br /&gt;
&lt;br /&gt;
    ST_BGA_GAME_SETUP =&amp;gt; array(&lt;br /&gt;
        &amp;quot;name&amp;quot; =&amp;gt; &amp;quot;gameSetup&amp;quot;,&lt;br /&gt;
        &amp;quot;description&amp;quot; =&amp;gt; clienttranslate(&amp;quot;Game setup&amp;quot;),&lt;br /&gt;
        &amp;quot;type&amp;quot; =&amp;gt; &amp;quot;manager&amp;quot;,&lt;br /&gt;
        &amp;quot;action&amp;quot; =&amp;gt; &amp;quot;stGameSetup&amp;quot;,&lt;br /&gt;
        &amp;quot;transitions&amp;quot; =&amp;gt; array( &amp;quot;&amp;quot; =&amp;gt; ST_PLAYER_PLAY_DISC )&lt;br /&gt;
    ),&lt;br /&gt;
    &lt;br /&gt;
    ST_PLAYER_PLAY_DISC =&amp;gt; array(&lt;br /&gt;
        &amp;quot;name&amp;quot; =&amp;gt; &amp;quot;playerTurn&amp;quot;,&lt;br /&gt;
		&amp;quot;description&amp;quot; =&amp;gt; clienttranslate(&#039;${actplayer} must play a disc&#039;),&lt;br /&gt;
		&amp;quot;descriptionmyturn&amp;quot; =&amp;gt; clienttranslate(&#039;${you} must play a disc&#039;),&lt;br /&gt;
        &amp;quot;type&amp;quot; =&amp;gt; &amp;quot;activeplayer&amp;quot;,&lt;br /&gt;
        &amp;quot;args&amp;quot; =&amp;gt; &amp;quot;argPlayerTurn&amp;quot;,&lt;br /&gt;
        &amp;quot;possibleactions&amp;quot; =&amp;gt; array( &#039;actPlayDisc&#039; ),&lt;br /&gt;
        &amp;quot;transitions&amp;quot; =&amp;gt; array( &amp;quot;playDisc&amp;quot; =&amp;gt; ST_NEXT_PLAYER, &amp;quot;zombiePass&amp;quot; =&amp;gt; ST_NEXT_PLAYER )&lt;br /&gt;
    ),&lt;br /&gt;
    &lt;br /&gt;
    ST_NEXT_PLAYER =&amp;gt; array(&lt;br /&gt;
        &amp;quot;name&amp;quot; =&amp;gt; &amp;quot;nextPlayer&amp;quot;,&lt;br /&gt;
        &amp;quot;type&amp;quot; =&amp;gt; &amp;quot;game&amp;quot;,&lt;br /&gt;
        &amp;quot;action&amp;quot; =&amp;gt; &amp;quot;stNextPlayer&amp;quot;,&lt;br /&gt;
        &amp;quot;updateGameProgression&amp;quot; =&amp;gt; true,        &lt;br /&gt;
        &amp;quot;transitions&amp;quot; =&amp;gt; array( &amp;quot;nextTurn&amp;quot; =&amp;gt; ST_PLAYER_PLAY_DISC, &amp;quot;cantPlay&amp;quot; =&amp;gt; ST_NEXT_PLAYER, &amp;quot;endGame&amp;quot; =&amp;gt; ST_END_GAME )&lt;br /&gt;
    ),&lt;br /&gt;
   &lt;br /&gt;
    ST_END_GAME =&amp;gt; array(&lt;br /&gt;
        &amp;quot;name&amp;quot; =&amp;gt; &amp;quot;gameEnd&amp;quot;,&lt;br /&gt;
        &amp;quot;description&amp;quot; =&amp;gt; clienttranslate(&amp;quot;End of game&amp;quot;),&lt;br /&gt;
        &amp;quot;type&amp;quot; =&amp;gt; &amp;quot;manager&amp;quot;,&lt;br /&gt;
        &amp;quot;action&amp;quot; =&amp;gt; &amp;quot;stGameEnd&amp;quot;,&lt;br /&gt;
        &amp;quot;args&amp;quot; =&amp;gt; &amp;quot;argGameEnd&amp;quot;&lt;br /&gt;
    )&lt;br /&gt;
&lt;br /&gt;
);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We used constants to give an index to the different states. This is to avoid mistakes when we reuse these indexes on the transitions array.&lt;br /&gt;
&lt;br /&gt;
Let&#039;s create a file you&#039;ll put in modules/php/constants.inc.php :&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;?php&lt;br /&gt;
&lt;br /&gt;
/*&lt;br /&gt;
 * State constants&lt;br /&gt;
 */&lt;br /&gt;
const ST_BGA_GAME_SETUP = 1;&lt;br /&gt;
&lt;br /&gt;
const ST_PLAYER_PLAY_DISC = 10;&lt;br /&gt;
const ST_NEXT_PLAYER = 11;&lt;br /&gt;
&lt;br /&gt;
const ST_END_GAME = 99;&lt;br /&gt;
&lt;br /&gt;
?&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You will also need to add &amp;lt;code&amp;gt;require_once(&amp;quot;modules/php/constants.inc.php&amp;quot;);&amp;lt;/code&amp;gt; at the beginning of the state.inc.php to load these constants.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Now, in &amp;lt;code&amp;gt;reversi.game.php&amp;lt;/code&amp;gt; let&#039;s create the methods that are declared in this game states description file:&lt;br /&gt;
* &amp;lt;code&amp;gt;argPlayerTurn&amp;lt;/code&amp;gt;: referenced in the &amp;lt;code&amp;gt;args&amp;lt;/code&amp;gt; property of the &amp;lt;code&amp;gt;playerTurn&amp;lt;/code&amp;gt; state; this is the name of the method to call to retrieve arguments for this gamestate. Arguments are sent to the client side to be used on &amp;lt;code&amp;gt;onEnteringState&amp;lt;/code&amp;gt; or to set arguments in the gamestate description.&lt;br /&gt;
* &amp;lt;code&amp;gt;stNextPlayer&amp;lt;/code&amp;gt;: referenced in the &amp;lt;code&amp;gt;action&amp;lt;/code&amp;gt; property of the &amp;lt;code&amp;gt;nextPlayer&amp;lt;/code&amp;gt; state; this is the name of the method to call when this game state become the current game state.&lt;br /&gt;
&lt;br /&gt;
=== Test Your States ===&lt;br /&gt;
... and start a new Reversi game.&lt;br /&gt;
&lt;br /&gt;
As you can see on the screen capture below, the BGA framework makes the game jump to our first game state &amp;lt;code&amp;gt;playerTurn&amp;lt;/code&amp;gt; right after the initial setup. That&#039;s why the status bar contains the description of &amp;lt;code&amp;gt;playerTurn&amp;lt;/code&amp;gt; state (&amp;quot;XXXX must play a disc&amp;quot;):&lt;br /&gt;
&lt;br /&gt;
[[File:reversi7.jpg]]&lt;br /&gt;
&lt;br /&gt;
== The rules ==&lt;br /&gt;
&lt;br /&gt;
We will use the &amp;lt;code&amp;gt;getPossibleMoves&amp;lt;/code&amp;gt; PHP method to:&lt;br /&gt;
* Indicate to the current player where she is allowed to play by returning a list of coordinates&lt;br /&gt;
* Check if the player has the right to play in the spot they choose&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;&lt;br /&gt;
Example of getPossibleMoves here https://gist.github.com/leocaseiro/a8bc2851bd0caddd06685b5035937d15&lt;br /&gt;
&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This is pure PHP programming here, and there are no special things from the BGA framework that can be used. This is why we won&#039;t go into details here. The overall idea is:&lt;br /&gt;
* Create a &amp;lt;code&amp;gt;getTurnedOverDiscs(x,y)&amp;lt;/code&amp;gt; method that returns coordinates of discs that would be turned over if a token would be played at &amp;lt;code&amp;gt;x&amp;lt;/code&amp;gt;,&amp;lt;code&amp;gt;y&amp;lt;/code&amp;gt;.&lt;br /&gt;
* Loop through all free squares of the board and call the &amp;lt;code&amp;gt;getTurnedOverDiscs&amp;lt;/code&amp;gt; method on each of them. If at least 1 token is turned over, this is a valid move.&lt;br /&gt;
&lt;br /&gt;
IMPORTANT: Making a database query is slow! Please don&#039;t load the entire game board with a SQL query multiple times. In our implementation, we load the entire board once at the beginning of &amp;lt;code&amp;gt;getPossibleMoves&amp;lt;/code&amp;gt;, and then pass the board as an argument to all methods.&lt;br /&gt;
&lt;br /&gt;
If you want to look into details, please look at the &amp;quot;utility method&amp;quot; sections of &amp;lt;code&amp;gt;reversi.game.php&amp;lt;/code&amp;gt;. If building the tutorial yourself, copy the functions under &amp;quot;Utility functions&amp;quot; comment from the Reversi tutorial.&lt;br /&gt;
&lt;br /&gt;
== Display allowed moves ==&lt;br /&gt;
&lt;br /&gt;
Now we want to highlight the squares where the player can place a disc.&lt;br /&gt;
&lt;br /&gt;
To do this, we add a &amp;lt;code&amp;gt;argPlayerTurn&amp;lt;/code&amp;gt; method in &amp;lt;code&amp;gt;reversi.game.php&amp;lt;/code&amp;gt;. This method is called on the server each time we enter into &amp;lt;code&amp;gt;playerTurn&amp;lt;/code&amp;gt; game state, and its result is transferred automatically to the client-side:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
function argPlayerTurn(): array&lt;br /&gt;
{&lt;br /&gt;
    return [&lt;br /&gt;
        &#039;possibleMoves&#039; =&amp;gt; $this-&amp;gt;getPossibleMoves( intval($this-&amp;gt;getActivePlayerId()) )&lt;br /&gt;
    ];&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We use the &amp;lt;code&amp;gt;getPossibleMoves&amp;lt;/code&amp;gt; method we just developed.&lt;br /&gt;
&lt;br /&gt;
Each time we enter into a new game state, we use the &amp;lt;code&amp;gt;onEnteringState&amp;lt;/code&amp;gt; Javascript method (in the &amp;lt;code&amp;gt;reversi.js&amp;lt;/code&amp;gt; file, under &amp;quot;Game &amp;amp; client states&amp;quot;). This lets us use the data returned by the method above on the client side.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        onEnteringState: function( stateName, args )&lt;br /&gt;
        {&lt;br /&gt;
           console.log( &#039;Entering state: &#039;+stateName );&lt;br /&gt;
            &lt;br /&gt;
            switch( stateName )&lt;br /&gt;
            {&lt;br /&gt;
            case &#039;playerTurn&#039;:&lt;br /&gt;
                this.updatePossibleMoves( args.args.possibleMoves );&lt;br /&gt;
                break;&lt;br /&gt;
            }&lt;br /&gt;
        },&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
So, when we enter into &amp;lt;code&amp;gt;playerTurn&amp;lt;/code&amp;gt; game state, we call our &amp;lt;code&amp;gt;updatePossibleMoves&amp;lt;/code&amp;gt; method (under the &amp;quot;Utility methods&amp;quot; section). This method looks like this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
updatePossibleMoves: function( possibleMoves )&lt;br /&gt;
{&lt;br /&gt;
    // Remove current possible moves&lt;br /&gt;
    document.querySelectorAll(&#039;.possibleMove&#039;).forEach(div =&amp;gt; div.classList.remove(&#039;possibleMove&#039;));&lt;br /&gt;
&lt;br /&gt;
    for( var x in possibleMoves )&lt;br /&gt;
    {&lt;br /&gt;
        for( var y in possibleMoves[ x ] )&lt;br /&gt;
        {&lt;br /&gt;
            // x,y is a possible move&lt;br /&gt;
            document.getElementById(`square_${x}_${y}`).classList.add(&#039;possibleMove&#039;);&lt;br /&gt;
        }            &lt;br /&gt;
    }&lt;br /&gt;
                &lt;br /&gt;
    this.addTooltipToClass( &#039;possibleMove&#039;, &#039;&#039;, _(&#039;Place a disc here&#039;) );&lt;br /&gt;
},&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Here&#039;s what this does. At first, it removes all &amp;lt;code&amp;gt;possibleMove&amp;lt;/code&amp;gt; classes currently applied with the very useful &amp;lt;code&amp;gt;document.querySelectorAll&amp;lt;/code&amp;gt; method.&lt;br /&gt;
&lt;br /&gt;
Then it loops through all possible moves our PHP &amp;lt;code&amp;gt;updatePossibleMoves&amp;lt;/code&amp;gt; function created for us, and adds the &amp;lt;code&amp;gt;possibleMove&amp;lt;/code&amp;gt; class to each corresponding square.&lt;br /&gt;
&lt;br /&gt;
Finally, it uses the BGA framework &amp;lt;code&amp;gt;addTooltipToClass&amp;lt;/code&amp;gt; method to associate a tooltip to all those highlighted squares so that players can understand their meaning.&lt;br /&gt;
&lt;br /&gt;
To see the possible moves we need to create a CSS class (&amp;lt;code&amp;gt;possibleMove&amp;lt;/code&amp;gt;) that can be applied to a &amp;lt;code&amp;gt;square&amp;lt;/code&amp;gt; element to highlight it:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
.possibleMove {&lt;br /&gt;
    background-color: white;&lt;br /&gt;
    opacity: 0.2; &lt;br /&gt;
    cursor: pointer;  &lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
And here we are:&lt;br /&gt;
&lt;br /&gt;
[[File:reversi8.jpg.jpg]]&lt;br /&gt;
&lt;br /&gt;
== Let&#039;s play ==&lt;br /&gt;
&lt;br /&gt;
From now, it&#039;s better to restart a game with 2 players, because we are going to implement a complete Reversi turn. The summary of what we are going to do is:&lt;br /&gt;
* When we click on a &amp;lt;code&amp;gt;possibleMove&amp;lt;/code&amp;gt; square, send the move to the server.&lt;br /&gt;
* Server side, check the move is correct, apply Reversi rules and jump to next player.&lt;br /&gt;
* Client side, change the token position to reflect the move.&lt;br /&gt;
&lt;br /&gt;
First we associate each click on a square to one of our methods using our Javascript &amp;lt;code&amp;gt;setup&amp;lt;/code&amp;gt; method:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
document.querySelectorAll(&#039;.square&#039;).forEach(square =&amp;gt; square.addEventListener(&#039;click&#039;, e =&amp;gt; this.onPlayDisc(e)));&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note the use of the &amp;quot;dojo.query&amp;quot; method to get all HTML elements with &amp;quot;square&amp;quot; class in just one function call. Now, our &amp;quot;onPlayDisc&amp;quot; method is called each time someone clicks on a square.&lt;br /&gt;
&lt;br /&gt;
Here&#039;s our &amp;quot;onPlayDisc&amp;quot; method below:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
onPlayDisc: function( evt )&lt;br /&gt;
{&lt;br /&gt;
    // Stop this event propagation&lt;br /&gt;
    evt.preventDefault();&lt;br /&gt;
    evt.stopPropagation();&lt;br /&gt;
&lt;br /&gt;
    // Get the cliqued square x and y&lt;br /&gt;
    // Note: square id format is &amp;quot;square_X_Y&amp;quot;&lt;br /&gt;
    var coords = evt.currentTarget.id.split(&#039;_&#039;);&lt;br /&gt;
    var x = coords[1];&lt;br /&gt;
    var y = coords[2];&lt;br /&gt;
&lt;br /&gt;
    if(!document.getElementById(`square_${x}_${y}`).classList.contains(&#039;possibleMove&#039;)) {&lt;br /&gt;
        // This is not a possible move =&amp;gt; the click does nothing&lt;br /&gt;
        return ;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    this.bgaPerformAction(&amp;quot;actPlayDisc&amp;quot;, {&lt;br /&gt;
        x:x,&lt;br /&gt;
        y:y&lt;br /&gt;
    });&lt;br /&gt;
},&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
What we do here is:&lt;br /&gt;
* We stop the propagation of the Javascript &amp;lt;code&amp;gt;onclick&amp;lt;/code&amp;gt; event. Otherwise, it can lead to random behavior so it&#039;s always a good idea.&lt;br /&gt;
* We get the x/y coordinates of the square by using &amp;lt;code&amp;gt;evt.currentTarget.id&amp;lt;/code&amp;gt;&lt;br /&gt;
* We check that clicked square has the &amp;lt;code&amp;gt;possibleMove&amp;lt;/code&amp;gt; class, otherwise we know for sure that we can&#039;t play there.&lt;br /&gt;
* Finally, we make a call to the server using BGA &amp;lt;code&amp;gt;bgaPerformAction&amp;lt;/code&amp;gt; method with argument x and y. This call will check that &amp;lt;code&amp;gt;actPlayDisc&amp;lt;/code&amp;gt; action is possible, according to current game state (see &amp;lt;code&amp;gt;possibleactions&amp;lt;/code&amp;gt; entry in our &amp;lt;code&amp;gt;playerTurn&amp;lt;/code&amp;gt; game state defined above). This check is important to avoid issues if a player double clicks on a square.&lt;br /&gt;
&lt;br /&gt;
Now, we have to manage this &amp;lt;code&amp;gt;actPlayDisc&amp;lt;/code&amp;gt; action on the server side. At first, we introduce a &amp;lt;code&amp;gt;actPlayDisc&amp;lt;/code&amp;gt; entry point in our &amp;lt;code&amp;gt;reversi.action.php&amp;lt;/code&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
public function actPlayDisc()&lt;br /&gt;
{&lt;br /&gt;
    $this-&amp;gt;setAjaxMode();&lt;br /&gt;
    $x = (int)$this-&amp;gt;getArg( &amp;quot;x&amp;quot;, AT_posint, true );&lt;br /&gt;
    $y = (int)$this-&amp;gt;getArg( &amp;quot;y&amp;quot;, AT_posint, true );&lt;br /&gt;
    $result = $this-&amp;gt;game-&amp;gt;actPlayDisc( $x, $y );&lt;br /&gt;
    $this-&amp;gt;ajaxResponse( );&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
As you can see, we get the 2 arguments x and y from the javascript call, and call a corresponding &amp;lt;code&amp;gt;actPlayDisc&amp;lt;/code&amp;gt; method in our game logic (&amp;lt;code&amp;gt;reversi.game.php&amp;lt;/code&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
Now, let&#039;s have a look of this &amp;lt;code&amp;gt;actPlayDisc&amp;lt;/code&amp;gt; method:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
function actPlayDisc( int $x, int $y )&lt;br /&gt;
{&lt;br /&gt;
    // Check that this player is active and that this action is possible at this moment&lt;br /&gt;
    $this-&amp;gt;checkAction( &#039;actPlayDisc&#039; );  &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
... at first, we check that this action is possible according to current game state (see &amp;quot;possible action&amp;quot;). We already did it on client side, but it&#039;s important to do it on server side too (otherwise it would be possible to cheat).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        $player_id = intval($this-&amp;gt;getActivePlayerId()); &lt;br /&gt;
        &lt;br /&gt;
        // Now, check if this is a possible move&lt;br /&gt;
        $board = $this-&amp;gt;getBoard();&lt;br /&gt;
        $turnedOverDiscs = $this-&amp;gt;getTurnedOverDiscs( $x, $y, $player_id, $board );&lt;br /&gt;
        &lt;br /&gt;
        if( count( $turnedOverDiscs ) &amp;gt; 0 )&lt;br /&gt;
        {&lt;br /&gt;
            // This move is possible!&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
...now, we are using the &amp;lt;code&amp;gt;getTurnedOverDiscs&amp;lt;/code&amp;gt; method again to check that this move is possible.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
            // Let&#039;s place a disc at x,y and return all &amp;quot;$returned&amp;quot; discs to the active player&lt;br /&gt;
            &lt;br /&gt;
            $sql = &amp;quot;UPDATE board SET board_player=&#039;$player_id&#039;&lt;br /&gt;
                    WHERE ( board_x, board_y) IN ( &amp;quot;;&lt;br /&gt;
            &lt;br /&gt;
            foreach( $turnedOverDiscs as $turnedOver )&lt;br /&gt;
            {&lt;br /&gt;
                $sql .= &amp;quot;(&#039;&amp;quot;.$turnedOver[&#039;x&#039;].&amp;quot;&#039;,&#039;&amp;quot;.$turnedOver[&#039;y&#039;].&amp;quot;&#039;),&amp;quot;;&lt;br /&gt;
            }&lt;br /&gt;
            $sql .= &amp;quot;(&#039;$x&#039;,&#039;$y&#039;) ) &amp;quot;;&lt;br /&gt;
                       &lt;br /&gt;
            $this-&amp;gt;DbQuery( $sql );&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
... we update the database to change the color of all turned over disc + the disc we just placed.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
            // Update scores according to the number of disc on board&lt;br /&gt;
            $sql = &amp;quot;UPDATE player&lt;br /&gt;
                    SET player_score = (&lt;br /&gt;
                    SELECT COUNT( board_x ) FROM board WHERE board_player=player_id&lt;br /&gt;
                    )&amp;quot;;&lt;br /&gt;
            $this-&amp;gt;DbQuery( $sql );&lt;br /&gt;
            &lt;br /&gt;
            // Statistics&lt;br /&gt;
            $this-&amp;gt;incStat( count( $turnedOverDiscs ), &amp;quot;turnedOver&amp;quot;, $player_id );&lt;br /&gt;
            if( ($x==1 &amp;amp;&amp;amp; $y==1) || ($x==8 &amp;amp;&amp;amp; $y==1) || ($x==1 &amp;amp;&amp;amp; $y==8) || ($x==8 &amp;amp;&amp;amp; $y==8) )&lt;br /&gt;
                $this-&amp;gt;incStat( 1, &#039;discPlayedOnCorner&#039;, $player_id );&lt;br /&gt;
            else if( $x==1 || $x==8 || $y==1 || $y==8 )&lt;br /&gt;
                $this-&amp;gt;incStat( 1, &#039;discPlayedOnBorder&#039;, $player_id );&lt;br /&gt;
            else if( $x&amp;gt;=3 &amp;amp;&amp;amp; $x&amp;lt;=6 &amp;amp;&amp;amp; $y&amp;gt;=3 &amp;amp;&amp;amp; $y&amp;lt;=6 )&lt;br /&gt;
                $this-&amp;gt;incStat( 1, &#039;discPlayedOnCenter&#039;, $player_id );&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
... now, we update both player score by counting all disc, and we manage game statistics.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
            // Notify&lt;br /&gt;
            $this-&amp;gt;notifyAllPlayers( &amp;quot;playDisc&amp;quot;, clienttranslate( &#039;${player_name} plays a disc and turns over ${returned_nbr} disc(s)&#039; ), array(&lt;br /&gt;
                &#039;player_id&#039; =&amp;gt; $player_id,&lt;br /&gt;
                &#039;player_name&#039; =&amp;gt; $this-&amp;gt;getActivePlayerName(),&lt;br /&gt;
                &#039;returned_nbr&#039; =&amp;gt; count( $turnedOverDiscs ),&lt;br /&gt;
                &#039;x&#039; =&amp;gt; $x,&lt;br /&gt;
                &#039;y&#039; =&amp;gt; $y&lt;br /&gt;
            ) );&lt;br /&gt;
&lt;br /&gt;
            $this-&amp;gt;notifyAllPlayers( &amp;quot;turnOverDiscs&amp;quot;, &#039;&#039;, array(&lt;br /&gt;
                &#039;player_id&#039; =&amp;gt; $player_id,&lt;br /&gt;
                &#039;turnedOver&#039; =&amp;gt; $turnedOverDiscs&lt;br /&gt;
            ) );&lt;br /&gt;
            &lt;br /&gt;
            $newScores = $this-&amp;gt;getCollectionFromDb( &amp;quot;SELECT player_id, player_score FROM player&amp;quot;, true );&lt;br /&gt;
            $this-&amp;gt;notifyAllPlayers( &amp;quot;newScores&amp;quot;, &amp;quot;&amp;quot;, array(&lt;br /&gt;
                &amp;quot;scores&amp;quot; =&amp;gt; $newScores&lt;br /&gt;
            ) );&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
... then we notify about all these changes. We are using for that 3 notifications (&amp;lt;code&amp;gt;playDisc&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;turnOverDiscs&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;newScores&amp;lt;/code&amp;gt; that we are going to implement on client side later). Note that the description of the &amp;lt;code&amp;gt;playDisc&amp;lt;/code&amp;gt; notification will be logged in the game log.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
            // Then, go to the next state&lt;br /&gt;
            $this-&amp;gt;gamestate-&amp;gt;nextState( &#039;playDisc&#039; );&lt;br /&gt;
        }&lt;br /&gt;
        else&lt;br /&gt;
            throw new BgaSystemException( &amp;quot;Impossible move&amp;quot; );&lt;br /&gt;
    }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
... finally, we jump to the next game state if everything goes fine (&amp;lt;code&amp;gt;playDisc&amp;lt;/code&amp;gt; is the name of a transition in the &amp;lt;code&amp;gt;playerTurn&amp;lt;/code&amp;gt; game state description above which leads to state 11 which is &amp;lt;code&amp;gt;nextPlayer&amp;lt;/code&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
To make the statistics work, we have to initialize them in &amp;lt;code&amp;gt;stats.json&amp;lt;/code&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
  &amp;quot;player&amp;quot;: {&lt;br /&gt;
    &amp;quot;discPlayedOnCorner&amp;quot;: {&lt;br /&gt;
      &amp;quot;id&amp;quot;: 10,&lt;br /&gt;
      &amp;quot;name&amp;quot;: &amp;quot;Discs played on a corner&amp;quot;,&lt;br /&gt;
      &amp;quot;type&amp;quot;: &amp;quot;int&amp;quot;&lt;br /&gt;
    },&lt;br /&gt;
    &amp;quot;discPlayedOnBorder&amp;quot;: {&lt;br /&gt;
      &amp;quot;id&amp;quot;: 11,&lt;br /&gt;
      &amp;quot;name&amp;quot;: &amp;quot;Discs played on a border&amp;quot;,&lt;br /&gt;
      &amp;quot;type&amp;quot;: &amp;quot;int&amp;quot;&lt;br /&gt;
    },&lt;br /&gt;
    &amp;quot;discPlayedOnCenter&amp;quot;: {&lt;br /&gt;
      &amp;quot;id&amp;quot;: 12,&lt;br /&gt;
      &amp;quot;name&amp;quot;: &amp;quot;Discs played on board center part&amp;quot;,&lt;br /&gt;
      &amp;quot;type&amp;quot;: &amp;quot;int&amp;quot;&lt;br /&gt;
    },&lt;br /&gt;
    &amp;quot;turnedOver&amp;quot;: {&lt;br /&gt;
      &amp;quot;id&amp;quot;: 13,&lt;br /&gt;
      &amp;quot;name&amp;quot;: &amp;quot;Number of discs turned over&amp;quot;,&lt;br /&gt;
      &amp;quot;type&amp;quot;: &amp;quot;int&amp;quot;&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
A last thing to do on the server side is to activate the next player when we enter the &amp;lt;code&amp;gt;nextPlayer&amp;lt;/code&amp;gt; game state (in the &amp;lt;code&amp;gt;reversi.game.php&amp;lt;/code&amp;gt; file, under &amp;quot;Game state reactions&amp;quot;):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    function stNextPlayer(): void&lt;br /&gt;
    {&lt;br /&gt;
        // Active next player&lt;br /&gt;
        $player_id = intval($this-&amp;gt;activeNextPlayer());&lt;br /&gt;
&lt;br /&gt;
        // Check if both player has at least 1 discs, and if there are free squares to play&lt;br /&gt;
        $player_to_discs = $this-&amp;gt;getCollectionFromDb( &amp;quot;SELECT board_player, COUNT( board_x )&lt;br /&gt;
                                                       FROM board&lt;br /&gt;
                                                       GROUP BY board_player&amp;quot;, true );&lt;br /&gt;
&lt;br /&gt;
        if( ! isset( $player_to_discs[ null ] ) )&lt;br /&gt;
        {&lt;br /&gt;
            // Index 0 has not been set =&amp;gt; there&#039;s no more free place on the board !&lt;br /&gt;
            // =&amp;gt; end of the game&lt;br /&gt;
            $this-&amp;gt;gamestate-&amp;gt;nextState( &#039;endGame&#039; );&lt;br /&gt;
            return ;&lt;br /&gt;
        }&lt;br /&gt;
        else if( ! isset( $player_to_discs[ $player_id ] ) )&lt;br /&gt;
        {&lt;br /&gt;
            // Active player has no more disc on the board =&amp;gt; he looses immediately&lt;br /&gt;
            $this-&amp;gt;gamestate-&amp;gt;nextState( &#039;endGame&#039; );&lt;br /&gt;
            return ;&lt;br /&gt;
        }&lt;br /&gt;
        &lt;br /&gt;
        // Can this player play?&lt;br /&gt;
&lt;br /&gt;
        $possibleMoves = $this-&amp;gt;getPossibleMoves( $player_id );&lt;br /&gt;
        if( count( $possibleMoves ) == 0 )&lt;br /&gt;
        {&lt;br /&gt;
&lt;br /&gt;
            // This player can&#039;t play&lt;br /&gt;
            // Can his opponent play ?&lt;br /&gt;
            $opponent_id = (int)$this-&amp;gt;getUniqueValueFromDb( &amp;quot;SELECT player_id FROM player WHERE player_id!=&#039;$player_id&#039; &amp;quot; );&lt;br /&gt;
            if( count( $this-&amp;gt;getPossibleMoves( $opponent_id ) ) == 0 )&lt;br /&gt;
            {&lt;br /&gt;
                // Nobody can move =&amp;gt; end of the game&lt;br /&gt;
                $this-&amp;gt;gamestate-&amp;gt;nextState( &#039;endGame&#039; );&lt;br /&gt;
            }&lt;br /&gt;
            else&lt;br /&gt;
            {            &lt;br /&gt;
                // =&amp;gt; pass his turn&lt;br /&gt;
                $this-&amp;gt;gamestate-&amp;gt;nextState( &#039;cantPlay&#039; );&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
        else&lt;br /&gt;
        {&lt;br /&gt;
            // This player can play. Give him some extra time&lt;br /&gt;
            $this-&amp;gt;giveExtraTime( $player_id );&lt;br /&gt;
            $this-&amp;gt;gamestate-&amp;gt;nextState( &#039;nextTurn&#039; );&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Now, when we play a token, the rules are checked and the token appears in the database.&lt;br /&gt;
&lt;br /&gt;
[[File:reversi9.jpg]]&lt;br /&gt;
&lt;br /&gt;
Of course, as we don&#039;t manage notifications on client side, we need to press F5 after each move to see the changes on the board.&lt;br /&gt;
&lt;br /&gt;
== Make the move appear automatically ==&lt;br /&gt;
&lt;br /&gt;
Now, what we have to do is process the notifications sent by the server and make the move appear on the interface.&lt;br /&gt;
&lt;br /&gt;
In our &amp;lt;code&amp;gt;setupNotifications&amp;lt;/code&amp;gt; method in &amp;lt;code&amp;gt;reversi.js&amp;lt;/code&amp;gt;, we register 2 methods for the 2 notifications we created at the previous step (&amp;lt;code&amp;gt;playDisc&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;turnOverDiscs&amp;lt;/code&amp;gt;):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
            const notifs = [&lt;br /&gt;
                [&#039;playDisc&#039;, 500],&lt;br /&gt;
                [&#039;turnOverDiscs&#039;, 1500],&lt;br /&gt;
                [&#039;newScores&#039;, 1],&lt;br /&gt;
            ];&lt;br /&gt;
    &lt;br /&gt;
            notifs.forEach((notif) =&amp;gt; {&lt;br /&gt;
                dojo.subscribe(notif[0], this, `notif_${notif[0]}`);&lt;br /&gt;
                this.notifqueue.setSynchronous(notif[0], notif[1]);&lt;br /&gt;
            });&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We will associate each of our 3 notifications with a method prefixed with &amp;lt;code&amp;gt;notif_&amp;lt;/code&amp;gt;. We also define these notifications as &amp;quot;synchronous&amp;quot;, with a duration in millisecond. It tells the user interface to wait some time after executing the notification, to let the animation end before starting the next notification. In our specific case, the animation will be the following:&lt;br /&gt;
* Make a disc slide from the player panel to its place on the board&lt;br /&gt;
* (wait 500ms)&lt;br /&gt;
* Make all turned over discs blink (and of course turned them over)&lt;br /&gt;
* (wait 1500ms)&lt;br /&gt;
* Update the player scores&lt;br /&gt;
* (no real delay on this one)&lt;br /&gt;
&lt;br /&gt;
The second part of the code is a generic thing to automatically bind the notifs we configured to the &amp;lt;code&amp;gt;notif_&amp;lt;notifName&amp;gt;&amp;lt;/code&amp;gt; functions we are about to create.&lt;br /&gt;
&lt;br /&gt;
Let&#039;s have a look now on the &amp;lt;code&amp;gt;playDisc&amp;lt;/code&amp;gt; notification handler method:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
notif_playDisc: function( notif )&lt;br /&gt;
{&lt;br /&gt;
    // Remove current possible moves (makes the board more clear)&lt;br /&gt;
    document.querySelectorAll(&#039;.possibleMove&#039;).forEach(div =&amp;gt; div.classList.remove(&#039;possibleMove&#039;));&lt;br /&gt;
&lt;br /&gt;
    this.addDiscOnBoard( notif.args.x, notif.args.y, notif.args.player_id );&lt;br /&gt;
},&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
No surprise here, we re-used some existing stuff to:&lt;br /&gt;
* Remove the highlighted squares.&lt;br /&gt;
* Add a new disc on board, coming from player panel.&lt;br /&gt;
&lt;br /&gt;
Now, here&#039;s the method that handles the &amp;lt;code&amp;gt;turnOverDiscs&amp;lt;/code&amp;gt; notification:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
notif_turnOverDiscs: function( notif )&lt;br /&gt;
{&lt;br /&gt;
    // Get the color of the player who is returning the discs&lt;br /&gt;
    var targetColor = this.gamedatas.players[ notif.args.player_id ].color;&lt;br /&gt;
&lt;br /&gt;
    // Made these discs blinking and set them to the specified color&lt;br /&gt;
    for( var i in notif.args.turnedOver )&lt;br /&gt;
    {&lt;br /&gt;
        var disc = notif.args.turnedOver[ i ];&lt;br /&gt;
        &lt;br /&gt;
        // Make the disc blink 2 times&lt;br /&gt;
        var anim = dojo.fx.chain( [&lt;br /&gt;
            dojo.fadeOut( { node: &#039;disc_&#039;+disc.x+&#039;&#039;+disc.y } ),&lt;br /&gt;
            dojo.fadeIn( { node: &#039;disc_&#039;+disc.x+&#039;&#039;+disc.y } ),&lt;br /&gt;
            dojo.fadeOut( { &lt;br /&gt;
                            node: &#039;disc_&#039;+disc.x+&#039;&#039;+disc.y,&lt;br /&gt;
                            onEnd: node =&amp;gt; $(node).dataset.color = targetColor,&lt;br /&gt;
                            } ),&lt;br /&gt;
            dojo.fadeIn( { node: &#039;disc_&#039;+disc.x+&#039;&#039;+disc.y  } )&lt;br /&gt;
                            &lt;br /&gt;
        ] ); // end of dojo.fx.chain&lt;br /&gt;
&lt;br /&gt;
        // ... and launch the animation&lt;br /&gt;
        anim.play();                &lt;br /&gt;
    }&lt;br /&gt;
},&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The list of the discs to be turned over has been made available by our server side code in &amp;lt;code&amp;gt;notif.args.turnedOver&amp;lt;/code&amp;gt; (see previous paragraph). We loop through all these discs, and create a complex animation using &amp;lt;code&amp;gt;dojo.Animation&amp;lt;/code&amp;gt; for each of them. The complete documentation on dojo animations [http://dojotoolkit.org/documentation/tutorials/1.6/animation/ can be found here].&lt;br /&gt;
&lt;br /&gt;
In few words: we create a chain of 4 animations to make the disc fade out, fade in, fade out again, and fade in again. At the end of the second fade out, we change the color of the disc. Finally, we launch the animation with &amp;lt;code&amp;gt;play()&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
And Also the notification to update the scores:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
notif_newScores: function( notif )&lt;br /&gt;
        {&lt;br /&gt;
            for( var player_id in notif.args.scores )&lt;br /&gt;
            {&lt;br /&gt;
                var newScore = notif.args.scores[ player_id ];&lt;br /&gt;
                this.scoreCtrl[ player_id ].toValue( newScore );&lt;br /&gt;
            }&lt;br /&gt;
        },&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Category:Studio]]&lt;/div&gt;</summary>
		<author><name>Sguzzer Gunayer</name></author>
	</entry>
	<entry>
		<id>https://en.doc.boardgamearena.com/index.php?title=Tutorial_reversi&amp;diff=22417</id>
		<title>Tutorial reversi</title>
		<link rel="alternate" type="text/html" href="https://en.doc.boardgamearena.com/index.php?title=Tutorial_reversi&amp;diff=22417"/>
		<updated>2024-09-03T14:53:15Z</updated>

		<summary type="html">&lt;p&gt;Sguzzer Gunayer: /* Set Token Colors in setupNewGame in .game.php file */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&#039;&#039;&#039;Check out an update version&#039;&#039;&#039; of the [[BGA Type Safe Template: Reversi|Reversi Tutorial]] which uses the [[BGA Type Safe Template]]. {{Studio_Framework_Navigation}}&lt;br /&gt;
&lt;br /&gt;
== Introduction ==&lt;br /&gt;
&lt;br /&gt;
Using this tutorial, you can build a complete working game on the BGA environment: Reversi.&lt;br /&gt;
&lt;br /&gt;
Before you read this tutorial, you must:&lt;br /&gt;
* Read the overall presentations of the BGA Framework ([[Studio|see here]]).&lt;br /&gt;
* Know the [http://en.wikipedia.org/wiki/Reversi#Rules rules of Reversi].&lt;br /&gt;
* Know the languages used on BGA: PHP, SQL, HTML, CSS, Javascript&lt;br /&gt;
* &#039;&#039;&#039;Setup your development environment&#039;&#039;&#039; [http://en.doc.boardgamearena.com/First_steps_with_BGA_Studio First Steps with BGA Studio]&lt;br /&gt;
&lt;br /&gt;
== Create your first game ==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Note: you should already have created a project following instructions in [[First_steps_with_BGA_Studio#Create_a_new_game_project|Create a new game project]]. While you will find a &#039;&#039;&#039;reversi&#039;&#039;&#039; directory in your SFTP folder, do not use it for this tutorial. Instead, use the project you have created as an (empty) starting point.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
With the initial skeleton of code provided in your project, you can already start a game from the BGA Studio:&lt;br /&gt;
* Go to your [https://studio.boardgamearena.com/controlpanel studio Control panel], then Manage games and select your initial project. &#039;&#039;Note: there are warnings displayed about a missing BGG_ID and presentation text. You can ignore that for now.&#039;&#039;&lt;br /&gt;
* Click the Play link next to your project name. This will open the Play page and offer to create a new table for your project. &#039;&#039;Optional: click the Heart icon to add your project to your favorite games list.&#039;&#039;&lt;br /&gt;
* On the Play page, on the top of the page, make sure that your settings are &amp;quot;Simple game&amp;quot;, &amp;quot;Real time&amp;quot; and &amp;quot;Manual&amp;quot;.&lt;br /&gt;
* Click &amp;quot;Create table&amp;quot; to create a table of your project. &lt;br /&gt;
* For now, we are going to work with one player only, so use the (-) button to set the number of players to 1. Most of the time it is simpler to proceed with only one player during the early phase of development of your game, as it&#039;s easy and fast to start/stop games. If you choose to start with 2 players, you should see two names on the right: testdude0 and testdude1. To switch between them, press the red arrow button near their names; it will open another tab. This way you don&#039;t need to login and logout from multiple accounts.) &lt;br /&gt;
* Reminder: Always use the &amp;quot;Express Start&amp;quot; button to start the game.&lt;br /&gt;
&lt;br /&gt;
Thus, you can start a &amp;quot;Reversi&amp;quot; game, and arrive on a void, empty game. Yeah.&lt;br /&gt;
&lt;br /&gt;
End the game by clicking on the game options icon on the top right, and then on &amp;quot;Express Stop&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
== Editing the game information (Optional) ==&lt;br /&gt;
&lt;br /&gt;
This step is optional and will fix the warnings on the project page (missing BGG_ID and presentation).&lt;br /&gt;
&lt;br /&gt;
==== Edits to fix Errors ====&lt;br /&gt;
* Edit your local copy of the &amp;lt;code&amp;gt;gameinfos.inc.php&amp;lt;/code&amp;gt; file:&lt;br /&gt;
** Change the &amp;lt;code&amp;gt;bgg_id&amp;lt;/code&amp;gt; value from &amp;lt;code&amp;gt;0&amp;lt;/code&amp;gt; to &amp;lt;code&amp;gt;2389&amp;lt;/code&amp;gt; - that&#039;s around line 37.&lt;br /&gt;
** Add &amp;lt;code&amp;gt;1,&amp;lt;/code&amp;gt; to the players array - that&#039;s around line 41.&lt;br /&gt;
** Change the presentation array content - that&#039;s around line 134. Uncomment one line and change the text. Remove the final comma if you keep only one line!&lt;br /&gt;
* Upload the &amp;lt;code&amp;gt;gameinfos.inc.php&amp;lt;/code&amp;gt; file to the SFTP server (see [[First_steps_with_BGA_Studio#Connect_to_your_SFTP_folder|Connect to your SFTP folder]]).&lt;br /&gt;
&lt;br /&gt;
==== Test your Edits ====&lt;br /&gt;
* Go back to your project page, and in the &amp;quot;Game Information&amp;quot; section, click &amp;quot;Reload game informations&amp;quot;.&lt;br /&gt;
* Finally, refresh the project page in your browser (usually CTRL-F5).&lt;br /&gt;
&lt;br /&gt;
===== Not working? =====&lt;br /&gt;
Some changes will require bypassing the cache. It is often worth doing a hard refresh to make sure the&lt;br /&gt;
&lt;br /&gt;
Sometimes the cache will keep your changes from showing. Since this is a possibility, it will be useful to know how to bypass the cache. To do so you may manually clear cache or use a shortcut to refresh and ignore the cached version of the page. Here&#039;s how&lt;br /&gt;
&lt;br /&gt;
====== Windows ======&lt;br /&gt;
Chrome, Firefox, or Edge: Press &amp;lt;code&amp;gt;Ctrl+F5&amp;lt;/code&amp;gt; or &amp;lt;code&amp;gt;Shift+F5&amp;lt;/code&amp;gt; or &amp;lt;code&amp;gt;Ctrl+Shift+R&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====== Mac ======&lt;br /&gt;
Chrome or Firefox: Press &amp;lt;code&amp;gt;Shift+Command+R&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Safari for Mac: Press &amp;lt;code&amp;gt;Command+Option+E&amp;lt;/code&amp;gt; to empty the cache, then hold down Shift and click Reload in the toolbar&lt;br /&gt;
&lt;br /&gt;
== Make it look like Reversi ==&lt;br /&gt;
&lt;br /&gt;
Let&#039;s start with the board. This will give you a good idea of how things will look and where tokens should go.&lt;br /&gt;
&lt;br /&gt;
Be careful designing the layout of your game: you must always keep in mind that players with a 1024px screen width must be able to play. Usually, it means that the width of the play area can be 750px (in the worst case).&lt;br /&gt;
&lt;br /&gt;
For Reversi, it&#039;s useless to have a 750x750px board - much too big, so we chose this one which fit perfectly (536x528):&lt;br /&gt;
&lt;br /&gt;
[[File:Board.jpg]]&lt;br /&gt;
&lt;br /&gt;
Note that we are using a jpg file. Jpg files are lighter than png, so they are faster to load. Later, we are going to use PNGs for tokens because they allow for transparency.&lt;br /&gt;
&lt;br /&gt;
==== Add the board ====&lt;br /&gt;
use lowercase file names&lt;br /&gt;
* upload &amp;lt;code&amp;gt;board.jpg&amp;lt;/code&amp;gt; in your &amp;lt;code&amp;gt;img/&amp;lt;/code&amp;gt; directory. &lt;br /&gt;
* edit &amp;lt;code&amp;gt;reversi_reversi.tpl&amp;lt;/code&amp;gt; to add a &amp;lt;code&amp;gt;div&amp;lt;/code&amp;gt; for your board.&lt;br /&gt;
&lt;br /&gt;
Note: If you are building this game by following the tutorial, you will have a different project name than &amp;lt;code&amp;gt;reversi&amp;lt;/code&amp;gt; (i.e. &amp;lt;code&amp;gt;mygame_mygame.tpl&amp;lt;/code&amp;gt;). The file names in your project will be different than shown in this tutorial, replacing &amp;lt;code&amp;gt;reversi&amp;lt;/code&amp;gt; with your project name. Be sure that any code (other than comments) that references &amp;lt;code&amp;gt;reversi&amp;lt;/code&amp;gt; is changed to your actual project name.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;div id=&amp;quot;board&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* edit your &amp;lt;code&amp;gt;reversi.css&amp;lt;/code&amp;gt; file to transform it into a visible board:&lt;br /&gt;
&lt;br /&gt;
 #board {&lt;br /&gt;
    width: 536px;&lt;br /&gt;
    height: 528px;&lt;br /&gt;
    background-image: url(&#039;img/board.jpg&#039;);&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Important: refresh your page.&#039;&#039;&#039; Here&#039;s your board:[[File:reversi1.jpg]]&lt;br /&gt;
&lt;br /&gt;
If the board does not appear, refresh the page (always do this when you update the CSS file), and check the image filename. Remember file names are case sensitive!&lt;br /&gt;
&lt;br /&gt;
==== Code the Grid ====&lt;br /&gt;
Now, we need to create some invisible HTML elements where squares are. These elements will be used as position references for the white and black tokens. &lt;br /&gt;
&lt;br /&gt;
===== Build the grid of squares =====&lt;br /&gt;
The board is 8 squares by 8 squares. This means we need 64 squares. To avoid writing 64 individual &amp;lt;code&amp;gt;div&amp;lt;/code&amp;gt; elements on our template, we are going to generate the squares on JS setup.&lt;br /&gt;
&lt;br /&gt;
We&#039;ll do this in our Javascript &amp;lt;code&amp;gt;setup&amp;lt;/code&amp;gt; method under &amp;lt;code&amp;gt;// TODO: Set up your game interface here, according to &amp;quot;gamedatas&amp;quot;&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
const board = document.getElementById(&#039;board&#039;);&lt;br /&gt;
const hor_scale = 64.8;&lt;br /&gt;
const ver_scale = 64.4;&lt;br /&gt;
for (let x=1; x&amp;lt;=8; x++) {&lt;br /&gt;
    for (let y=1; y&amp;lt;=8; y++) {&lt;br /&gt;
        const left = Math.round((x - 1) * hor_scale + 10);&lt;br /&gt;
        const top = Math.round((y - 1) * ver_scale + 7);&lt;br /&gt;
        // we use afterbegin to make sure squares are placed before discs&lt;br /&gt;
        board.insertAdjacentHTML(`afterbegin`, `&amp;lt;div id=&amp;quot;square_${x}_${y}&amp;quot; class=&amp;quot;square&amp;quot; style=&amp;quot;left: ${left}px; top: ${top}px;&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;`);&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note: as you can see, squares in our &amp;lt;code&amp;gt;board.jpg&amp;lt;/code&amp;gt; files do not have an exact width/height in pixels, and that&#039;s the reason we are using floating point numbers here.&lt;br /&gt;
&lt;br /&gt;
===== Style Those Squares =====&lt;br /&gt;
Now, to finish our work and check if everything works fine, we are going to style our square a little bit in our CSS stylesheet:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#board {&lt;br /&gt;
    width: 536px;&lt;br /&gt;
    height: 528px;&lt;br /&gt;
    background-image: url(&#039;img/board.jpg&#039;);&lt;br /&gt;
    position: relative;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.square {&lt;br /&gt;
    width: 62px;&lt;br /&gt;
    height: 62px;&lt;br /&gt;
    position: absolute;&lt;br /&gt;
    background-color: red;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Explanations:&lt;br /&gt;
* With &amp;quot;position: relative&amp;quot; on board, we ensure square elements are positioned relatively to board.&lt;br /&gt;
* &amp;lt;code&amp;gt;background-color: red;&amp;lt;/code&amp;gt; is used for testing. This allows us to see the invisible elements. (You could instead do something like &amp;lt;code&amp;gt;outline: 2px solid orange;&amp;lt;/code&amp;gt; have fun and be creative)&lt;br /&gt;
&lt;br /&gt;
Let&#039;s refresh and check our (beautiful) squares:&lt;br /&gt;
&lt;br /&gt;
[[File:reversi2.jpg]]&lt;br /&gt;
&lt;br /&gt;
Now that you know the squares are there, you can remove the test line &amp;lt;code&amp;gt;background-color: red;&amp;lt;/code&amp;gt;  from your &amp;lt;code&amp;gt;.square&amp;lt;/code&amp;gt; class in the CSS stylesheet.&lt;br /&gt;
&lt;br /&gt;
===== Not Working? =====&lt;br /&gt;
If the styled squares do not appear, inspect and check your css (Chrome DevTools: Application &amp;gt; Frames &amp;gt; top &amp;gt; Stylesheets &amp;gt; reversi.css). &lt;br /&gt;
&lt;br /&gt;
== The Tokens ==&lt;br /&gt;
&lt;br /&gt;
Now, our board is ready for some tokens!&lt;br /&gt;
&lt;br /&gt;
[Note: Throughout this tutorial, sometimes &amp;quot;tokens&amp;quot; is used, and sometimes &amp;quot;discs&amp;quot; is used. They are often swapped if you&#039;re looking at code in the reversi example project.]&lt;br /&gt;
&lt;br /&gt;
=== Build the Token ===&lt;br /&gt;
There are quite a few steps before the tokens will appear. You may be used to testing after every change, but that won&#039;t work well here. The token will &#039;&#039;&#039;not&#039;&#039;&#039; show until you have add styles to the css, js template to the tpl, utility method in the js,  adjusted the php file, and added the token to the board in the js file.&lt;br /&gt;
&lt;br /&gt;
==== HTML in the .tpl file ====&lt;br /&gt;
At first, we introduce a new &#039;div&#039; element as a child of &amp;quot;board&amp;quot; to host all these tokens (in our template):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;div id=&amp;quot;board&amp;quot;&amp;gt;&lt;br /&gt;
    &lt;br /&gt;
    &amp;lt;div id=&amp;quot;discs&amp;quot;&amp;gt;&lt;br /&gt;
    &amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note: &amp;lt;code&amp;gt;discs&amp;lt;/code&amp;gt; is plural. This div will be used to hold the token divs. Shortly, we will use javascript to add individual tokens to the board.&lt;br /&gt;
&lt;br /&gt;
==== Add Token to img directory ====&lt;br /&gt;
Here&#039;s a new piece of art with the tokens. We need transparency here so we are using a png file:&lt;br /&gt;
&lt;br /&gt;
[[File:tokens.png]]&lt;br /&gt;
&lt;br /&gt;
Upload this image file &amp;lt;code&amp;gt;tokens.png&amp;lt;/code&amp;gt; in your &amp;lt;code&amp;gt;img/&amp;lt;/code&amp;gt; directory.&lt;br /&gt;
&lt;br /&gt;
Important Fun Fact: we are using ONE file for both tokens. It is really important to use a minimum number of graphic files for your game. This is called the &amp;quot;CSS sprite&amp;quot; technique, because it makes the game load faster and more reliable. [http://www.w3schools.com/css/css_image_sprites.asp Read more about CSS sprites].&lt;br /&gt;
&lt;br /&gt;
==== Style the Tokens in .css file ====&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
.disc {&lt;br /&gt;
    width: 56px;&lt;br /&gt;
    height: 56px;&lt;br /&gt;
    position: absolute;&lt;br /&gt;
    background-image: url(&#039;img/tokens.png&#039;);&lt;br /&gt;
    background-size: auto 100%;&lt;br /&gt;
}&lt;br /&gt;
.disc[data-color=&amp;quot;ffffff&amp;quot;] { background-position-x: 0%; }&lt;br /&gt;
.disc[data-color=&amp;quot;000000&amp;quot;] { background-position-x: 100%; }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
With this CSS code, we can set and change the token color by changing the data-color attribute. Using data instead of a class ensures it can be only one of them (the disc cannot be black and white at the same time).&lt;br /&gt;
&lt;br /&gt;
Note the &amp;quot;&amp;lt;code&amp;gt;position: absolute&amp;lt;/code&amp;gt;&amp;quot; which allows us to position tokens on the board and make them &amp;quot;slide&amp;quot; to their positions.&lt;br /&gt;
&lt;br /&gt;
==== Add Token Utility Method in .js file ====&lt;br /&gt;
Now, let&#039;s make the first token appear on our board. Tokens are not visible at the beginning of the game: they appear dynamically during the game. For this reason, we are going to make them appear from our Javascript code, using a template string&lt;br /&gt;
&lt;br /&gt;
Let&#039;s create a method in our Javascript code (in the &amp;lt;code&amp;gt;reversi.js&amp;lt;/code&amp;gt; file) that will make a token appear on the board, using this template. Add under the section //// Utility methods:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
addDiscOnBoard: function( x, y, player )&lt;br /&gt;
{&lt;br /&gt;
    var color = this.gamedatas.players[ player ].color;&lt;br /&gt;
    &lt;br /&gt;
    document.getElementById(&#039;discs&#039;).insertAdjacentHTML(&#039;beforeend&#039;, `&amp;lt;div class=&amp;quot;disc&amp;quot; data-color=&amp;quot;${color}&amp;quot; id=&amp;quot;disc_${x}${y}&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;`);&lt;br /&gt;
    &lt;br /&gt;
    this.placeOnObject( `disc_${x}${y}`, &#039;overall_player_board_&#039;+player );&lt;br /&gt;
    this.slideToObject( `disc_${x}${y}`, &#039;square_&#039;+x+&#039;_&#039;+y ).play();&lt;br /&gt;
},  &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===== Utility Method Explanation =====&lt;br /&gt;
* with &amp;lt;code&amp;gt;element.insertAdjacentHTML&amp;lt;/code&amp;gt; method, we create a HTML piece of code and insert it as a new child of &amp;lt;code&amp;gt;tokens&amp;lt;/code&amp;gt; div element.&lt;br /&gt;
* with &amp;lt;code&amp;gt;this.placeOnObject&amp;lt;/code&amp;gt; BGA method, we place this element over the panel of some player. &lt;br /&gt;
* Immediately after, using &amp;lt;code&amp;gt;this.slideToObject&amp;lt;/code&amp;gt; BGA method, we make the token slide to the &amp;lt;code&amp;gt;square&amp;lt;/code&amp;gt; element, its final destination.&lt;br /&gt;
* &amp;lt;code&amp;gt;&#039;overall_player_board_&#039;+player&amp;lt;/code&amp;gt; refers to the div element that contains each player&#039;s information and avatar. By initially placing the token here, it gives the effect that the player&#039;s avatar is throwing the token onto the board.&lt;br /&gt;
&lt;br /&gt;
Note: don&#039;t forget to call the &amp;lt;code&amp;gt;play()&amp;lt;/code&amp;gt;, otherwise the token will remain at its original location.&lt;br /&gt;
&lt;br /&gt;
Note: during this process, the parent of the new token HTML element will stay &amp;lt;code&amp;gt;tokens&amp;lt;/code&amp;gt;. &amp;lt;code&amp;gt;placeOnObject&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;slideToObject&amp;lt;/code&amp;gt; methods are &#039;&#039;only&#039;&#039; moving the position of elements on screen, and they are &#039;&#039;not&#039;&#039; modifying the HTML tree.&lt;br /&gt;
&lt;br /&gt;
==== Set Token Colors in setupNewGame in .game.php file ====&lt;br /&gt;
Before we can show a token, we need to set the player colors in the &amp;lt;code&amp;gt;setupNewGame&amp;lt;/code&amp;gt; function in &amp;lt;code&amp;gt;reversi.game.php&amp;lt;/code&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
Replace &amp;lt;code&amp;gt;$default_colors = $gameinfos[&#039;player_colors&#039;];&amp;lt;/code&amp;gt; with the following line:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        $default_colors = array( &amp;quot;ffffff&amp;quot;, &amp;quot;000000&amp;quot; );&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note: A few lines below, you may have to remove the line &amp;lt;code&amp;gt;this-&amp;gt;reattributeColorsBasedOnPreferences( $players, $gameinfos[&#039;player_colors&#039;] );&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Test the Token ===&lt;br /&gt;
Now, to test if everything works fine&lt;br /&gt;
&lt;br /&gt;
==== addTokenOnBoard() in .js file to Test ====&lt;br /&gt;
In &amp;lt;code&amp;gt;reversi.js&amp;lt;/code&amp;gt;, in &amp;lt;code&amp;gt;setup: function&amp;lt;/code&amp;gt;, under the code we added to generate the squares. &lt;br /&gt;
 this.addDiscOnBoard( 2, 2, this.player_id );&lt;br /&gt;
Now restart the game.&lt;br /&gt;
&lt;br /&gt;
A token should appear and slide immediately to its position, like this:&lt;br /&gt;
&lt;br /&gt;
[[File:reversi3.jpg]]&lt;br /&gt;
&lt;br /&gt;
== The database ==&lt;br /&gt;
&lt;br /&gt;
We did most of the client-side programming, so let&#039;s have a look on the other side now. To design the database model of our game, you will need to access the database. You won&#039;t need to do anything in database UI, yet.&lt;br /&gt;
&lt;br /&gt;
=== Accessing the Database ===&lt;br /&gt;
To access the database, start a game, then click &amp;quot;Go to game database&amp;quot; link at the bottom of our game, to access the database directly with a PhpMyAdmin instance.&lt;br /&gt;
&lt;br /&gt;
After the first time you&#039;ve acess the database, you could skip opening a game and instead, go to https://studio.boardgamearena.com/db/ . Your PhpMyAdmin username/password is in your welcome email.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note&#039;&#039;&#039;: do not remove existing tables&lt;br /&gt;
&lt;br /&gt;
=== Create Table in .sql file ===&lt;br /&gt;
Now, you are able to create the table(s) you need for your game, and report every SQL command used in your &amp;lt;code&amp;gt;dbmodel.sql&amp;lt;/code&amp;gt; file. &lt;br /&gt;
&lt;br /&gt;
The database model of Reversi is short: just one table with the squares of the board. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
CREATE TABLE IF NOT EXISTS `board` (&lt;br /&gt;
  `board_x` smallint(5) unsigned NOT NULL,&lt;br /&gt;
  `board_y` smallint(5) unsigned NOT NULL,&lt;br /&gt;
  `board_player` int(10) unsigned DEFAULT NULL,&lt;br /&gt;
  PRIMARY KEY (`board_x`,`board_y`)&lt;br /&gt;
) ENGINE=InnoDB DEFAULT CHARSET=utf8;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Add the above SQL to &amp;lt;code&amp;gt;dbmodel.sql&amp;lt;/code&amp;gt;. Pay special attention to the backtick &amp;lt;code&amp;gt;`&amp;lt;/code&amp;gt; character vs. the single quote &amp;lt;code&amp;gt;&#039;&amp;lt;/code&amp;gt; when working with SQL. &lt;br /&gt;
&lt;br /&gt;
=== Test the Table ===&lt;br /&gt;
Now, a new database with a &amp;lt;code&amp;gt;board&amp;lt;/code&amp;gt; table will be created each time we start a Reversi game. This is why after modifying our &amp;lt;code&amp;gt;dbmodel.sql&amp;lt;/code&amp;gt; it&#039;s a good time to stop your current game &amp;amp; start a new game.&lt;br /&gt;
&lt;br /&gt;
Start a new game and verify a table is created.&lt;br /&gt;
&lt;br /&gt;
== Setup the initial game position ==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note&#039;&#039;&#039;: From now on, you must launch the game with &#039;&#039;&#039;two players&#039;&#039;&#039; to get two &amp;lt;code&amp;gt;player_id&amp;lt;/code&amp;gt;s within the database. Otherwise, the game will crash.&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;setupNewGame&amp;lt;/code&amp;gt; method of our &amp;lt;code&amp;gt;reversi.game.php&amp;lt;/code&amp;gt; is called during initial setup. This initializes our data and places the starting tokens on the board. At the beginning of the game, there should be 4 tokens on the board.&lt;br /&gt;
&lt;br /&gt;
=== Initialize the Board in .game.php file ===&lt;br /&gt;
Under &amp;lt;code&amp;gt;// TODO: setup the initial game situation here&amp;lt;/code&amp;gt;, initialize the board&amp;lt;pre&amp;gt;&lt;br /&gt;
        // Init the board&lt;br /&gt;
        $sql = &amp;quot;INSERT INTO board (board_x,board_y,board_player) VALUES &amp;quot;;&lt;br /&gt;
        $sql_values = array();&lt;br /&gt;
        list( $blackplayer_id, $whiteplayer_id ) = array_keys( $players );&lt;br /&gt;
        for( $x=1; $x&amp;lt;=8; $x++ )&lt;br /&gt;
        {&lt;br /&gt;
            for( $y=1; $y&amp;lt;=8; $y++ )&lt;br /&gt;
            {&lt;br /&gt;
                $token_value = &amp;quot;NULL&amp;quot;;&lt;br /&gt;
                if( ($x==4 &amp;amp;&amp;amp; $y==4) || ($x==5 &amp;amp;&amp;amp; $y==5) )  // Initial positions of white player&lt;br /&gt;
                    $token_value = &amp;quot;&#039;$whiteplayer_id&#039;&amp;quot;;&lt;br /&gt;
                else if( ($x==4 &amp;amp;&amp;amp; $y==5) || ($x==5 &amp;amp;&amp;amp; $y==4) )  // Initial positions of black player&lt;br /&gt;
                    $token_value = &amp;quot;&#039;$blackplayer_id&#039;&amp;quot;;&lt;br /&gt;
                    &lt;br /&gt;
                $sql_values[] = &amp;quot;(&#039;$x&#039;,&#039;$y&#039;,$token_value)&amp;quot;;&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
        $sql .= implode( &#039;,&#039;, $sql_values );&lt;br /&gt;
        $this-&amp;gt;DbQuery( $sql );&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Board Initialization Explanation ====&lt;br /&gt;
&lt;br /&gt;
* We create one table entry for each square, with a &amp;lt;code&amp;gt;NULL&amp;lt;/code&amp;gt; value which means &amp;quot;empty square&amp;quot;&lt;br /&gt;
* On 4 of the squares, we place an initial token.&lt;br /&gt;
&lt;br /&gt;
After this, we set &amp;lt;code&amp;gt;activeNextPlayer&amp;lt;/code&amp;gt; to make the first player active at the beginning of the game (this line is already present in the default code template).&lt;br /&gt;
&lt;br /&gt;
If you didn&#039;t do it earlier, you need to remove the call to &amp;lt;code&amp;gt;self::reattributeColorsBasedOnPreferences()&amp;lt;/code&amp;gt; in &amp;lt;code&amp;gt;SetupNewGame()&amp;lt;/code&amp;gt;. If you don&#039;t, player color preferences will try (and fail) to override the two colors supported here.&lt;br /&gt;
&lt;br /&gt;
=== Show the Initial Token Setup ===&lt;br /&gt;
Now, we need to make these tokens appear on the client side. The first step is to return the token positions with our &amp;lt;code&amp;gt;getAllDatas()&amp;lt;/code&amp;gt; PHP method. &amp;lt;code&amp;gt;getAllDatas()&amp;lt;/code&amp;gt; is called during each page reload.&lt;br /&gt;
&lt;br /&gt;
In the &amp;lt;code&amp;gt;getAllDatas()&amp;lt;/code&amp;gt; method, after &amp;lt;code&amp;gt;// TODO: Gather all information about current game situation (visible by player $current_player_id)&amp;lt;/code&amp;gt;, add the following lines:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        // Get reversi board token&lt;br /&gt;
        $result[&#039;board&#039;] = self::getObjectListFromDB( &amp;quot;SELECT board_x x, board_y y, board_player player&lt;br /&gt;
                                                       FROM board&lt;br /&gt;
                                                       WHERE board_player IS NOT NULL&amp;quot; );&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Next, you may need to modify the query that gets player information to also get the player&#039;s colors. This is in the variable &amp;lt;code&amp;gt;$sql&amp;lt;/code&amp;gt;, above the lines you just inserted in &amp;lt;code&amp;gt;getAllDatas()&amp;lt;/code&amp;gt;. Below is what the line will look like. Notice how we&#039;ve added &amp;lt;code&amp;gt;player_color color&amp;lt;/code&amp;gt; to the sql query.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$sql = &amp;quot;SELECT player_id id, player_score score, player_color color FROM player &amp;quot;;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
We are using the BGA framework&#039;s &amp;lt;code&amp;gt;getObjectListFromDB()&amp;lt;/code&amp;gt; that formats the result of this SQL query in a PHP array with x, y and player attributes. We add it to the result associative array with the key &amp;lt;code&amp;gt;board&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Last, we process this array client side. Let&#039;s place a token on the board for each array item. We&#039;ll do this in our Javascript &amp;lt;code&amp;gt;setup&amp;lt;/code&amp;gt; method under the code we added to generate the squares. &lt;br /&gt;
&lt;br /&gt;
This will result in a removal or edit of the previously added line &amp;lt;code&amp;gt;this.addDiscOnBoard(2, 2, this.player_id);&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
for( var i in gamedatas.board )&lt;br /&gt;
{&lt;br /&gt;
    var square = gamedatas.board[i];&lt;br /&gt;
    &lt;br /&gt;
    if( square.player !== null )&lt;br /&gt;
    {&lt;br /&gt;
        this.addDiscOnBoard( square.x, square.y, square.player );&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;board&amp;lt;/code&amp;gt; entry created in &amp;lt;code&amp;gt;getAllDatas()&amp;lt;/code&amp;gt; is used here as &amp;lt;code&amp;gt;gamedatas.board&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Test the Game Start ===&lt;br /&gt;
Reload... and here we are:&lt;br /&gt;
&lt;br /&gt;
[[File:reversi5.jpg]]&lt;br /&gt;
&lt;br /&gt;
It starts to feel like Reversi here...&lt;br /&gt;
&lt;br /&gt;
== The game state machine ==&lt;br /&gt;
&lt;br /&gt;
Stop your game, again. You&#039;re about to start the core game logic.&lt;br /&gt;
&lt;br /&gt;
You already read [http://www.slideshare.net/boardgamearena/bga-studio-focus-on-bga-game-state-machine Focus on BGA game state machine], so you know that this is the heart of your game logic. For reversi, it&#039;s relatively simple. Here&#039;s a diagram of our game state machine:&lt;br /&gt;
&lt;br /&gt;
[[File:reversi6.jpg]]&lt;br /&gt;
&lt;br /&gt;
=== Build your States ===&lt;br /&gt;
And here&#039;s our &amp;lt;code&amp;gt;states.inc.php&amp;lt;/code&amp;gt;, according to this diagram:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$machinestates = array(&lt;br /&gt;
&lt;br /&gt;
    ST_BGA_GAME_SETUP =&amp;gt; array(&lt;br /&gt;
        &amp;quot;name&amp;quot; =&amp;gt; &amp;quot;gameSetup&amp;quot;,&lt;br /&gt;
        &amp;quot;description&amp;quot; =&amp;gt; clienttranslate(&amp;quot;Game setup&amp;quot;),&lt;br /&gt;
        &amp;quot;type&amp;quot; =&amp;gt; &amp;quot;manager&amp;quot;,&lt;br /&gt;
        &amp;quot;action&amp;quot; =&amp;gt; &amp;quot;stGameSetup&amp;quot;,&lt;br /&gt;
        &amp;quot;transitions&amp;quot; =&amp;gt; array( &amp;quot;&amp;quot; =&amp;gt; ST_PLAYER_PLAY_DISC )&lt;br /&gt;
    ),&lt;br /&gt;
    &lt;br /&gt;
    ST_PLAYER_PLAY_DISC =&amp;gt; array(&lt;br /&gt;
        &amp;quot;name&amp;quot; =&amp;gt; &amp;quot;playerTurn&amp;quot;,&lt;br /&gt;
		&amp;quot;description&amp;quot; =&amp;gt; clienttranslate(&#039;${actplayer} must play a disc&#039;),&lt;br /&gt;
		&amp;quot;descriptionmyturn&amp;quot; =&amp;gt; clienttranslate(&#039;${you} must play a disc&#039;),&lt;br /&gt;
        &amp;quot;type&amp;quot; =&amp;gt; &amp;quot;activeplayer&amp;quot;,&lt;br /&gt;
        &amp;quot;args&amp;quot; =&amp;gt; &amp;quot;argPlayerTurn&amp;quot;,&lt;br /&gt;
        &amp;quot;possibleactions&amp;quot; =&amp;gt; array( &#039;actPlayDisc&#039; ),&lt;br /&gt;
        &amp;quot;transitions&amp;quot; =&amp;gt; array( &amp;quot;playDisc&amp;quot; =&amp;gt; ST_NEXT_PLAYER, &amp;quot;zombiePass&amp;quot; =&amp;gt; ST_NEXT_PLAYER )&lt;br /&gt;
    ),&lt;br /&gt;
    &lt;br /&gt;
    ST_NEXT_PLAYER =&amp;gt; array(&lt;br /&gt;
        &amp;quot;name&amp;quot; =&amp;gt; &amp;quot;nextPlayer&amp;quot;,&lt;br /&gt;
        &amp;quot;type&amp;quot; =&amp;gt; &amp;quot;game&amp;quot;,&lt;br /&gt;
        &amp;quot;action&amp;quot; =&amp;gt; &amp;quot;stNextPlayer&amp;quot;,&lt;br /&gt;
        &amp;quot;updateGameProgression&amp;quot; =&amp;gt; true,        &lt;br /&gt;
        &amp;quot;transitions&amp;quot; =&amp;gt; array( &amp;quot;nextTurn&amp;quot; =&amp;gt; ST_PLAYER_PLAY_DISC, &amp;quot;cantPlay&amp;quot; =&amp;gt; ST_NEXT_PLAYER, &amp;quot;endGame&amp;quot; =&amp;gt; ST_END_GAME )&lt;br /&gt;
    ),&lt;br /&gt;
   &lt;br /&gt;
    ST_END_GAME =&amp;gt; array(&lt;br /&gt;
        &amp;quot;name&amp;quot; =&amp;gt; &amp;quot;gameEnd&amp;quot;,&lt;br /&gt;
        &amp;quot;description&amp;quot; =&amp;gt; clienttranslate(&amp;quot;End of game&amp;quot;),&lt;br /&gt;
        &amp;quot;type&amp;quot; =&amp;gt; &amp;quot;manager&amp;quot;,&lt;br /&gt;
        &amp;quot;action&amp;quot; =&amp;gt; &amp;quot;stGameEnd&amp;quot;,&lt;br /&gt;
        &amp;quot;args&amp;quot; =&amp;gt; &amp;quot;argGameEnd&amp;quot;&lt;br /&gt;
    )&lt;br /&gt;
&lt;br /&gt;
);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We used constants to give an index to the different states. This is to avoid mistakes when we reuse these indexes on the transitions array.&lt;br /&gt;
&lt;br /&gt;
Let&#039;s create a file you&#039;ll put in modules/php/constants.inc.php :&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;?php&lt;br /&gt;
&lt;br /&gt;
/*&lt;br /&gt;
 * State constants&lt;br /&gt;
 */&lt;br /&gt;
const ST_BGA_GAME_SETUP = 1;&lt;br /&gt;
&lt;br /&gt;
const ST_PLAYER_PLAY_DISC = 10;&lt;br /&gt;
const ST_NEXT_PLAYER = 11;&lt;br /&gt;
&lt;br /&gt;
const ST_END_GAME = 99;&lt;br /&gt;
&lt;br /&gt;
?&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You will also need to add &amp;lt;code&amp;gt;require_once(&amp;quot;modules/php/constants.inc.php&amp;quot;);&amp;lt;/code&amp;gt; at the beginning of the state.inc.php to load these constants.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Now, in &amp;lt;code&amp;gt;reversi.game.php&amp;lt;/code&amp;gt; let&#039;s create the methods that are declared in this game states description file:&lt;br /&gt;
* &amp;lt;code&amp;gt;argPlayerTurn&amp;lt;/code&amp;gt;: referenced in the &amp;lt;code&amp;gt;args&amp;lt;/code&amp;gt; property of the &amp;lt;code&amp;gt;playerTurn&amp;lt;/code&amp;gt; state; this is the name of the method to call to retrieve arguments for this gamestate. Arguments are sent to the client side to be used on &amp;lt;code&amp;gt;onEnteringState&amp;lt;/code&amp;gt; or to set arguments in the gamestate description.&lt;br /&gt;
* &amp;lt;code&amp;gt;stNextPlayer&amp;lt;/code&amp;gt;: referenced in the &amp;lt;code&amp;gt;action&amp;lt;/code&amp;gt; property of the &amp;lt;code&amp;gt;nextPlayer&amp;lt;/code&amp;gt; state; this is the name of the method to call when this game state become the current game state.&lt;br /&gt;
&lt;br /&gt;
=== Test Your States ===&lt;br /&gt;
... and start a new Reversi game.&lt;br /&gt;
&lt;br /&gt;
As you can see on the screen capture below, the BGA framework makes the game jump to our first game state &amp;lt;code&amp;gt;playerTurn&amp;lt;/code&amp;gt; right after the initial setup. That&#039;s why the status bar contains the description of &amp;lt;code&amp;gt;playerTurn&amp;lt;/code&amp;gt; state (&amp;quot;XXXX must play a disc&amp;quot;):&lt;br /&gt;
&lt;br /&gt;
[[File:reversi7.jpg]]&lt;br /&gt;
&lt;br /&gt;
== The rules ==&lt;br /&gt;
&lt;br /&gt;
We will use the &amp;lt;code&amp;gt;getPossibleMoves&amp;lt;/code&amp;gt; PHP method to:&lt;br /&gt;
* Indicate to the current player where she is allowed to play by returning a list of coordinates&lt;br /&gt;
* Check if the player has the right to play in the spot they choose&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;&lt;br /&gt;
Example of getPossibleMoves here https://gist.github.com/leocaseiro/a8bc2851bd0caddd06685b5035937d15&lt;br /&gt;
&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This is pure PHP programming here, and there are no special things from the BGA framework that can be used. This is why we won&#039;t go into details here. The overall idea is:&lt;br /&gt;
* Create a &amp;lt;code&amp;gt;getTurnedOverDiscs(x,y)&amp;lt;/code&amp;gt; method that returns coordinates of discs that would be turned over if a token would be played at &amp;lt;code&amp;gt;x&amp;lt;/code&amp;gt;,&amp;lt;code&amp;gt;y&amp;lt;/code&amp;gt;.&lt;br /&gt;
* Loop through all free squares of the board and call the &amp;lt;code&amp;gt;getTurnedOverDiscs&amp;lt;/code&amp;gt; method on each of them. If at least 1 token is turned over, this is a valid move.&lt;br /&gt;
&lt;br /&gt;
IMPORTANT: Making a database query is slow! Please don&#039;t load the entire game board with a SQL query multiple times. In our implementation, we load the entire board once at the beginning of &amp;lt;code&amp;gt;getPossibleMoves&amp;lt;/code&amp;gt;, and then pass the board as an argument to all methods.&lt;br /&gt;
&lt;br /&gt;
If you want to look into details, please look at the &amp;quot;utility method&amp;quot; sections of &amp;lt;code&amp;gt;reversi.game.php&amp;lt;/code&amp;gt;. If building the tutorial yourself, copy the functions under &amp;quot;Utility functions&amp;quot; comment from the Reversi tutorial.&lt;br /&gt;
&lt;br /&gt;
== Display allowed moves ==&lt;br /&gt;
&lt;br /&gt;
Now we want to highlight the squares where the player can place a disc.&lt;br /&gt;
&lt;br /&gt;
To do this, we add a &amp;lt;code&amp;gt;argPlayerTurn&amp;lt;/code&amp;gt; method in &amp;lt;code&amp;gt;reversi.game.php&amp;lt;/code&amp;gt;. This method is called on the server each time we enter into &amp;lt;code&amp;gt;playerTurn&amp;lt;/code&amp;gt; game state, and its result is transferred automatically to the client-side:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
function argPlayerTurn(): array&lt;br /&gt;
{&lt;br /&gt;
    return [&lt;br /&gt;
        &#039;possibleMoves&#039; =&amp;gt; $this-&amp;gt;getPossibleMoves( intval($this-&amp;gt;getActivePlayerId()) )&lt;br /&gt;
    ];&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We use the &amp;lt;code&amp;gt;getPossibleMoves&amp;lt;/code&amp;gt; method we just developed.&lt;br /&gt;
&lt;br /&gt;
Each time we enter into a new game state, we use the &amp;lt;code&amp;gt;onEnteringState&amp;lt;/code&amp;gt; Javascript method (in the &amp;lt;code&amp;gt;reversi.js&amp;lt;/code&amp;gt; file, under &amp;quot;Game &amp;amp; client states&amp;quot;). This lets us use the data returned by the method above on the client side.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        onEnteringState: function( stateName, args )&lt;br /&gt;
        {&lt;br /&gt;
           console.log( &#039;Entering state: &#039;+stateName );&lt;br /&gt;
            &lt;br /&gt;
            switch( stateName )&lt;br /&gt;
            {&lt;br /&gt;
            case &#039;playerTurn&#039;:&lt;br /&gt;
                this.updatePossibleMoves( args.args.possibleMoves );&lt;br /&gt;
                break;&lt;br /&gt;
            }&lt;br /&gt;
        },&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
So, when we enter into &amp;lt;code&amp;gt;playerTurn&amp;lt;/code&amp;gt; game state, we call our &amp;lt;code&amp;gt;updatePossibleMoves&amp;lt;/code&amp;gt; method (under the &amp;quot;Utility methods&amp;quot; section). This method looks like this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
updatePossibleMoves: function( possibleMoves )&lt;br /&gt;
{&lt;br /&gt;
    // Remove current possible moves&lt;br /&gt;
    document.querySelectorAll(&#039;.possibleMove&#039;).forEach(div =&amp;gt; div.classList.remove(&#039;possibleMove&#039;));&lt;br /&gt;
&lt;br /&gt;
    for( var x in possibleMoves )&lt;br /&gt;
    {&lt;br /&gt;
        for( var y in possibleMoves[ x ] )&lt;br /&gt;
        {&lt;br /&gt;
            // x,y is a possible move&lt;br /&gt;
            document.getElementById(`square_${x}_${y}`).classList.add(&#039;possibleMove&#039;);&lt;br /&gt;
        }            &lt;br /&gt;
    }&lt;br /&gt;
                &lt;br /&gt;
    this.addTooltipToClass( &#039;possibleMove&#039;, &#039;&#039;, _(&#039;Place a disc here&#039;) );&lt;br /&gt;
},&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Here&#039;s what this does. At first, it removes all &amp;lt;code&amp;gt;possibleMove&amp;lt;/code&amp;gt; classes currently applied with the very useful &amp;lt;code&amp;gt;document.querySelectorAll&amp;lt;/code&amp;gt; method.&lt;br /&gt;
&lt;br /&gt;
Then it loops through all possible moves our PHP &amp;lt;code&amp;gt;updatePossibleMoves&amp;lt;/code&amp;gt; function created for us, and adds the &amp;lt;code&amp;gt;possibleMove&amp;lt;/code&amp;gt; class to each corresponding square.&lt;br /&gt;
&lt;br /&gt;
Finally, it uses the BGA framework &amp;lt;code&amp;gt;addTooltipToClass&amp;lt;/code&amp;gt; method to associate a tooltip to all those highlighted squares so that players can understand their meaning.&lt;br /&gt;
&lt;br /&gt;
To see the possible moves we need to create a CSS class (&amp;lt;code&amp;gt;possibleMove&amp;lt;/code&amp;gt;) that can be applied to a &amp;lt;code&amp;gt;square&amp;lt;/code&amp;gt; element to highlight it:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
.possibleMove {&lt;br /&gt;
    background-color: white;&lt;br /&gt;
    opacity: 0.2; &lt;br /&gt;
    cursor: pointer;  &lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
And here we are:&lt;br /&gt;
&lt;br /&gt;
[[File:reversi8.jpg.jpg]]&lt;br /&gt;
&lt;br /&gt;
== Let&#039;s play ==&lt;br /&gt;
&lt;br /&gt;
From now, it&#039;s better to restart a game with 2 players, because we are going to implement a complete Reversi turn. The summary of what we are going to do is:&lt;br /&gt;
* When we click on a &amp;lt;code&amp;gt;possibleMove&amp;lt;/code&amp;gt; square, send the move to the server.&lt;br /&gt;
* Server side, check the move is correct, apply Reversi rules and jump to next player.&lt;br /&gt;
* Client side, change the token position to reflect the move.&lt;br /&gt;
&lt;br /&gt;
First we associate each click on a square to one of our methods using our Javascript &amp;lt;code&amp;gt;setup&amp;lt;/code&amp;gt; method:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
document.querySelectorAll(&#039;.square&#039;).forEach(square =&amp;gt; square.addEventListener(&#039;click&#039;, e =&amp;gt; this.onPlayDisc(e)));&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note the use of the &amp;quot;dojo.query&amp;quot; method to get all HTML elements with &amp;quot;square&amp;quot; class in just one function call. Now, our &amp;quot;onPlayDisc&amp;quot; method is called each time someone clicks on a square.&lt;br /&gt;
&lt;br /&gt;
Here&#039;s our &amp;quot;onPlayDisc&amp;quot; method below:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
onPlayDisc: function( evt )&lt;br /&gt;
{&lt;br /&gt;
    // Stop this event propagation&lt;br /&gt;
    evt.preventDefault();&lt;br /&gt;
    evt.stopPropagation();&lt;br /&gt;
&lt;br /&gt;
    // Get the cliqued square x and y&lt;br /&gt;
    // Note: square id format is &amp;quot;square_X_Y&amp;quot;&lt;br /&gt;
    var coords = evt.currentTarget.id.split(&#039;_&#039;);&lt;br /&gt;
    var x = coords[1];&lt;br /&gt;
    var y = coords[2];&lt;br /&gt;
&lt;br /&gt;
    if(!document.getElementById(`square_${x}_${y}`).classList.contains(&#039;possibleMove&#039;)) {&lt;br /&gt;
        // This is not a possible move =&amp;gt; the click does nothing&lt;br /&gt;
        return ;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    this.bgaPerformAction(&amp;quot;actPlayDisc&amp;quot;, {&lt;br /&gt;
        x:x,&lt;br /&gt;
        y:y&lt;br /&gt;
    });&lt;br /&gt;
},&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
What we do here is:&lt;br /&gt;
* We stop the propagation of the Javascript &amp;lt;code&amp;gt;onclick&amp;lt;/code&amp;gt; event. Otherwise, it can lead to random behavior so it&#039;s always a good idea.&lt;br /&gt;
* We get the x/y coordinates of the square by using &amp;lt;code&amp;gt;evt.currentTarget.id&amp;lt;/code&amp;gt;&lt;br /&gt;
* We check that clicked square has the &amp;lt;code&amp;gt;possibleMove&amp;lt;/code&amp;gt; class, otherwise we know for sure that we can&#039;t play there.&lt;br /&gt;
* Finally, we make a call to the server using BGA &amp;lt;code&amp;gt;bgaPerformAction&amp;lt;/code&amp;gt; method with argument x and y. This call will check that &amp;lt;code&amp;gt;actPlayDisc&amp;lt;/code&amp;gt; action is possible, according to current game state (see &amp;lt;code&amp;gt;possibleactions&amp;lt;/code&amp;gt; entry in our &amp;lt;code&amp;gt;playerTurn&amp;lt;/code&amp;gt; game state defined above). This check is important to avoid issues if a player double clicks on a square.&lt;br /&gt;
&lt;br /&gt;
Now, we have to manage this &amp;lt;code&amp;gt;actPlayDisc&amp;lt;/code&amp;gt; action on the server side. At first, we introduce a &amp;lt;code&amp;gt;actPlayDisc&amp;lt;/code&amp;gt; entry point in our &amp;lt;code&amp;gt;reversi.action.php&amp;lt;/code&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
public function actPlayDisc()&lt;br /&gt;
{&lt;br /&gt;
    $this-&amp;gt;setAjaxMode();&lt;br /&gt;
    $x = (int)$this-&amp;gt;getArg( &amp;quot;x&amp;quot;, AT_posint, true );&lt;br /&gt;
    $y = (int)$this-&amp;gt;getArg( &amp;quot;y&amp;quot;, AT_posint, true );&lt;br /&gt;
    $result = $this-&amp;gt;game-&amp;gt;actPlayDisc( $x, $y );&lt;br /&gt;
    $this-&amp;gt;ajaxResponse( );&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
As you can see, we get the 2 arguments x and y from the javascript call, and call a corresponding &amp;lt;code&amp;gt;actPlayDisc&amp;lt;/code&amp;gt; method in our game logic (&amp;lt;code&amp;gt;reversi.game.php&amp;lt;/code&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
Now, let&#039;s have a look of this &amp;lt;code&amp;gt;actPlayDisc&amp;lt;/code&amp;gt; method:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
function actPlayDisc( int $x, int $y )&lt;br /&gt;
{&lt;br /&gt;
    // Check that this player is active and that this action is possible at this moment&lt;br /&gt;
    $this-&amp;gt;checkAction( &#039;actPlayDisc&#039; );  &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
... at first, we check that this action is possible according to current game state (see &amp;quot;possible action&amp;quot;). We already did it on client side, but it&#039;s important to do it on server side too (otherwise it would be possible to cheat).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        $player_id = intval($this-&amp;gt;getActivePlayerId()); &lt;br /&gt;
        &lt;br /&gt;
        // Now, check if this is a possible move&lt;br /&gt;
        $board = $this-&amp;gt;getBoard();&lt;br /&gt;
        $turnedOverDiscs = $this-&amp;gt;getTurnedOverDiscs( $x, $y, $player_id, $board );&lt;br /&gt;
        &lt;br /&gt;
        if( count( $turnedOverDiscs ) &amp;gt; 0 )&lt;br /&gt;
        {&lt;br /&gt;
            // This move is possible!&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
...now, we are using the &amp;lt;code&amp;gt;getTurnedOverDiscs&amp;lt;/code&amp;gt; method again to check that this move is possible.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
            // Let&#039;s place a disc at x,y and return all &amp;quot;$returned&amp;quot; discs to the active player&lt;br /&gt;
            &lt;br /&gt;
            $sql = &amp;quot;UPDATE board SET board_player=&#039;$player_id&#039;&lt;br /&gt;
                    WHERE ( board_x, board_y) IN ( &amp;quot;;&lt;br /&gt;
            &lt;br /&gt;
            foreach( $turnedOverDiscs as $turnedOver )&lt;br /&gt;
            {&lt;br /&gt;
                $sql .= &amp;quot;(&#039;&amp;quot;.$turnedOver[&#039;x&#039;].&amp;quot;&#039;,&#039;&amp;quot;.$turnedOver[&#039;y&#039;].&amp;quot;&#039;),&amp;quot;;&lt;br /&gt;
            }&lt;br /&gt;
            $sql .= &amp;quot;(&#039;$x&#039;,&#039;$y&#039;) ) &amp;quot;;&lt;br /&gt;
                       &lt;br /&gt;
            $this-&amp;gt;DbQuery( $sql );&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
... we update the database to change the color of all turned over disc + the disc we just placed.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
            // Update scores according to the number of disc on board&lt;br /&gt;
            $sql = &amp;quot;UPDATE player&lt;br /&gt;
                    SET player_score = (&lt;br /&gt;
                    SELECT COUNT( board_x ) FROM board WHERE board_player=player_id&lt;br /&gt;
                    )&amp;quot;;&lt;br /&gt;
            $this-&amp;gt;DbQuery( $sql );&lt;br /&gt;
            &lt;br /&gt;
            // Statistics&lt;br /&gt;
            $this-&amp;gt;incStat( count( $turnedOverDiscs ), &amp;quot;turnedOver&amp;quot;, $player_id );&lt;br /&gt;
            if( ($x==1 &amp;amp;&amp;amp; $y==1) || ($x==8 &amp;amp;&amp;amp; $y==1) || ($x==1 &amp;amp;&amp;amp; $y==8) || ($x==8 &amp;amp;&amp;amp; $y==8) )&lt;br /&gt;
                $this-&amp;gt;incStat( 1, &#039;discPlayedOnCorner&#039;, $player_id );&lt;br /&gt;
            else if( $x==1 || $x==8 || $y==1 || $y==8 )&lt;br /&gt;
                $this-&amp;gt;incStat( 1, &#039;discPlayedOnBorder&#039;, $player_id );&lt;br /&gt;
            else if( $x&amp;gt;=3 &amp;amp;&amp;amp; $x&amp;lt;=6 &amp;amp;&amp;amp; $y&amp;gt;=3 &amp;amp;&amp;amp; $y&amp;lt;=6 )&lt;br /&gt;
                $this-&amp;gt;incStat( 1, &#039;discPlayedOnCenter&#039;, $player_id );&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
... now, we update both player score by counting all disc, and we manage game statistics.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
            // Notify&lt;br /&gt;
            $this-&amp;gt;notifyAllPlayers( &amp;quot;playDisc&amp;quot;, clienttranslate( &#039;${player_name} plays a disc and turns over ${returned_nbr} disc(s)&#039; ), array(&lt;br /&gt;
                &#039;player_id&#039; =&amp;gt; $player_id,&lt;br /&gt;
                &#039;player_name&#039; =&amp;gt; $this-&amp;gt;getActivePlayerName(),&lt;br /&gt;
                &#039;returned_nbr&#039; =&amp;gt; count( $turnedOverDiscs ),&lt;br /&gt;
                &#039;x&#039; =&amp;gt; $x,&lt;br /&gt;
                &#039;y&#039; =&amp;gt; $y&lt;br /&gt;
            ) );&lt;br /&gt;
&lt;br /&gt;
            $this-&amp;gt;notifyAllPlayers( &amp;quot;turnOverDiscs&amp;quot;, &#039;&#039;, array(&lt;br /&gt;
                &#039;player_id&#039; =&amp;gt; $player_id,&lt;br /&gt;
                &#039;turnedOver&#039; =&amp;gt; $turnedOverDiscs&lt;br /&gt;
            ) );&lt;br /&gt;
            &lt;br /&gt;
            $newScores = $this-&amp;gt;getCollectionFromDb( &amp;quot;SELECT player_id, player_score FROM player&amp;quot;, true );&lt;br /&gt;
            $this-&amp;gt;notifyAllPlayers( &amp;quot;newScores&amp;quot;, &amp;quot;&amp;quot;, array(&lt;br /&gt;
                &amp;quot;scores&amp;quot; =&amp;gt; $newScores&lt;br /&gt;
            ) );&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
... then we notify about all these changes. We are using for that 3 notifications (&amp;lt;code&amp;gt;playDisc&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;turnOverDiscs&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;newScores&amp;lt;/code&amp;gt; that we are going to implement on client side later). Note that the description of the &amp;lt;code&amp;gt;playDisc&amp;lt;/code&amp;gt; notification will be logged in the game log.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
            // Then, go to the next state&lt;br /&gt;
            $this-&amp;gt;gamestate-&amp;gt;nextState( &#039;playDisc&#039; );&lt;br /&gt;
        }&lt;br /&gt;
        else&lt;br /&gt;
            throw new BgaSystemException( &amp;quot;Impossible move&amp;quot; );&lt;br /&gt;
    }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
... finally, we jump to the next game state if everything goes fine (&amp;lt;code&amp;gt;playDisc&amp;lt;/code&amp;gt; is the name of a transition in the &amp;lt;code&amp;gt;playerTurn&amp;lt;/code&amp;gt; game state description above which leads to state 11 which is &amp;lt;code&amp;gt;nextPlayer&amp;lt;/code&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
To make the statistics work, we have to initialize them in &amp;lt;code&amp;gt;stats.json&amp;lt;/code&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
  &amp;quot;player&amp;quot;: {&lt;br /&gt;
    &amp;quot;discPlayedOnCorner&amp;quot;: {&lt;br /&gt;
      &amp;quot;id&amp;quot;: 10,&lt;br /&gt;
      &amp;quot;name&amp;quot;: &amp;quot;Discs played on a corner&amp;quot;,&lt;br /&gt;
      &amp;quot;type&amp;quot;: &amp;quot;int&amp;quot;&lt;br /&gt;
    },&lt;br /&gt;
    &amp;quot;discPlayedOnBorder&amp;quot;: {&lt;br /&gt;
      &amp;quot;id&amp;quot;: 11,&lt;br /&gt;
      &amp;quot;name&amp;quot;: &amp;quot;Discs played on a border&amp;quot;,&lt;br /&gt;
      &amp;quot;type&amp;quot;: &amp;quot;int&amp;quot;&lt;br /&gt;
    },&lt;br /&gt;
    &amp;quot;discPlayedOnCenter&amp;quot;: {&lt;br /&gt;
      &amp;quot;id&amp;quot;: 12,&lt;br /&gt;
      &amp;quot;name&amp;quot;: &amp;quot;Discs played on board center part&amp;quot;,&lt;br /&gt;
      &amp;quot;type&amp;quot;: &amp;quot;int&amp;quot;&lt;br /&gt;
    },&lt;br /&gt;
    &amp;quot;turnedOver&amp;quot;: {&lt;br /&gt;
      &amp;quot;id&amp;quot;: 13,&lt;br /&gt;
      &amp;quot;name&amp;quot;: &amp;quot;Number of discs turned over&amp;quot;,&lt;br /&gt;
      &amp;quot;type&amp;quot;: &amp;quot;int&amp;quot;&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
A last thing to do on the server side is to activate the next player when we enter the &amp;lt;code&amp;gt;nextPlayer&amp;lt;/code&amp;gt; game state (in the &amp;lt;code&amp;gt;reversi.game.php&amp;lt;/code&amp;gt; file, under &amp;quot;Game state reactions&amp;quot;):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    function stNextPlayer(): void&lt;br /&gt;
    {&lt;br /&gt;
        // Active next player&lt;br /&gt;
        $player_id = intval($this-&amp;gt;activeNextPlayer());&lt;br /&gt;
&lt;br /&gt;
        // Check if both player has at least 1 discs, and if there are free squares to play&lt;br /&gt;
        $player_to_discs = $this-&amp;gt;getCollectionFromDb( &amp;quot;SELECT board_player, COUNT( board_x )&lt;br /&gt;
                                                       FROM board&lt;br /&gt;
                                                       GROUP BY board_player&amp;quot;, true );&lt;br /&gt;
&lt;br /&gt;
        if( ! isset( $player_to_discs[ null ] ) )&lt;br /&gt;
        {&lt;br /&gt;
            // Index 0 has not been set =&amp;gt; there&#039;s no more free place on the board !&lt;br /&gt;
            // =&amp;gt; end of the game&lt;br /&gt;
            $this-&amp;gt;gamestate-&amp;gt;nextState( &#039;endGame&#039; );&lt;br /&gt;
            return ;&lt;br /&gt;
        }&lt;br /&gt;
        else if( ! isset( $player_to_discs[ $player_id ] ) )&lt;br /&gt;
        {&lt;br /&gt;
            // Active player has no more disc on the board =&amp;gt; he looses immediately&lt;br /&gt;
            $this-&amp;gt;gamestate-&amp;gt;nextState( &#039;endGame&#039; );&lt;br /&gt;
            return ;&lt;br /&gt;
        }&lt;br /&gt;
        &lt;br /&gt;
        // Can this player play?&lt;br /&gt;
&lt;br /&gt;
        $possibleMoves = $this-&amp;gt;getPossibleMoves( $player_id );&lt;br /&gt;
        if( count( $possibleMoves ) == 0 )&lt;br /&gt;
        {&lt;br /&gt;
&lt;br /&gt;
            // This player can&#039;t play&lt;br /&gt;
            // Can his opponent play ?&lt;br /&gt;
            $opponent_id = (int)$this-&amp;gt;getUniqueValueFromDb( &amp;quot;SELECT player_id FROM player WHERE player_id!=&#039;$player_id&#039; &amp;quot; );&lt;br /&gt;
            if( count( $this-&amp;gt;getPossibleMoves( $opponent_id ) ) == 0 )&lt;br /&gt;
            {&lt;br /&gt;
                // Nobody can move =&amp;gt; end of the game&lt;br /&gt;
                $this-&amp;gt;gamestate-&amp;gt;nextState( &#039;endGame&#039; );&lt;br /&gt;
            }&lt;br /&gt;
            else&lt;br /&gt;
            {            &lt;br /&gt;
                // =&amp;gt; pass his turn&lt;br /&gt;
                $this-&amp;gt;gamestate-&amp;gt;nextState( &#039;cantPlay&#039; );&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
        else&lt;br /&gt;
        {&lt;br /&gt;
            // This player can play. Give him some extra time&lt;br /&gt;
            $this-&amp;gt;giveExtraTime( $player_id );&lt;br /&gt;
            $this-&amp;gt;gamestate-&amp;gt;nextState( &#039;nextTurn&#039; );&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Now, when we play a token, the rules are checked and the token appears in the database.&lt;br /&gt;
&lt;br /&gt;
[[File:reversi9.jpg]]&lt;br /&gt;
&lt;br /&gt;
Of course, as we don&#039;t manage notifications on client side, we need to press F5 after each move to see the changes on the board.&lt;br /&gt;
&lt;br /&gt;
== Make the move appear automatically ==&lt;br /&gt;
&lt;br /&gt;
Now, what we have to do is process the notifications sent by the server and make the move appear on the interface.&lt;br /&gt;
&lt;br /&gt;
In our &amp;lt;code&amp;gt;setupNotifications&amp;lt;/code&amp;gt; method in &amp;lt;code&amp;gt;reversi.js&amp;lt;/code&amp;gt;, we register 2 methods for the 2 notifications we created at the previous step (&amp;lt;code&amp;gt;playDisc&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;turnOverDiscs&amp;lt;/code&amp;gt;):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
            const notifs = [&lt;br /&gt;
                [&#039;playDisc&#039;, 500],&lt;br /&gt;
                [&#039;turnOverDiscs&#039;, 1500],&lt;br /&gt;
                [&#039;newScores&#039;, 1],&lt;br /&gt;
            ];&lt;br /&gt;
    &lt;br /&gt;
            notifs.forEach((notif) =&amp;gt; {&lt;br /&gt;
                dojo.subscribe(notif[0], this, `notif_${notif[0]}`);&lt;br /&gt;
                this.notifqueue.setSynchronous(notif[0], notif[1]);&lt;br /&gt;
            });&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We will associate each of our 3 notifications with a method prefixed with &amp;lt;code&amp;gt;notif_&amp;lt;/code&amp;gt;. We also define these notifications as &amp;quot;synchronous&amp;quot;, with a duration in millisecond. It tells the user interface to wait some time after executing the notification, to let the animation end before starting the next notification. In our specific case, the animation will be the following:&lt;br /&gt;
* Make a disc slide from the player panel to its place on the board&lt;br /&gt;
* (wait 500ms)&lt;br /&gt;
* Make all turned over discs blink (and of course turned them over)&lt;br /&gt;
* (wait 1500ms)&lt;br /&gt;
* Update the player scores&lt;br /&gt;
* (no real delay on this one)&lt;br /&gt;
&lt;br /&gt;
The second part of the code is a generic thing to automatically bind the notifs we configured to the &amp;lt;code&amp;gt;notif_&amp;lt;notifName&amp;gt;&amp;lt;/code&amp;gt; functions we are about to create.&lt;br /&gt;
&lt;br /&gt;
Let&#039;s have a look now on the &amp;lt;code&amp;gt;playDisc&amp;lt;/code&amp;gt; notification handler method:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
notif_playDisc: function( notif )&lt;br /&gt;
{&lt;br /&gt;
    // Remove current possible moves (makes the board more clear)&lt;br /&gt;
    document.querySelectorAll(&#039;.possibleMove&#039;).forEach(div =&amp;gt; div.classList.remove(&#039;possibleMove&#039;));&lt;br /&gt;
&lt;br /&gt;
    this.addDiscOnBoard( notif.args.x, notif.args.y, notif.args.player_id );&lt;br /&gt;
},&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
No surprise here, we re-used some existing stuff to:&lt;br /&gt;
* Remove the highlighted squares.&lt;br /&gt;
* Add a new disc on board, coming from player panel.&lt;br /&gt;
&lt;br /&gt;
Now, here&#039;s the method that handles the &amp;lt;code&amp;gt;turnOverDiscs&amp;lt;/code&amp;gt; notification:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
notif_turnOverDiscs: function( notif )&lt;br /&gt;
{&lt;br /&gt;
    // Get the color of the player who is returning the discs&lt;br /&gt;
    var targetColor = this.gamedatas.players[ notif.args.player_id ].color;&lt;br /&gt;
&lt;br /&gt;
    // Made these discs blinking and set them to the specified color&lt;br /&gt;
    for( var i in notif.args.turnedOver )&lt;br /&gt;
    {&lt;br /&gt;
        var disc = notif.args.turnedOver[ i ];&lt;br /&gt;
        &lt;br /&gt;
        // Make the disc blink 2 times&lt;br /&gt;
        var anim = dojo.fx.chain( [&lt;br /&gt;
            dojo.fadeOut( { node: &#039;disc_&#039;+disc.x+&#039;&#039;+disc.y } ),&lt;br /&gt;
            dojo.fadeIn( { node: &#039;disc_&#039;+disc.x+&#039;&#039;+disc.y } ),&lt;br /&gt;
            dojo.fadeOut( { &lt;br /&gt;
                            node: &#039;disc_&#039;+disc.x+&#039;&#039;+disc.y,&lt;br /&gt;
                            onEnd: node =&amp;gt; $(node).dataset.color = targetColor,&lt;br /&gt;
                            } ),&lt;br /&gt;
            dojo.fadeIn( { node: &#039;disc_&#039;+disc.x+&#039;&#039;+disc.y  } )&lt;br /&gt;
                            &lt;br /&gt;
        ] ); // end of dojo.fx.chain&lt;br /&gt;
&lt;br /&gt;
        // ... and launch the animation&lt;br /&gt;
        anim.play();                &lt;br /&gt;
    }&lt;br /&gt;
},&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The list of the discs to be turned over has been made available by our server side code in &amp;lt;code&amp;gt;notif.args.turnedOver&amp;lt;/code&amp;gt; (see previous paragraph). We loop through all these discs, and create a complex animation using &amp;lt;code&amp;gt;dojo.Animation&amp;lt;/code&amp;gt; for each of them. The complete documentation on dojo animations [http://dojotoolkit.org/documentation/tutorials/1.6/animation/ can be found here].&lt;br /&gt;
&lt;br /&gt;
In few words: we create a chain of 4 animations to make the disc fade out, fade in, fade out again, and fade in again. At the end of the second fade out, we change the color of the disc. Finally, we launch the animation with &amp;lt;code&amp;gt;play()&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
And Also the notification to update the scores:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
notif_newScores: function( notif )&lt;br /&gt;
        {&lt;br /&gt;
            for( var player_id in notif.args.scores )&lt;br /&gt;
            {&lt;br /&gt;
                var newScore = notif.args.scores[ player_id ];&lt;br /&gt;
                this.scoreCtrl[ player_id ].toValue( newScore );&lt;br /&gt;
            }&lt;br /&gt;
        },&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Category:Studio]]&lt;/div&gt;</summary>
		<author><name>Sguzzer Gunayer</name></author>
	</entry>
	<entry>
		<id>https://en.doc.boardgamearena.com/index.php?title=Tutorial_reversi&amp;diff=22416</id>
		<title>Tutorial reversi</title>
		<link rel="alternate" type="text/html" href="https://en.doc.boardgamearena.com/index.php?title=Tutorial_reversi&amp;diff=22416"/>
		<updated>2024-09-03T14:51:38Z</updated>

		<summary type="html">&lt;p&gt;Sguzzer Gunayer: /* Set Token Colors in setupNewGame in .game.php file */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&#039;&#039;&#039;Check out an update version&#039;&#039;&#039; of the [[BGA Type Safe Template: Reversi|Reversi Tutorial]] which uses the [[BGA Type Safe Template]]. {{Studio_Framework_Navigation}}&lt;br /&gt;
&lt;br /&gt;
== Introduction ==&lt;br /&gt;
&lt;br /&gt;
Using this tutorial, you can build a complete working game on the BGA environment: Reversi.&lt;br /&gt;
&lt;br /&gt;
Before you read this tutorial, you must:&lt;br /&gt;
* Read the overall presentations of the BGA Framework ([[Studio|see here]]).&lt;br /&gt;
* Know the [http://en.wikipedia.org/wiki/Reversi#Rules rules of Reversi].&lt;br /&gt;
* Know the languages used on BGA: PHP, SQL, HTML, CSS, Javascript&lt;br /&gt;
* &#039;&#039;&#039;Setup your development environment&#039;&#039;&#039; [http://en.doc.boardgamearena.com/First_steps_with_BGA_Studio First Steps with BGA Studio]&lt;br /&gt;
&lt;br /&gt;
== Create your first game ==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Note: you should already have created a project following instructions in [[First_steps_with_BGA_Studio#Create_a_new_game_project|Create a new game project]]. While you will find a &#039;&#039;&#039;reversi&#039;&#039;&#039; directory in your SFTP folder, do not use it for this tutorial. Instead, use the project you have created as an (empty) starting point.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
With the initial skeleton of code provided in your project, you can already start a game from the BGA Studio:&lt;br /&gt;
* Go to your [https://studio.boardgamearena.com/controlpanel studio Control panel], then Manage games and select your initial project. &#039;&#039;Note: there are warnings displayed about a missing BGG_ID and presentation text. You can ignore that for now.&#039;&#039;&lt;br /&gt;
* Click the Play link next to your project name. This will open the Play page and offer to create a new table for your project. &#039;&#039;Optional: click the Heart icon to add your project to your favorite games list.&#039;&#039;&lt;br /&gt;
* On the Play page, on the top of the page, make sure that your settings are &amp;quot;Simple game&amp;quot;, &amp;quot;Real time&amp;quot; and &amp;quot;Manual&amp;quot;.&lt;br /&gt;
* Click &amp;quot;Create table&amp;quot; to create a table of your project. &lt;br /&gt;
* For now, we are going to work with one player only, so use the (-) button to set the number of players to 1. Most of the time it is simpler to proceed with only one player during the early phase of development of your game, as it&#039;s easy and fast to start/stop games. If you choose to start with 2 players, you should see two names on the right: testdude0 and testdude1. To switch between them, press the red arrow button near their names; it will open another tab. This way you don&#039;t need to login and logout from multiple accounts.) &lt;br /&gt;
* Reminder: Always use the &amp;quot;Express Start&amp;quot; button to start the game.&lt;br /&gt;
&lt;br /&gt;
Thus, you can start a &amp;quot;Reversi&amp;quot; game, and arrive on a void, empty game. Yeah.&lt;br /&gt;
&lt;br /&gt;
End the game by clicking on the game options icon on the top right, and then on &amp;quot;Express Stop&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
== Editing the game information (Optional) ==&lt;br /&gt;
&lt;br /&gt;
This step is optional and will fix the warnings on the project page (missing BGG_ID and presentation).&lt;br /&gt;
&lt;br /&gt;
==== Edits to fix Errors ====&lt;br /&gt;
* Edit your local copy of the &amp;lt;code&amp;gt;gameinfos.inc.php&amp;lt;/code&amp;gt; file:&lt;br /&gt;
** Change the &amp;lt;code&amp;gt;bgg_id&amp;lt;/code&amp;gt; value from &amp;lt;code&amp;gt;0&amp;lt;/code&amp;gt; to &amp;lt;code&amp;gt;2389&amp;lt;/code&amp;gt; - that&#039;s around line 37.&lt;br /&gt;
** Add &amp;lt;code&amp;gt;1,&amp;lt;/code&amp;gt; to the players array - that&#039;s around line 41.&lt;br /&gt;
** Change the presentation array content - that&#039;s around line 134. Uncomment one line and change the text. Remove the final comma if you keep only one line!&lt;br /&gt;
* Upload the &amp;lt;code&amp;gt;gameinfos.inc.php&amp;lt;/code&amp;gt; file to the SFTP server (see [[First_steps_with_BGA_Studio#Connect_to_your_SFTP_folder|Connect to your SFTP folder]]).&lt;br /&gt;
&lt;br /&gt;
==== Test your Edits ====&lt;br /&gt;
* Go back to your project page, and in the &amp;quot;Game Information&amp;quot; section, click &amp;quot;Reload game informations&amp;quot;.&lt;br /&gt;
* Finally, refresh the project page in your browser (usually CTRL-F5).&lt;br /&gt;
&lt;br /&gt;
===== Not working? =====&lt;br /&gt;
Some changes will require bypassing the cache. It is often worth doing a hard refresh to make sure the&lt;br /&gt;
&lt;br /&gt;
Sometimes the cache will keep your changes from showing. Since this is a possibility, it will be useful to know how to bypass the cache. To do so you may manually clear cache or use a shortcut to refresh and ignore the cached version of the page. Here&#039;s how&lt;br /&gt;
&lt;br /&gt;
====== Windows ======&lt;br /&gt;
Chrome, Firefox, or Edge: Press &amp;lt;code&amp;gt;Ctrl+F5&amp;lt;/code&amp;gt; or &amp;lt;code&amp;gt;Shift+F5&amp;lt;/code&amp;gt; or &amp;lt;code&amp;gt;Ctrl+Shift+R&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====== Mac ======&lt;br /&gt;
Chrome or Firefox: Press &amp;lt;code&amp;gt;Shift+Command+R&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Safari for Mac: Press &amp;lt;code&amp;gt;Command+Option+E&amp;lt;/code&amp;gt; to empty the cache, then hold down Shift and click Reload in the toolbar&lt;br /&gt;
&lt;br /&gt;
== Make it look like Reversi ==&lt;br /&gt;
&lt;br /&gt;
Let&#039;s start with the board. This will give you a good idea of how things will look and where tokens should go.&lt;br /&gt;
&lt;br /&gt;
Be careful designing the layout of your game: you must always keep in mind that players with a 1024px screen width must be able to play. Usually, it means that the width of the play area can be 750px (in the worst case).&lt;br /&gt;
&lt;br /&gt;
For Reversi, it&#039;s useless to have a 750x750px board - much too big, so we chose this one which fit perfectly (536x528):&lt;br /&gt;
&lt;br /&gt;
[[File:Board.jpg]]&lt;br /&gt;
&lt;br /&gt;
Note that we are using a jpg file. Jpg files are lighter than png, so they are faster to load. Later, we are going to use PNGs for tokens because they allow for transparency.&lt;br /&gt;
&lt;br /&gt;
==== Add the board ====&lt;br /&gt;
use lowercase file names&lt;br /&gt;
* upload &amp;lt;code&amp;gt;board.jpg&amp;lt;/code&amp;gt; in your &amp;lt;code&amp;gt;img/&amp;lt;/code&amp;gt; directory. &lt;br /&gt;
* edit &amp;lt;code&amp;gt;reversi_reversi.tpl&amp;lt;/code&amp;gt; to add a &amp;lt;code&amp;gt;div&amp;lt;/code&amp;gt; for your board.&lt;br /&gt;
&lt;br /&gt;
Note: If you are building this game by following the tutorial, you will have a different project name than &amp;lt;code&amp;gt;reversi&amp;lt;/code&amp;gt; (i.e. &amp;lt;code&amp;gt;mygame_mygame.tpl&amp;lt;/code&amp;gt;). The file names in your project will be different than shown in this tutorial, replacing &amp;lt;code&amp;gt;reversi&amp;lt;/code&amp;gt; with your project name. Be sure that any code (other than comments) that references &amp;lt;code&amp;gt;reversi&amp;lt;/code&amp;gt; is changed to your actual project name.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;div id=&amp;quot;board&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* edit your &amp;lt;code&amp;gt;reversi.css&amp;lt;/code&amp;gt; file to transform it into a visible board:&lt;br /&gt;
&lt;br /&gt;
 #board {&lt;br /&gt;
    width: 536px;&lt;br /&gt;
    height: 528px;&lt;br /&gt;
    background-image: url(&#039;img/board.jpg&#039;);&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Important: refresh your page.&#039;&#039;&#039; Here&#039;s your board:[[File:reversi1.jpg]]&lt;br /&gt;
&lt;br /&gt;
If the board does not appear, refresh the page (always do this when you update the CSS file), and check the image filename. Remember file names are case sensitive!&lt;br /&gt;
&lt;br /&gt;
==== Code the Grid ====&lt;br /&gt;
Now, we need to create some invisible HTML elements where squares are. These elements will be used as position references for the white and black tokens. &lt;br /&gt;
&lt;br /&gt;
===== Build the grid of squares =====&lt;br /&gt;
The board is 8 squares by 8 squares. This means we need 64 squares. To avoid writing 64 individual &amp;lt;code&amp;gt;div&amp;lt;/code&amp;gt; elements on our template, we are going to generate the squares on JS setup.&lt;br /&gt;
&lt;br /&gt;
We&#039;ll do this in our Javascript &amp;lt;code&amp;gt;setup&amp;lt;/code&amp;gt; method under &amp;lt;code&amp;gt;// TODO: Set up your game interface here, according to &amp;quot;gamedatas&amp;quot;&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
const board = document.getElementById(&#039;board&#039;);&lt;br /&gt;
const hor_scale = 64.8;&lt;br /&gt;
const ver_scale = 64.4;&lt;br /&gt;
for (let x=1; x&amp;lt;=8; x++) {&lt;br /&gt;
    for (let y=1; y&amp;lt;=8; y++) {&lt;br /&gt;
        const left = Math.round((x - 1) * hor_scale + 10);&lt;br /&gt;
        const top = Math.round((y - 1) * ver_scale + 7);&lt;br /&gt;
        // we use afterbegin to make sure squares are placed before discs&lt;br /&gt;
        board.insertAdjacentHTML(`afterbegin`, `&amp;lt;div id=&amp;quot;square_${x}_${y}&amp;quot; class=&amp;quot;square&amp;quot; style=&amp;quot;left: ${left}px; top: ${top}px;&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;`);&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note: as you can see, squares in our &amp;lt;code&amp;gt;board.jpg&amp;lt;/code&amp;gt; files do not have an exact width/height in pixels, and that&#039;s the reason we are using floating point numbers here.&lt;br /&gt;
&lt;br /&gt;
===== Style Those Squares =====&lt;br /&gt;
Now, to finish our work and check if everything works fine, we are going to style our square a little bit in our CSS stylesheet:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#board {&lt;br /&gt;
    width: 536px;&lt;br /&gt;
    height: 528px;&lt;br /&gt;
    background-image: url(&#039;img/board.jpg&#039;);&lt;br /&gt;
    position: relative;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.square {&lt;br /&gt;
    width: 62px;&lt;br /&gt;
    height: 62px;&lt;br /&gt;
    position: absolute;&lt;br /&gt;
    background-color: red;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Explanations:&lt;br /&gt;
* With &amp;quot;position: relative&amp;quot; on board, we ensure square elements are positioned relatively to board.&lt;br /&gt;
* &amp;lt;code&amp;gt;background-color: red;&amp;lt;/code&amp;gt; is used for testing. This allows us to see the invisible elements. (You could instead do something like &amp;lt;code&amp;gt;outline: 2px solid orange;&amp;lt;/code&amp;gt; have fun and be creative)&lt;br /&gt;
&lt;br /&gt;
Let&#039;s refresh and check our (beautiful) squares:&lt;br /&gt;
&lt;br /&gt;
[[File:reversi2.jpg]]&lt;br /&gt;
&lt;br /&gt;
Now that you know the squares are there, you can remove the test line &amp;lt;code&amp;gt;background-color: red;&amp;lt;/code&amp;gt;  from your &amp;lt;code&amp;gt;.square&amp;lt;/code&amp;gt; class in the CSS stylesheet.&lt;br /&gt;
&lt;br /&gt;
===== Not Working? =====&lt;br /&gt;
If the styled squares do not appear, inspect and check your css (Chrome DevTools: Application &amp;gt; Frames &amp;gt; top &amp;gt; Stylesheets &amp;gt; reversi.css). &lt;br /&gt;
&lt;br /&gt;
== The Tokens ==&lt;br /&gt;
&lt;br /&gt;
Now, our board is ready for some tokens!&lt;br /&gt;
&lt;br /&gt;
[Note: Throughout this tutorial, sometimes &amp;quot;tokens&amp;quot; is used, and sometimes &amp;quot;discs&amp;quot; is used. They are often swapped if you&#039;re looking at code in the reversi example project.]&lt;br /&gt;
&lt;br /&gt;
=== Build the Token ===&lt;br /&gt;
There are quite a few steps before the tokens will appear. You may be used to testing after every change, but that won&#039;t work well here. The token will &#039;&#039;&#039;not&#039;&#039;&#039; show until you have add styles to the css, js template to the tpl, utility method in the js,  adjusted the php file, and added the token to the board in the js file.&lt;br /&gt;
&lt;br /&gt;
==== HTML in the .tpl file ====&lt;br /&gt;
At first, we introduce a new &#039;div&#039; element as a child of &amp;quot;board&amp;quot; to host all these tokens (in our template):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;div id=&amp;quot;board&amp;quot;&amp;gt;&lt;br /&gt;
    &lt;br /&gt;
    &amp;lt;div id=&amp;quot;discs&amp;quot;&amp;gt;&lt;br /&gt;
    &amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note: &amp;lt;code&amp;gt;discs&amp;lt;/code&amp;gt; is plural. This div will be used to hold the token divs. Shortly, we will use javascript to add individual tokens to the board.&lt;br /&gt;
&lt;br /&gt;
==== Add Token to img directory ====&lt;br /&gt;
Here&#039;s a new piece of art with the tokens. We need transparency here so we are using a png file:&lt;br /&gt;
&lt;br /&gt;
[[File:tokens.png]]&lt;br /&gt;
&lt;br /&gt;
Upload this image file &amp;lt;code&amp;gt;tokens.png&amp;lt;/code&amp;gt; in your &amp;lt;code&amp;gt;img/&amp;lt;/code&amp;gt; directory.&lt;br /&gt;
&lt;br /&gt;
Important Fun Fact: we are using ONE file for both tokens. It is really important to use a minimum number of graphic files for your game. This is called the &amp;quot;CSS sprite&amp;quot; technique, because it makes the game load faster and more reliable. [http://www.w3schools.com/css/css_image_sprites.asp Read more about CSS sprites].&lt;br /&gt;
&lt;br /&gt;
==== Style the Tokens in .css file ====&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
.disc {&lt;br /&gt;
    width: 56px;&lt;br /&gt;
    height: 56px;&lt;br /&gt;
    position: absolute;&lt;br /&gt;
    background-image: url(&#039;img/tokens.png&#039;);&lt;br /&gt;
    background-size: auto 100%;&lt;br /&gt;
}&lt;br /&gt;
.disc[data-color=&amp;quot;ffffff&amp;quot;] { background-position-x: 0%; }&lt;br /&gt;
.disc[data-color=&amp;quot;000000&amp;quot;] { background-position-x: 100%; }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
With this CSS code, we can set and change the token color by changing the data-color attribute. Using data instead of a class ensures it can be only one of them (the disc cannot be black and white at the same time).&lt;br /&gt;
&lt;br /&gt;
Note the &amp;quot;&amp;lt;code&amp;gt;position: absolute&amp;lt;/code&amp;gt;&amp;quot; which allows us to position tokens on the board and make them &amp;quot;slide&amp;quot; to their positions.&lt;br /&gt;
&lt;br /&gt;
==== Add Token Utility Method in .js file ====&lt;br /&gt;
Now, let&#039;s make the first token appear on our board. Tokens are not visible at the beginning of the game: they appear dynamically during the game. For this reason, we are going to make them appear from our Javascript code, using a template string&lt;br /&gt;
&lt;br /&gt;
Let&#039;s create a method in our Javascript code (in the &amp;lt;code&amp;gt;reversi.js&amp;lt;/code&amp;gt; file) that will make a token appear on the board, using this template. Add under the section //// Utility methods:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
addDiscOnBoard: function( x, y, player )&lt;br /&gt;
{&lt;br /&gt;
    var color = this.gamedatas.players[ player ].color;&lt;br /&gt;
    &lt;br /&gt;
    document.getElementById(&#039;discs&#039;).insertAdjacentHTML(&#039;beforeend&#039;, `&amp;lt;div class=&amp;quot;disc&amp;quot; data-color=&amp;quot;${color}&amp;quot; id=&amp;quot;disc_${x}${y}&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;`);&lt;br /&gt;
    &lt;br /&gt;
    this.placeOnObject( `disc_${x}${y}`, &#039;overall_player_board_&#039;+player );&lt;br /&gt;
    this.slideToObject( `disc_${x}${y}`, &#039;square_&#039;+x+&#039;_&#039;+y ).play();&lt;br /&gt;
},  &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===== Utility Method Explanation =====&lt;br /&gt;
* with &amp;lt;code&amp;gt;element.insertAdjacentHTML&amp;lt;/code&amp;gt; method, we create a HTML piece of code and insert it as a new child of &amp;lt;code&amp;gt;tokens&amp;lt;/code&amp;gt; div element.&lt;br /&gt;
* with &amp;lt;code&amp;gt;this.placeOnObject&amp;lt;/code&amp;gt; BGA method, we place this element over the panel of some player. &lt;br /&gt;
* Immediately after, using &amp;lt;code&amp;gt;this.slideToObject&amp;lt;/code&amp;gt; BGA method, we make the token slide to the &amp;lt;code&amp;gt;square&amp;lt;/code&amp;gt; element, its final destination.&lt;br /&gt;
* &amp;lt;code&amp;gt;&#039;overall_player_board_&#039;+player&amp;lt;/code&amp;gt; refers to the div element that contains each player&#039;s information and avatar. By initially placing the token here, it gives the effect that the player&#039;s avatar is throwing the token onto the board.&lt;br /&gt;
&lt;br /&gt;
Note: don&#039;t forget to call the &amp;lt;code&amp;gt;play()&amp;lt;/code&amp;gt;, otherwise the token will remain at its original location.&lt;br /&gt;
&lt;br /&gt;
Note: during this process, the parent of the new token HTML element will stay &amp;lt;code&amp;gt;tokens&amp;lt;/code&amp;gt;. &amp;lt;code&amp;gt;placeOnObject&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;slideToObject&amp;lt;/code&amp;gt; methods are &#039;&#039;only&#039;&#039; moving the position of elements on screen, and they are &#039;&#039;not&#039;&#039; modifying the HTML tree.&lt;br /&gt;
&lt;br /&gt;
==== Set Token Colors in setupNewGame in .game.php file ====&lt;br /&gt;
Before we can show a token, we need to set the player colors in the &amp;lt;code&amp;gt;setupNewGame&amp;lt;/code&amp;gt; function in &amp;lt;code&amp;gt;reversi.game.php&amp;lt;/code&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
Replace &amp;lt;code&amp;gt;$default_colors = $gameinfos[&#039;player_colors&#039;];&amp;lt;/code&amp;gt; with the following line:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        $default_colors = array( &amp;quot;ffffff&amp;quot;, &amp;quot;000000&amp;quot; );&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note: A few lines below, you may have to remove the line &amp;lt;code&amp;gt;self::reattributeColorsBasedOnPreferences( $players, $gameinfos[&#039;player_colors&#039;] );&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Test the Token ===&lt;br /&gt;
Now, to test if everything works fine&lt;br /&gt;
&lt;br /&gt;
==== addTokenOnBoard() in .js file to Test ====&lt;br /&gt;
In &amp;lt;code&amp;gt;reversi.js&amp;lt;/code&amp;gt;, in &amp;lt;code&amp;gt;setup: function&amp;lt;/code&amp;gt;, under the code we added to generate the squares. &lt;br /&gt;
 this.addDiscOnBoard( 2, 2, this.player_id );&lt;br /&gt;
Now restart the game.&lt;br /&gt;
&lt;br /&gt;
A token should appear and slide immediately to its position, like this:&lt;br /&gt;
&lt;br /&gt;
[[File:reversi3.jpg]]&lt;br /&gt;
&lt;br /&gt;
== The database ==&lt;br /&gt;
&lt;br /&gt;
We did most of the client-side programming, so let&#039;s have a look on the other side now. To design the database model of our game, you will need to access the database. You won&#039;t need to do anything in database UI, yet.&lt;br /&gt;
&lt;br /&gt;
=== Accessing the Database ===&lt;br /&gt;
To access the database, start a game, then click &amp;quot;Go to game database&amp;quot; link at the bottom of our game, to access the database directly with a PhpMyAdmin instance.&lt;br /&gt;
&lt;br /&gt;
After the first time you&#039;ve acess the database, you could skip opening a game and instead, go to https://studio.boardgamearena.com/db/ . Your PhpMyAdmin username/password is in your welcome email.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note&#039;&#039;&#039;: do not remove existing tables&lt;br /&gt;
&lt;br /&gt;
=== Create Table in .sql file ===&lt;br /&gt;
Now, you are able to create the table(s) you need for your game, and report every SQL command used in your &amp;lt;code&amp;gt;dbmodel.sql&amp;lt;/code&amp;gt; file. &lt;br /&gt;
&lt;br /&gt;
The database model of Reversi is short: just one table with the squares of the board. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
CREATE TABLE IF NOT EXISTS `board` (&lt;br /&gt;
  `board_x` smallint(5) unsigned NOT NULL,&lt;br /&gt;
  `board_y` smallint(5) unsigned NOT NULL,&lt;br /&gt;
  `board_player` int(10) unsigned DEFAULT NULL,&lt;br /&gt;
  PRIMARY KEY (`board_x`,`board_y`)&lt;br /&gt;
) ENGINE=InnoDB DEFAULT CHARSET=utf8;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Add the above SQL to &amp;lt;code&amp;gt;dbmodel.sql&amp;lt;/code&amp;gt;. Pay special attention to the backtick &amp;lt;code&amp;gt;`&amp;lt;/code&amp;gt; character vs. the single quote &amp;lt;code&amp;gt;&#039;&amp;lt;/code&amp;gt; when working with SQL. &lt;br /&gt;
&lt;br /&gt;
=== Test the Table ===&lt;br /&gt;
Now, a new database with a &amp;lt;code&amp;gt;board&amp;lt;/code&amp;gt; table will be created each time we start a Reversi game. This is why after modifying our &amp;lt;code&amp;gt;dbmodel.sql&amp;lt;/code&amp;gt; it&#039;s a good time to stop your current game &amp;amp; start a new game.&lt;br /&gt;
&lt;br /&gt;
Start a new game and verify a table is created.&lt;br /&gt;
&lt;br /&gt;
== Setup the initial game position ==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note&#039;&#039;&#039;: From now on, you must launch the game with &#039;&#039;&#039;two players&#039;&#039;&#039; to get two &amp;lt;code&amp;gt;player_id&amp;lt;/code&amp;gt;s within the database. Otherwise, the game will crash.&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;setupNewGame&amp;lt;/code&amp;gt; method of our &amp;lt;code&amp;gt;reversi.game.php&amp;lt;/code&amp;gt; is called during initial setup. This initializes our data and places the starting tokens on the board. At the beginning of the game, there should be 4 tokens on the board.&lt;br /&gt;
&lt;br /&gt;
=== Initialize the Board in .game.php file ===&lt;br /&gt;
Under &amp;lt;code&amp;gt;// TODO: setup the initial game situation here&amp;lt;/code&amp;gt;, initialize the board&amp;lt;pre&amp;gt;&lt;br /&gt;
        // Init the board&lt;br /&gt;
        $sql = &amp;quot;INSERT INTO board (board_x,board_y,board_player) VALUES &amp;quot;;&lt;br /&gt;
        $sql_values = array();&lt;br /&gt;
        list( $blackplayer_id, $whiteplayer_id ) = array_keys( $players );&lt;br /&gt;
        for( $x=1; $x&amp;lt;=8; $x++ )&lt;br /&gt;
        {&lt;br /&gt;
            for( $y=1; $y&amp;lt;=8; $y++ )&lt;br /&gt;
            {&lt;br /&gt;
                $token_value = &amp;quot;NULL&amp;quot;;&lt;br /&gt;
                if( ($x==4 &amp;amp;&amp;amp; $y==4) || ($x==5 &amp;amp;&amp;amp; $y==5) )  // Initial positions of white player&lt;br /&gt;
                    $token_value = &amp;quot;&#039;$whiteplayer_id&#039;&amp;quot;;&lt;br /&gt;
                else if( ($x==4 &amp;amp;&amp;amp; $y==5) || ($x==5 &amp;amp;&amp;amp; $y==4) )  // Initial positions of black player&lt;br /&gt;
                    $token_value = &amp;quot;&#039;$blackplayer_id&#039;&amp;quot;;&lt;br /&gt;
                    &lt;br /&gt;
                $sql_values[] = &amp;quot;(&#039;$x&#039;,&#039;$y&#039;,$token_value)&amp;quot;;&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
        $sql .= implode( &#039;,&#039;, $sql_values );&lt;br /&gt;
        $this-&amp;gt;DbQuery( $sql );&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Board Initialization Explanation ====&lt;br /&gt;
&lt;br /&gt;
* We create one table entry for each square, with a &amp;lt;code&amp;gt;NULL&amp;lt;/code&amp;gt; value which means &amp;quot;empty square&amp;quot;&lt;br /&gt;
* On 4 of the squares, we place an initial token.&lt;br /&gt;
&lt;br /&gt;
After this, we set &amp;lt;code&amp;gt;activeNextPlayer&amp;lt;/code&amp;gt; to make the first player active at the beginning of the game (this line is already present in the default code template).&lt;br /&gt;
&lt;br /&gt;
If you didn&#039;t do it earlier, you need to remove the call to &amp;lt;code&amp;gt;self::reattributeColorsBasedOnPreferences()&amp;lt;/code&amp;gt; in &amp;lt;code&amp;gt;SetupNewGame()&amp;lt;/code&amp;gt;. If you don&#039;t, player color preferences will try (and fail) to override the two colors supported here.&lt;br /&gt;
&lt;br /&gt;
=== Show the Initial Token Setup ===&lt;br /&gt;
Now, we need to make these tokens appear on the client side. The first step is to return the token positions with our &amp;lt;code&amp;gt;getAllDatas()&amp;lt;/code&amp;gt; PHP method. &amp;lt;code&amp;gt;getAllDatas()&amp;lt;/code&amp;gt; is called during each page reload.&lt;br /&gt;
&lt;br /&gt;
In the &amp;lt;code&amp;gt;getAllDatas()&amp;lt;/code&amp;gt; method, after &amp;lt;code&amp;gt;// TODO: Gather all information about current game situation (visible by player $current_player_id)&amp;lt;/code&amp;gt;, add the following lines:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        // Get reversi board token&lt;br /&gt;
        $result[&#039;board&#039;] = self::getObjectListFromDB( &amp;quot;SELECT board_x x, board_y y, board_player player&lt;br /&gt;
                                                       FROM board&lt;br /&gt;
                                                       WHERE board_player IS NOT NULL&amp;quot; );&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Next, you may need to modify the query that gets player information to also get the player&#039;s colors. This is in the variable &amp;lt;code&amp;gt;$sql&amp;lt;/code&amp;gt;, above the lines you just inserted in &amp;lt;code&amp;gt;getAllDatas()&amp;lt;/code&amp;gt;. Below is what the line will look like. Notice how we&#039;ve added &amp;lt;code&amp;gt;player_color color&amp;lt;/code&amp;gt; to the sql query.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$sql = &amp;quot;SELECT player_id id, player_score score, player_color color FROM player &amp;quot;;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
We are using the BGA framework&#039;s &amp;lt;code&amp;gt;getObjectListFromDB()&amp;lt;/code&amp;gt; that formats the result of this SQL query in a PHP array with x, y and player attributes. We add it to the result associative array with the key &amp;lt;code&amp;gt;board&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Last, we process this array client side. Let&#039;s place a token on the board for each array item. We&#039;ll do this in our Javascript &amp;lt;code&amp;gt;setup&amp;lt;/code&amp;gt; method under the code we added to generate the squares. &lt;br /&gt;
&lt;br /&gt;
This will result in a removal or edit of the previously added line &amp;lt;code&amp;gt;this.addDiscOnBoard(2, 2, this.player_id);&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
for( var i in gamedatas.board )&lt;br /&gt;
{&lt;br /&gt;
    var square = gamedatas.board[i];&lt;br /&gt;
    &lt;br /&gt;
    if( square.player !== null )&lt;br /&gt;
    {&lt;br /&gt;
        this.addDiscOnBoard( square.x, square.y, square.player );&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;board&amp;lt;/code&amp;gt; entry created in &amp;lt;code&amp;gt;getAllDatas()&amp;lt;/code&amp;gt; is used here as &amp;lt;code&amp;gt;gamedatas.board&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Test the Game Start ===&lt;br /&gt;
Reload... and here we are:&lt;br /&gt;
&lt;br /&gt;
[[File:reversi5.jpg]]&lt;br /&gt;
&lt;br /&gt;
It starts to feel like Reversi here...&lt;br /&gt;
&lt;br /&gt;
== The game state machine ==&lt;br /&gt;
&lt;br /&gt;
Stop your game, again. You&#039;re about to start the core game logic.&lt;br /&gt;
&lt;br /&gt;
You already read [http://www.slideshare.net/boardgamearena/bga-studio-focus-on-bga-game-state-machine Focus on BGA game state machine], so you know that this is the heart of your game logic. For reversi, it&#039;s relatively simple. Here&#039;s a diagram of our game state machine:&lt;br /&gt;
&lt;br /&gt;
[[File:reversi6.jpg]]&lt;br /&gt;
&lt;br /&gt;
=== Build your States ===&lt;br /&gt;
And here&#039;s our &amp;lt;code&amp;gt;states.inc.php&amp;lt;/code&amp;gt;, according to this diagram:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$machinestates = array(&lt;br /&gt;
&lt;br /&gt;
    ST_BGA_GAME_SETUP =&amp;gt; array(&lt;br /&gt;
        &amp;quot;name&amp;quot; =&amp;gt; &amp;quot;gameSetup&amp;quot;,&lt;br /&gt;
        &amp;quot;description&amp;quot; =&amp;gt; clienttranslate(&amp;quot;Game setup&amp;quot;),&lt;br /&gt;
        &amp;quot;type&amp;quot; =&amp;gt; &amp;quot;manager&amp;quot;,&lt;br /&gt;
        &amp;quot;action&amp;quot; =&amp;gt; &amp;quot;stGameSetup&amp;quot;,&lt;br /&gt;
        &amp;quot;transitions&amp;quot; =&amp;gt; array( &amp;quot;&amp;quot; =&amp;gt; ST_PLAYER_PLAY_DISC )&lt;br /&gt;
    ),&lt;br /&gt;
    &lt;br /&gt;
    ST_PLAYER_PLAY_DISC =&amp;gt; array(&lt;br /&gt;
        &amp;quot;name&amp;quot; =&amp;gt; &amp;quot;playerTurn&amp;quot;,&lt;br /&gt;
		&amp;quot;description&amp;quot; =&amp;gt; clienttranslate(&#039;${actplayer} must play a disc&#039;),&lt;br /&gt;
		&amp;quot;descriptionmyturn&amp;quot; =&amp;gt; clienttranslate(&#039;${you} must play a disc&#039;),&lt;br /&gt;
        &amp;quot;type&amp;quot; =&amp;gt; &amp;quot;activeplayer&amp;quot;,&lt;br /&gt;
        &amp;quot;args&amp;quot; =&amp;gt; &amp;quot;argPlayerTurn&amp;quot;,&lt;br /&gt;
        &amp;quot;possibleactions&amp;quot; =&amp;gt; array( &#039;actPlayDisc&#039; ),&lt;br /&gt;
        &amp;quot;transitions&amp;quot; =&amp;gt; array( &amp;quot;playDisc&amp;quot; =&amp;gt; ST_NEXT_PLAYER, &amp;quot;zombiePass&amp;quot; =&amp;gt; ST_NEXT_PLAYER )&lt;br /&gt;
    ),&lt;br /&gt;
    &lt;br /&gt;
    ST_NEXT_PLAYER =&amp;gt; array(&lt;br /&gt;
        &amp;quot;name&amp;quot; =&amp;gt; &amp;quot;nextPlayer&amp;quot;,&lt;br /&gt;
        &amp;quot;type&amp;quot; =&amp;gt; &amp;quot;game&amp;quot;,&lt;br /&gt;
        &amp;quot;action&amp;quot; =&amp;gt; &amp;quot;stNextPlayer&amp;quot;,&lt;br /&gt;
        &amp;quot;updateGameProgression&amp;quot; =&amp;gt; true,        &lt;br /&gt;
        &amp;quot;transitions&amp;quot; =&amp;gt; array( &amp;quot;nextTurn&amp;quot; =&amp;gt; ST_PLAYER_PLAY_DISC, &amp;quot;cantPlay&amp;quot; =&amp;gt; ST_NEXT_PLAYER, &amp;quot;endGame&amp;quot; =&amp;gt; ST_END_GAME )&lt;br /&gt;
    ),&lt;br /&gt;
   &lt;br /&gt;
    ST_END_GAME =&amp;gt; array(&lt;br /&gt;
        &amp;quot;name&amp;quot; =&amp;gt; &amp;quot;gameEnd&amp;quot;,&lt;br /&gt;
        &amp;quot;description&amp;quot; =&amp;gt; clienttranslate(&amp;quot;End of game&amp;quot;),&lt;br /&gt;
        &amp;quot;type&amp;quot; =&amp;gt; &amp;quot;manager&amp;quot;,&lt;br /&gt;
        &amp;quot;action&amp;quot; =&amp;gt; &amp;quot;stGameEnd&amp;quot;,&lt;br /&gt;
        &amp;quot;args&amp;quot; =&amp;gt; &amp;quot;argGameEnd&amp;quot;&lt;br /&gt;
    )&lt;br /&gt;
&lt;br /&gt;
);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We used constants to give an index to the different states. This is to avoid mistakes when we reuse these indexes on the transitions array.&lt;br /&gt;
&lt;br /&gt;
Let&#039;s create a file you&#039;ll put in modules/php/constants.inc.php :&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;?php&lt;br /&gt;
&lt;br /&gt;
/*&lt;br /&gt;
 * State constants&lt;br /&gt;
 */&lt;br /&gt;
const ST_BGA_GAME_SETUP = 1;&lt;br /&gt;
&lt;br /&gt;
const ST_PLAYER_PLAY_DISC = 10;&lt;br /&gt;
const ST_NEXT_PLAYER = 11;&lt;br /&gt;
&lt;br /&gt;
const ST_END_GAME = 99;&lt;br /&gt;
&lt;br /&gt;
?&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You will also need to add &amp;lt;code&amp;gt;require_once(&amp;quot;modules/php/constants.inc.php&amp;quot;);&amp;lt;/code&amp;gt; at the beginning of the state.inc.php to load these constants.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Now, in &amp;lt;code&amp;gt;reversi.game.php&amp;lt;/code&amp;gt; let&#039;s create the methods that are declared in this game states description file:&lt;br /&gt;
* &amp;lt;code&amp;gt;argPlayerTurn&amp;lt;/code&amp;gt;: referenced in the &amp;lt;code&amp;gt;args&amp;lt;/code&amp;gt; property of the &amp;lt;code&amp;gt;playerTurn&amp;lt;/code&amp;gt; state; this is the name of the method to call to retrieve arguments for this gamestate. Arguments are sent to the client side to be used on &amp;lt;code&amp;gt;onEnteringState&amp;lt;/code&amp;gt; or to set arguments in the gamestate description.&lt;br /&gt;
* &amp;lt;code&amp;gt;stNextPlayer&amp;lt;/code&amp;gt;: referenced in the &amp;lt;code&amp;gt;action&amp;lt;/code&amp;gt; property of the &amp;lt;code&amp;gt;nextPlayer&amp;lt;/code&amp;gt; state; this is the name of the method to call when this game state become the current game state.&lt;br /&gt;
&lt;br /&gt;
=== Test Your States ===&lt;br /&gt;
... and start a new Reversi game.&lt;br /&gt;
&lt;br /&gt;
As you can see on the screen capture below, the BGA framework makes the game jump to our first game state &amp;lt;code&amp;gt;playerTurn&amp;lt;/code&amp;gt; right after the initial setup. That&#039;s why the status bar contains the description of &amp;lt;code&amp;gt;playerTurn&amp;lt;/code&amp;gt; state (&amp;quot;XXXX must play a disc&amp;quot;):&lt;br /&gt;
&lt;br /&gt;
[[File:reversi7.jpg]]&lt;br /&gt;
&lt;br /&gt;
== The rules ==&lt;br /&gt;
&lt;br /&gt;
We will use the &amp;lt;code&amp;gt;getPossibleMoves&amp;lt;/code&amp;gt; PHP method to:&lt;br /&gt;
* Indicate to the current player where she is allowed to play by returning a list of coordinates&lt;br /&gt;
* Check if the player has the right to play in the spot they choose&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;&lt;br /&gt;
Example of getPossibleMoves here https://gist.github.com/leocaseiro/a8bc2851bd0caddd06685b5035937d15&lt;br /&gt;
&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This is pure PHP programming here, and there are no special things from the BGA framework that can be used. This is why we won&#039;t go into details here. The overall idea is:&lt;br /&gt;
* Create a &amp;lt;code&amp;gt;getTurnedOverDiscs(x,y)&amp;lt;/code&amp;gt; method that returns coordinates of discs that would be turned over if a token would be played at &amp;lt;code&amp;gt;x&amp;lt;/code&amp;gt;,&amp;lt;code&amp;gt;y&amp;lt;/code&amp;gt;.&lt;br /&gt;
* Loop through all free squares of the board and call the &amp;lt;code&amp;gt;getTurnedOverDiscs&amp;lt;/code&amp;gt; method on each of them. If at least 1 token is turned over, this is a valid move.&lt;br /&gt;
&lt;br /&gt;
IMPORTANT: Making a database query is slow! Please don&#039;t load the entire game board with a SQL query multiple times. In our implementation, we load the entire board once at the beginning of &amp;lt;code&amp;gt;getPossibleMoves&amp;lt;/code&amp;gt;, and then pass the board as an argument to all methods.&lt;br /&gt;
&lt;br /&gt;
If you want to look into details, please look at the &amp;quot;utility method&amp;quot; sections of &amp;lt;code&amp;gt;reversi.game.php&amp;lt;/code&amp;gt;. If building the tutorial yourself, copy the functions under &amp;quot;Utility functions&amp;quot; comment from the Reversi tutorial.&lt;br /&gt;
&lt;br /&gt;
== Display allowed moves ==&lt;br /&gt;
&lt;br /&gt;
Now we want to highlight the squares where the player can place a disc.&lt;br /&gt;
&lt;br /&gt;
To do this, we add a &amp;lt;code&amp;gt;argPlayerTurn&amp;lt;/code&amp;gt; method in &amp;lt;code&amp;gt;reversi.game.php&amp;lt;/code&amp;gt;. This method is called on the server each time we enter into &amp;lt;code&amp;gt;playerTurn&amp;lt;/code&amp;gt; game state, and its result is transferred automatically to the client-side:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
function argPlayerTurn(): array&lt;br /&gt;
{&lt;br /&gt;
    return [&lt;br /&gt;
        &#039;possibleMoves&#039; =&amp;gt; $this-&amp;gt;getPossibleMoves( intval($this-&amp;gt;getActivePlayerId()) )&lt;br /&gt;
    ];&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We use the &amp;lt;code&amp;gt;getPossibleMoves&amp;lt;/code&amp;gt; method we just developed.&lt;br /&gt;
&lt;br /&gt;
Each time we enter into a new game state, we use the &amp;lt;code&amp;gt;onEnteringState&amp;lt;/code&amp;gt; Javascript method (in the &amp;lt;code&amp;gt;reversi.js&amp;lt;/code&amp;gt; file, under &amp;quot;Game &amp;amp; client states&amp;quot;). This lets us use the data returned by the method above on the client side.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        onEnteringState: function( stateName, args )&lt;br /&gt;
        {&lt;br /&gt;
           console.log( &#039;Entering state: &#039;+stateName );&lt;br /&gt;
            &lt;br /&gt;
            switch( stateName )&lt;br /&gt;
            {&lt;br /&gt;
            case &#039;playerTurn&#039;:&lt;br /&gt;
                this.updatePossibleMoves( args.args.possibleMoves );&lt;br /&gt;
                break;&lt;br /&gt;
            }&lt;br /&gt;
        },&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
So, when we enter into &amp;lt;code&amp;gt;playerTurn&amp;lt;/code&amp;gt; game state, we call our &amp;lt;code&amp;gt;updatePossibleMoves&amp;lt;/code&amp;gt; method (under the &amp;quot;Utility methods&amp;quot; section). This method looks like this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
updatePossibleMoves: function( possibleMoves )&lt;br /&gt;
{&lt;br /&gt;
    // Remove current possible moves&lt;br /&gt;
    document.querySelectorAll(&#039;.possibleMove&#039;).forEach(div =&amp;gt; div.classList.remove(&#039;possibleMove&#039;));&lt;br /&gt;
&lt;br /&gt;
    for( var x in possibleMoves )&lt;br /&gt;
    {&lt;br /&gt;
        for( var y in possibleMoves[ x ] )&lt;br /&gt;
        {&lt;br /&gt;
            // x,y is a possible move&lt;br /&gt;
            document.getElementById(`square_${x}_${y}`).classList.add(&#039;possibleMove&#039;);&lt;br /&gt;
        }            &lt;br /&gt;
    }&lt;br /&gt;
                &lt;br /&gt;
    this.addTooltipToClass( &#039;possibleMove&#039;, &#039;&#039;, _(&#039;Place a disc here&#039;) );&lt;br /&gt;
},&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Here&#039;s what this does. At first, it removes all &amp;lt;code&amp;gt;possibleMove&amp;lt;/code&amp;gt; classes currently applied with the very useful &amp;lt;code&amp;gt;document.querySelectorAll&amp;lt;/code&amp;gt; method.&lt;br /&gt;
&lt;br /&gt;
Then it loops through all possible moves our PHP &amp;lt;code&amp;gt;updatePossibleMoves&amp;lt;/code&amp;gt; function created for us, and adds the &amp;lt;code&amp;gt;possibleMove&amp;lt;/code&amp;gt; class to each corresponding square.&lt;br /&gt;
&lt;br /&gt;
Finally, it uses the BGA framework &amp;lt;code&amp;gt;addTooltipToClass&amp;lt;/code&amp;gt; method to associate a tooltip to all those highlighted squares so that players can understand their meaning.&lt;br /&gt;
&lt;br /&gt;
To see the possible moves we need to create a CSS class (&amp;lt;code&amp;gt;possibleMove&amp;lt;/code&amp;gt;) that can be applied to a &amp;lt;code&amp;gt;square&amp;lt;/code&amp;gt; element to highlight it:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
.possibleMove {&lt;br /&gt;
    background-color: white;&lt;br /&gt;
    opacity: 0.2; &lt;br /&gt;
    cursor: pointer;  &lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
And here we are:&lt;br /&gt;
&lt;br /&gt;
[[File:reversi8.jpg.jpg]]&lt;br /&gt;
&lt;br /&gt;
== Let&#039;s play ==&lt;br /&gt;
&lt;br /&gt;
From now, it&#039;s better to restart a game with 2 players, because we are going to implement a complete Reversi turn. The summary of what we are going to do is:&lt;br /&gt;
* When we click on a &amp;lt;code&amp;gt;possibleMove&amp;lt;/code&amp;gt; square, send the move to the server.&lt;br /&gt;
* Server side, check the move is correct, apply Reversi rules and jump to next player.&lt;br /&gt;
* Client side, change the token position to reflect the move.&lt;br /&gt;
&lt;br /&gt;
First we associate each click on a square to one of our methods using our Javascript &amp;lt;code&amp;gt;setup&amp;lt;/code&amp;gt; method:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
document.querySelectorAll(&#039;.square&#039;).forEach(square =&amp;gt; square.addEventListener(&#039;click&#039;, e =&amp;gt; this.onPlayDisc(e)));&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note the use of the &amp;quot;dojo.query&amp;quot; method to get all HTML elements with &amp;quot;square&amp;quot; class in just one function call. Now, our &amp;quot;onPlayDisc&amp;quot; method is called each time someone clicks on a square.&lt;br /&gt;
&lt;br /&gt;
Here&#039;s our &amp;quot;onPlayDisc&amp;quot; method below:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
onPlayDisc: function( evt )&lt;br /&gt;
{&lt;br /&gt;
    // Stop this event propagation&lt;br /&gt;
    evt.preventDefault();&lt;br /&gt;
    evt.stopPropagation();&lt;br /&gt;
&lt;br /&gt;
    // Get the cliqued square x and y&lt;br /&gt;
    // Note: square id format is &amp;quot;square_X_Y&amp;quot;&lt;br /&gt;
    var coords = evt.currentTarget.id.split(&#039;_&#039;);&lt;br /&gt;
    var x = coords[1];&lt;br /&gt;
    var y = coords[2];&lt;br /&gt;
&lt;br /&gt;
    if(!document.getElementById(`square_${x}_${y}`).classList.contains(&#039;possibleMove&#039;)) {&lt;br /&gt;
        // This is not a possible move =&amp;gt; the click does nothing&lt;br /&gt;
        return ;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    this.bgaPerformAction(&amp;quot;actPlayDisc&amp;quot;, {&lt;br /&gt;
        x:x,&lt;br /&gt;
        y:y&lt;br /&gt;
    });&lt;br /&gt;
},&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
What we do here is:&lt;br /&gt;
* We stop the propagation of the Javascript &amp;lt;code&amp;gt;onclick&amp;lt;/code&amp;gt; event. Otherwise, it can lead to random behavior so it&#039;s always a good idea.&lt;br /&gt;
* We get the x/y coordinates of the square by using &amp;lt;code&amp;gt;evt.currentTarget.id&amp;lt;/code&amp;gt;&lt;br /&gt;
* We check that clicked square has the &amp;lt;code&amp;gt;possibleMove&amp;lt;/code&amp;gt; class, otherwise we know for sure that we can&#039;t play there.&lt;br /&gt;
* Finally, we make a call to the server using BGA &amp;lt;code&amp;gt;bgaPerformAction&amp;lt;/code&amp;gt; method with argument x and y. This call will check that &amp;lt;code&amp;gt;actPlayDisc&amp;lt;/code&amp;gt; action is possible, according to current game state (see &amp;lt;code&amp;gt;possibleactions&amp;lt;/code&amp;gt; entry in our &amp;lt;code&amp;gt;playerTurn&amp;lt;/code&amp;gt; game state defined above). This check is important to avoid issues if a player double clicks on a square.&lt;br /&gt;
&lt;br /&gt;
Now, we have to manage this &amp;lt;code&amp;gt;actPlayDisc&amp;lt;/code&amp;gt; action on the server side. At first, we introduce a &amp;lt;code&amp;gt;actPlayDisc&amp;lt;/code&amp;gt; entry point in our &amp;lt;code&amp;gt;reversi.action.php&amp;lt;/code&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
public function actPlayDisc()&lt;br /&gt;
{&lt;br /&gt;
    $this-&amp;gt;setAjaxMode();&lt;br /&gt;
    $x = (int)$this-&amp;gt;getArg( &amp;quot;x&amp;quot;, AT_posint, true );&lt;br /&gt;
    $y = (int)$this-&amp;gt;getArg( &amp;quot;y&amp;quot;, AT_posint, true );&lt;br /&gt;
    $result = $this-&amp;gt;game-&amp;gt;actPlayDisc( $x, $y );&lt;br /&gt;
    $this-&amp;gt;ajaxResponse( );&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
As you can see, we get the 2 arguments x and y from the javascript call, and call a corresponding &amp;lt;code&amp;gt;actPlayDisc&amp;lt;/code&amp;gt; method in our game logic (&amp;lt;code&amp;gt;reversi.game.php&amp;lt;/code&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
Now, let&#039;s have a look of this &amp;lt;code&amp;gt;actPlayDisc&amp;lt;/code&amp;gt; method:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
function actPlayDisc( int $x, int $y )&lt;br /&gt;
{&lt;br /&gt;
    // Check that this player is active and that this action is possible at this moment&lt;br /&gt;
    $this-&amp;gt;checkAction( &#039;actPlayDisc&#039; );  &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
... at first, we check that this action is possible according to current game state (see &amp;quot;possible action&amp;quot;). We already did it on client side, but it&#039;s important to do it on server side too (otherwise it would be possible to cheat).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        $player_id = intval($this-&amp;gt;getActivePlayerId()); &lt;br /&gt;
        &lt;br /&gt;
        // Now, check if this is a possible move&lt;br /&gt;
        $board = $this-&amp;gt;getBoard();&lt;br /&gt;
        $turnedOverDiscs = $this-&amp;gt;getTurnedOverDiscs( $x, $y, $player_id, $board );&lt;br /&gt;
        &lt;br /&gt;
        if( count( $turnedOverDiscs ) &amp;gt; 0 )&lt;br /&gt;
        {&lt;br /&gt;
            // This move is possible!&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
...now, we are using the &amp;lt;code&amp;gt;getTurnedOverDiscs&amp;lt;/code&amp;gt; method again to check that this move is possible.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
            // Let&#039;s place a disc at x,y and return all &amp;quot;$returned&amp;quot; discs to the active player&lt;br /&gt;
            &lt;br /&gt;
            $sql = &amp;quot;UPDATE board SET board_player=&#039;$player_id&#039;&lt;br /&gt;
                    WHERE ( board_x, board_y) IN ( &amp;quot;;&lt;br /&gt;
            &lt;br /&gt;
            foreach( $turnedOverDiscs as $turnedOver )&lt;br /&gt;
            {&lt;br /&gt;
                $sql .= &amp;quot;(&#039;&amp;quot;.$turnedOver[&#039;x&#039;].&amp;quot;&#039;,&#039;&amp;quot;.$turnedOver[&#039;y&#039;].&amp;quot;&#039;),&amp;quot;;&lt;br /&gt;
            }&lt;br /&gt;
            $sql .= &amp;quot;(&#039;$x&#039;,&#039;$y&#039;) ) &amp;quot;;&lt;br /&gt;
                       &lt;br /&gt;
            $this-&amp;gt;DbQuery( $sql );&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
... we update the database to change the color of all turned over disc + the disc we just placed.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
            // Update scores according to the number of disc on board&lt;br /&gt;
            $sql = &amp;quot;UPDATE player&lt;br /&gt;
                    SET player_score = (&lt;br /&gt;
                    SELECT COUNT( board_x ) FROM board WHERE board_player=player_id&lt;br /&gt;
                    )&amp;quot;;&lt;br /&gt;
            $this-&amp;gt;DbQuery( $sql );&lt;br /&gt;
            &lt;br /&gt;
            // Statistics&lt;br /&gt;
            $this-&amp;gt;incStat( count( $turnedOverDiscs ), &amp;quot;turnedOver&amp;quot;, $player_id );&lt;br /&gt;
            if( ($x==1 &amp;amp;&amp;amp; $y==1) || ($x==8 &amp;amp;&amp;amp; $y==1) || ($x==1 &amp;amp;&amp;amp; $y==8) || ($x==8 &amp;amp;&amp;amp; $y==8) )&lt;br /&gt;
                $this-&amp;gt;incStat( 1, &#039;discPlayedOnCorner&#039;, $player_id );&lt;br /&gt;
            else if( $x==1 || $x==8 || $y==1 || $y==8 )&lt;br /&gt;
                $this-&amp;gt;incStat( 1, &#039;discPlayedOnBorder&#039;, $player_id );&lt;br /&gt;
            else if( $x&amp;gt;=3 &amp;amp;&amp;amp; $x&amp;lt;=6 &amp;amp;&amp;amp; $y&amp;gt;=3 &amp;amp;&amp;amp; $y&amp;lt;=6 )&lt;br /&gt;
                $this-&amp;gt;incStat( 1, &#039;discPlayedOnCenter&#039;, $player_id );&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
... now, we update both player score by counting all disc, and we manage game statistics.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
            // Notify&lt;br /&gt;
            $this-&amp;gt;notifyAllPlayers( &amp;quot;playDisc&amp;quot;, clienttranslate( &#039;${player_name} plays a disc and turns over ${returned_nbr} disc(s)&#039; ), array(&lt;br /&gt;
                &#039;player_id&#039; =&amp;gt; $player_id,&lt;br /&gt;
                &#039;player_name&#039; =&amp;gt; $this-&amp;gt;getActivePlayerName(),&lt;br /&gt;
                &#039;returned_nbr&#039; =&amp;gt; count( $turnedOverDiscs ),&lt;br /&gt;
                &#039;x&#039; =&amp;gt; $x,&lt;br /&gt;
                &#039;y&#039; =&amp;gt; $y&lt;br /&gt;
            ) );&lt;br /&gt;
&lt;br /&gt;
            $this-&amp;gt;notifyAllPlayers( &amp;quot;turnOverDiscs&amp;quot;, &#039;&#039;, array(&lt;br /&gt;
                &#039;player_id&#039; =&amp;gt; $player_id,&lt;br /&gt;
                &#039;turnedOver&#039; =&amp;gt; $turnedOverDiscs&lt;br /&gt;
            ) );&lt;br /&gt;
            &lt;br /&gt;
            $newScores = $this-&amp;gt;getCollectionFromDb( &amp;quot;SELECT player_id, player_score FROM player&amp;quot;, true );&lt;br /&gt;
            $this-&amp;gt;notifyAllPlayers( &amp;quot;newScores&amp;quot;, &amp;quot;&amp;quot;, array(&lt;br /&gt;
                &amp;quot;scores&amp;quot; =&amp;gt; $newScores&lt;br /&gt;
            ) );&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
... then we notify about all these changes. We are using for that 3 notifications (&amp;lt;code&amp;gt;playDisc&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;turnOverDiscs&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;newScores&amp;lt;/code&amp;gt; that we are going to implement on client side later). Note that the description of the &amp;lt;code&amp;gt;playDisc&amp;lt;/code&amp;gt; notification will be logged in the game log.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
            // Then, go to the next state&lt;br /&gt;
            $this-&amp;gt;gamestate-&amp;gt;nextState( &#039;playDisc&#039; );&lt;br /&gt;
        }&lt;br /&gt;
        else&lt;br /&gt;
            throw new BgaSystemException( &amp;quot;Impossible move&amp;quot; );&lt;br /&gt;
    }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
... finally, we jump to the next game state if everything goes fine (&amp;lt;code&amp;gt;playDisc&amp;lt;/code&amp;gt; is the name of a transition in the &amp;lt;code&amp;gt;playerTurn&amp;lt;/code&amp;gt; game state description above which leads to state 11 which is &amp;lt;code&amp;gt;nextPlayer&amp;lt;/code&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
To make the statistics work, we have to initialize them in &amp;lt;code&amp;gt;stats.json&amp;lt;/code&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
  &amp;quot;player&amp;quot;: {&lt;br /&gt;
    &amp;quot;discPlayedOnCorner&amp;quot;: {&lt;br /&gt;
      &amp;quot;id&amp;quot;: 10,&lt;br /&gt;
      &amp;quot;name&amp;quot;: &amp;quot;Discs played on a corner&amp;quot;,&lt;br /&gt;
      &amp;quot;type&amp;quot;: &amp;quot;int&amp;quot;&lt;br /&gt;
    },&lt;br /&gt;
    &amp;quot;discPlayedOnBorder&amp;quot;: {&lt;br /&gt;
      &amp;quot;id&amp;quot;: 11,&lt;br /&gt;
      &amp;quot;name&amp;quot;: &amp;quot;Discs played on a border&amp;quot;,&lt;br /&gt;
      &amp;quot;type&amp;quot;: &amp;quot;int&amp;quot;&lt;br /&gt;
    },&lt;br /&gt;
    &amp;quot;discPlayedOnCenter&amp;quot;: {&lt;br /&gt;
      &amp;quot;id&amp;quot;: 12,&lt;br /&gt;
      &amp;quot;name&amp;quot;: &amp;quot;Discs played on board center part&amp;quot;,&lt;br /&gt;
      &amp;quot;type&amp;quot;: &amp;quot;int&amp;quot;&lt;br /&gt;
    },&lt;br /&gt;
    &amp;quot;turnedOver&amp;quot;: {&lt;br /&gt;
      &amp;quot;id&amp;quot;: 13,&lt;br /&gt;
      &amp;quot;name&amp;quot;: &amp;quot;Number of discs turned over&amp;quot;,&lt;br /&gt;
      &amp;quot;type&amp;quot;: &amp;quot;int&amp;quot;&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
A last thing to do on the server side is to activate the next player when we enter the &amp;lt;code&amp;gt;nextPlayer&amp;lt;/code&amp;gt; game state (in the &amp;lt;code&amp;gt;reversi.game.php&amp;lt;/code&amp;gt; file, under &amp;quot;Game state reactions&amp;quot;):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    function stNextPlayer(): void&lt;br /&gt;
    {&lt;br /&gt;
        // Active next player&lt;br /&gt;
        $player_id = intval($this-&amp;gt;activeNextPlayer());&lt;br /&gt;
&lt;br /&gt;
        // Check if both player has at least 1 discs, and if there are free squares to play&lt;br /&gt;
        $player_to_discs = $this-&amp;gt;getCollectionFromDb( &amp;quot;SELECT board_player, COUNT( board_x )&lt;br /&gt;
                                                       FROM board&lt;br /&gt;
                                                       GROUP BY board_player&amp;quot;, true );&lt;br /&gt;
&lt;br /&gt;
        if( ! isset( $player_to_discs[ null ] ) )&lt;br /&gt;
        {&lt;br /&gt;
            // Index 0 has not been set =&amp;gt; there&#039;s no more free place on the board !&lt;br /&gt;
            // =&amp;gt; end of the game&lt;br /&gt;
            $this-&amp;gt;gamestate-&amp;gt;nextState( &#039;endGame&#039; );&lt;br /&gt;
            return ;&lt;br /&gt;
        }&lt;br /&gt;
        else if( ! isset( $player_to_discs[ $player_id ] ) )&lt;br /&gt;
        {&lt;br /&gt;
            // Active player has no more disc on the board =&amp;gt; he looses immediately&lt;br /&gt;
            $this-&amp;gt;gamestate-&amp;gt;nextState( &#039;endGame&#039; );&lt;br /&gt;
            return ;&lt;br /&gt;
        }&lt;br /&gt;
        &lt;br /&gt;
        // Can this player play?&lt;br /&gt;
&lt;br /&gt;
        $possibleMoves = $this-&amp;gt;getPossibleMoves( $player_id );&lt;br /&gt;
        if( count( $possibleMoves ) == 0 )&lt;br /&gt;
        {&lt;br /&gt;
&lt;br /&gt;
            // This player can&#039;t play&lt;br /&gt;
            // Can his opponent play ?&lt;br /&gt;
            $opponent_id = (int)$this-&amp;gt;getUniqueValueFromDb( &amp;quot;SELECT player_id FROM player WHERE player_id!=&#039;$player_id&#039; &amp;quot; );&lt;br /&gt;
            if( count( $this-&amp;gt;getPossibleMoves( $opponent_id ) ) == 0 )&lt;br /&gt;
            {&lt;br /&gt;
                // Nobody can move =&amp;gt; end of the game&lt;br /&gt;
                $this-&amp;gt;gamestate-&amp;gt;nextState( &#039;endGame&#039; );&lt;br /&gt;
            }&lt;br /&gt;
            else&lt;br /&gt;
            {            &lt;br /&gt;
                // =&amp;gt; pass his turn&lt;br /&gt;
                $this-&amp;gt;gamestate-&amp;gt;nextState( &#039;cantPlay&#039; );&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
        else&lt;br /&gt;
        {&lt;br /&gt;
            // This player can play. Give him some extra time&lt;br /&gt;
            $this-&amp;gt;giveExtraTime( $player_id );&lt;br /&gt;
            $this-&amp;gt;gamestate-&amp;gt;nextState( &#039;nextTurn&#039; );&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Now, when we play a token, the rules are checked and the token appears in the database.&lt;br /&gt;
&lt;br /&gt;
[[File:reversi9.jpg]]&lt;br /&gt;
&lt;br /&gt;
Of course, as we don&#039;t manage notifications on client side, we need to press F5 after each move to see the changes on the board.&lt;br /&gt;
&lt;br /&gt;
== Make the move appear automatically ==&lt;br /&gt;
&lt;br /&gt;
Now, what we have to do is process the notifications sent by the server and make the move appear on the interface.&lt;br /&gt;
&lt;br /&gt;
In our &amp;lt;code&amp;gt;setupNotifications&amp;lt;/code&amp;gt; method in &amp;lt;code&amp;gt;reversi.js&amp;lt;/code&amp;gt;, we register 2 methods for the 2 notifications we created at the previous step (&amp;lt;code&amp;gt;playDisc&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;turnOverDiscs&amp;lt;/code&amp;gt;):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
            const notifs = [&lt;br /&gt;
                [&#039;playDisc&#039;, 500],&lt;br /&gt;
                [&#039;turnOverDiscs&#039;, 1500],&lt;br /&gt;
                [&#039;newScores&#039;, 1],&lt;br /&gt;
            ];&lt;br /&gt;
    &lt;br /&gt;
            notifs.forEach((notif) =&amp;gt; {&lt;br /&gt;
                dojo.subscribe(notif[0], this, `notif_${notif[0]}`);&lt;br /&gt;
                this.notifqueue.setSynchronous(notif[0], notif[1]);&lt;br /&gt;
            });&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We will associate each of our 3 notifications with a method prefixed with &amp;lt;code&amp;gt;notif_&amp;lt;/code&amp;gt;. We also define these notifications as &amp;quot;synchronous&amp;quot;, with a duration in millisecond. It tells the user interface to wait some time after executing the notification, to let the animation end before starting the next notification. In our specific case, the animation will be the following:&lt;br /&gt;
* Make a disc slide from the player panel to its place on the board&lt;br /&gt;
* (wait 500ms)&lt;br /&gt;
* Make all turned over discs blink (and of course turned them over)&lt;br /&gt;
* (wait 1500ms)&lt;br /&gt;
* Update the player scores&lt;br /&gt;
* (no real delay on this one)&lt;br /&gt;
&lt;br /&gt;
The second part of the code is a generic thing to automatically bind the notifs we configured to the &amp;lt;code&amp;gt;notif_&amp;lt;notifName&amp;gt;&amp;lt;/code&amp;gt; functions we are about to create.&lt;br /&gt;
&lt;br /&gt;
Let&#039;s have a look now on the &amp;lt;code&amp;gt;playDisc&amp;lt;/code&amp;gt; notification handler method:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
notif_playDisc: function( notif )&lt;br /&gt;
{&lt;br /&gt;
    // Remove current possible moves (makes the board more clear)&lt;br /&gt;
    document.querySelectorAll(&#039;.possibleMove&#039;).forEach(div =&amp;gt; div.classList.remove(&#039;possibleMove&#039;));&lt;br /&gt;
&lt;br /&gt;
    this.addDiscOnBoard( notif.args.x, notif.args.y, notif.args.player_id );&lt;br /&gt;
},&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
No surprise here, we re-used some existing stuff to:&lt;br /&gt;
* Remove the highlighted squares.&lt;br /&gt;
* Add a new disc on board, coming from player panel.&lt;br /&gt;
&lt;br /&gt;
Now, here&#039;s the method that handles the &amp;lt;code&amp;gt;turnOverDiscs&amp;lt;/code&amp;gt; notification:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
notif_turnOverDiscs: function( notif )&lt;br /&gt;
{&lt;br /&gt;
    // Get the color of the player who is returning the discs&lt;br /&gt;
    var targetColor = this.gamedatas.players[ notif.args.player_id ].color;&lt;br /&gt;
&lt;br /&gt;
    // Made these discs blinking and set them to the specified color&lt;br /&gt;
    for( var i in notif.args.turnedOver )&lt;br /&gt;
    {&lt;br /&gt;
        var disc = notif.args.turnedOver[ i ];&lt;br /&gt;
        &lt;br /&gt;
        // Make the disc blink 2 times&lt;br /&gt;
        var anim = dojo.fx.chain( [&lt;br /&gt;
            dojo.fadeOut( { node: &#039;disc_&#039;+disc.x+&#039;&#039;+disc.y } ),&lt;br /&gt;
            dojo.fadeIn( { node: &#039;disc_&#039;+disc.x+&#039;&#039;+disc.y } ),&lt;br /&gt;
            dojo.fadeOut( { &lt;br /&gt;
                            node: &#039;disc_&#039;+disc.x+&#039;&#039;+disc.y,&lt;br /&gt;
                            onEnd: node =&amp;gt; $(node).dataset.color = targetColor,&lt;br /&gt;
                            } ),&lt;br /&gt;
            dojo.fadeIn( { node: &#039;disc_&#039;+disc.x+&#039;&#039;+disc.y  } )&lt;br /&gt;
                            &lt;br /&gt;
        ] ); // end of dojo.fx.chain&lt;br /&gt;
&lt;br /&gt;
        // ... and launch the animation&lt;br /&gt;
        anim.play();                &lt;br /&gt;
    }&lt;br /&gt;
},&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The list of the discs to be turned over has been made available by our server side code in &amp;lt;code&amp;gt;notif.args.turnedOver&amp;lt;/code&amp;gt; (see previous paragraph). We loop through all these discs, and create a complex animation using &amp;lt;code&amp;gt;dojo.Animation&amp;lt;/code&amp;gt; for each of them. The complete documentation on dojo animations [http://dojotoolkit.org/documentation/tutorials/1.6/animation/ can be found here].&lt;br /&gt;
&lt;br /&gt;
In few words: we create a chain of 4 animations to make the disc fade out, fade in, fade out again, and fade in again. At the end of the second fade out, we change the color of the disc. Finally, we launch the animation with &amp;lt;code&amp;gt;play()&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
And Also the notification to update the scores:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
notif_newScores: function( notif )&lt;br /&gt;
        {&lt;br /&gt;
            for( var player_id in notif.args.scores )&lt;br /&gt;
            {&lt;br /&gt;
                var newScore = notif.args.scores[ player_id ];&lt;br /&gt;
                this.scoreCtrl[ player_id ].toValue( newScore );&lt;br /&gt;
            }&lt;br /&gt;
        },&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Category:Studio]]&lt;/div&gt;</summary>
		<author><name>Sguzzer Gunayer</name></author>
	</entry>
	<entry>
		<id>https://en.doc.boardgamearena.com/index.php?title=Tutorial_reversi&amp;diff=22415</id>
		<title>Tutorial reversi</title>
		<link rel="alternate" type="text/html" href="https://en.doc.boardgamearena.com/index.php?title=Tutorial_reversi&amp;diff=22415"/>
		<updated>2024-09-03T14:51:01Z</updated>

		<summary type="html">&lt;p&gt;Sguzzer Gunayer: /* Set Token Colors in setupNewGame in .game.php file */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&#039;&#039;&#039;Check out an update version&#039;&#039;&#039; of the [[BGA Type Safe Template: Reversi|Reversi Tutorial]] which uses the [[BGA Type Safe Template]]. {{Studio_Framework_Navigation}}&lt;br /&gt;
&lt;br /&gt;
== Introduction ==&lt;br /&gt;
&lt;br /&gt;
Using this tutorial, you can build a complete working game on the BGA environment: Reversi.&lt;br /&gt;
&lt;br /&gt;
Before you read this tutorial, you must:&lt;br /&gt;
* Read the overall presentations of the BGA Framework ([[Studio|see here]]).&lt;br /&gt;
* Know the [http://en.wikipedia.org/wiki/Reversi#Rules rules of Reversi].&lt;br /&gt;
* Know the languages used on BGA: PHP, SQL, HTML, CSS, Javascript&lt;br /&gt;
* &#039;&#039;&#039;Setup your development environment&#039;&#039;&#039; [http://en.doc.boardgamearena.com/First_steps_with_BGA_Studio First Steps with BGA Studio]&lt;br /&gt;
&lt;br /&gt;
== Create your first game ==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Note: you should already have created a project following instructions in [[First_steps_with_BGA_Studio#Create_a_new_game_project|Create a new game project]]. While you will find a &#039;&#039;&#039;reversi&#039;&#039;&#039; directory in your SFTP folder, do not use it for this tutorial. Instead, use the project you have created as an (empty) starting point.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
With the initial skeleton of code provided in your project, you can already start a game from the BGA Studio:&lt;br /&gt;
* Go to your [https://studio.boardgamearena.com/controlpanel studio Control panel], then Manage games and select your initial project. &#039;&#039;Note: there are warnings displayed about a missing BGG_ID and presentation text. You can ignore that for now.&#039;&#039;&lt;br /&gt;
* Click the Play link next to your project name. This will open the Play page and offer to create a new table for your project. &#039;&#039;Optional: click the Heart icon to add your project to your favorite games list.&#039;&#039;&lt;br /&gt;
* On the Play page, on the top of the page, make sure that your settings are &amp;quot;Simple game&amp;quot;, &amp;quot;Real time&amp;quot; and &amp;quot;Manual&amp;quot;.&lt;br /&gt;
* Click &amp;quot;Create table&amp;quot; to create a table of your project. &lt;br /&gt;
* For now, we are going to work with one player only, so use the (-) button to set the number of players to 1. Most of the time it is simpler to proceed with only one player during the early phase of development of your game, as it&#039;s easy and fast to start/stop games. If you choose to start with 2 players, you should see two names on the right: testdude0 and testdude1. To switch between them, press the red arrow button near their names; it will open another tab. This way you don&#039;t need to login and logout from multiple accounts.) &lt;br /&gt;
* Reminder: Always use the &amp;quot;Express Start&amp;quot; button to start the game.&lt;br /&gt;
&lt;br /&gt;
Thus, you can start a &amp;quot;Reversi&amp;quot; game, and arrive on a void, empty game. Yeah.&lt;br /&gt;
&lt;br /&gt;
End the game by clicking on the game options icon on the top right, and then on &amp;quot;Express Stop&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
== Editing the game information (Optional) ==&lt;br /&gt;
&lt;br /&gt;
This step is optional and will fix the warnings on the project page (missing BGG_ID and presentation).&lt;br /&gt;
&lt;br /&gt;
==== Edits to fix Errors ====&lt;br /&gt;
* Edit your local copy of the &amp;lt;code&amp;gt;gameinfos.inc.php&amp;lt;/code&amp;gt; file:&lt;br /&gt;
** Change the &amp;lt;code&amp;gt;bgg_id&amp;lt;/code&amp;gt; value from &amp;lt;code&amp;gt;0&amp;lt;/code&amp;gt; to &amp;lt;code&amp;gt;2389&amp;lt;/code&amp;gt; - that&#039;s around line 37.&lt;br /&gt;
** Add &amp;lt;code&amp;gt;1,&amp;lt;/code&amp;gt; to the players array - that&#039;s around line 41.&lt;br /&gt;
** Change the presentation array content - that&#039;s around line 134. Uncomment one line and change the text. Remove the final comma if you keep only one line!&lt;br /&gt;
* Upload the &amp;lt;code&amp;gt;gameinfos.inc.php&amp;lt;/code&amp;gt; file to the SFTP server (see [[First_steps_with_BGA_Studio#Connect_to_your_SFTP_folder|Connect to your SFTP folder]]).&lt;br /&gt;
&lt;br /&gt;
==== Test your Edits ====&lt;br /&gt;
* Go back to your project page, and in the &amp;quot;Game Information&amp;quot; section, click &amp;quot;Reload game informations&amp;quot;.&lt;br /&gt;
* Finally, refresh the project page in your browser (usually CTRL-F5).&lt;br /&gt;
&lt;br /&gt;
===== Not working? =====&lt;br /&gt;
Some changes will require bypassing the cache. It is often worth doing a hard refresh to make sure the&lt;br /&gt;
&lt;br /&gt;
Sometimes the cache will keep your changes from showing. Since this is a possibility, it will be useful to know how to bypass the cache. To do so you may manually clear cache or use a shortcut to refresh and ignore the cached version of the page. Here&#039;s how&lt;br /&gt;
&lt;br /&gt;
====== Windows ======&lt;br /&gt;
Chrome, Firefox, or Edge: Press &amp;lt;code&amp;gt;Ctrl+F5&amp;lt;/code&amp;gt; or &amp;lt;code&amp;gt;Shift+F5&amp;lt;/code&amp;gt; or &amp;lt;code&amp;gt;Ctrl+Shift+R&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====== Mac ======&lt;br /&gt;
Chrome or Firefox: Press &amp;lt;code&amp;gt;Shift+Command+R&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Safari for Mac: Press &amp;lt;code&amp;gt;Command+Option+E&amp;lt;/code&amp;gt; to empty the cache, then hold down Shift and click Reload in the toolbar&lt;br /&gt;
&lt;br /&gt;
== Make it look like Reversi ==&lt;br /&gt;
&lt;br /&gt;
Let&#039;s start with the board. This will give you a good idea of how things will look and where tokens should go.&lt;br /&gt;
&lt;br /&gt;
Be careful designing the layout of your game: you must always keep in mind that players with a 1024px screen width must be able to play. Usually, it means that the width of the play area can be 750px (in the worst case).&lt;br /&gt;
&lt;br /&gt;
For Reversi, it&#039;s useless to have a 750x750px board - much too big, so we chose this one which fit perfectly (536x528):&lt;br /&gt;
&lt;br /&gt;
[[File:Board.jpg]]&lt;br /&gt;
&lt;br /&gt;
Note that we are using a jpg file. Jpg files are lighter than png, so they are faster to load. Later, we are going to use PNGs for tokens because they allow for transparency.&lt;br /&gt;
&lt;br /&gt;
==== Add the board ====&lt;br /&gt;
use lowercase file names&lt;br /&gt;
* upload &amp;lt;code&amp;gt;board.jpg&amp;lt;/code&amp;gt; in your &amp;lt;code&amp;gt;img/&amp;lt;/code&amp;gt; directory. &lt;br /&gt;
* edit &amp;lt;code&amp;gt;reversi_reversi.tpl&amp;lt;/code&amp;gt; to add a &amp;lt;code&amp;gt;div&amp;lt;/code&amp;gt; for your board.&lt;br /&gt;
&lt;br /&gt;
Note: If you are building this game by following the tutorial, you will have a different project name than &amp;lt;code&amp;gt;reversi&amp;lt;/code&amp;gt; (i.e. &amp;lt;code&amp;gt;mygame_mygame.tpl&amp;lt;/code&amp;gt;). The file names in your project will be different than shown in this tutorial, replacing &amp;lt;code&amp;gt;reversi&amp;lt;/code&amp;gt; with your project name. Be sure that any code (other than comments) that references &amp;lt;code&amp;gt;reversi&amp;lt;/code&amp;gt; is changed to your actual project name.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;div id=&amp;quot;board&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* edit your &amp;lt;code&amp;gt;reversi.css&amp;lt;/code&amp;gt; file to transform it into a visible board:&lt;br /&gt;
&lt;br /&gt;
 #board {&lt;br /&gt;
    width: 536px;&lt;br /&gt;
    height: 528px;&lt;br /&gt;
    background-image: url(&#039;img/board.jpg&#039;);&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Important: refresh your page.&#039;&#039;&#039; Here&#039;s your board:[[File:reversi1.jpg]]&lt;br /&gt;
&lt;br /&gt;
If the board does not appear, refresh the page (always do this when you update the CSS file), and check the image filename. Remember file names are case sensitive!&lt;br /&gt;
&lt;br /&gt;
==== Code the Grid ====&lt;br /&gt;
Now, we need to create some invisible HTML elements where squares are. These elements will be used as position references for the white and black tokens. &lt;br /&gt;
&lt;br /&gt;
===== Build the grid of squares =====&lt;br /&gt;
The board is 8 squares by 8 squares. This means we need 64 squares. To avoid writing 64 individual &amp;lt;code&amp;gt;div&amp;lt;/code&amp;gt; elements on our template, we are going to generate the squares on JS setup.&lt;br /&gt;
&lt;br /&gt;
We&#039;ll do this in our Javascript &amp;lt;code&amp;gt;setup&amp;lt;/code&amp;gt; method under &amp;lt;code&amp;gt;// TODO: Set up your game interface here, according to &amp;quot;gamedatas&amp;quot;&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
const board = document.getElementById(&#039;board&#039;);&lt;br /&gt;
const hor_scale = 64.8;&lt;br /&gt;
const ver_scale = 64.4;&lt;br /&gt;
for (let x=1; x&amp;lt;=8; x++) {&lt;br /&gt;
    for (let y=1; y&amp;lt;=8; y++) {&lt;br /&gt;
        const left = Math.round((x - 1) * hor_scale + 10);&lt;br /&gt;
        const top = Math.round((y - 1) * ver_scale + 7);&lt;br /&gt;
        // we use afterbegin to make sure squares are placed before discs&lt;br /&gt;
        board.insertAdjacentHTML(`afterbegin`, `&amp;lt;div id=&amp;quot;square_${x}_${y}&amp;quot; class=&amp;quot;square&amp;quot; style=&amp;quot;left: ${left}px; top: ${top}px;&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;`);&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note: as you can see, squares in our &amp;lt;code&amp;gt;board.jpg&amp;lt;/code&amp;gt; files do not have an exact width/height in pixels, and that&#039;s the reason we are using floating point numbers here.&lt;br /&gt;
&lt;br /&gt;
===== Style Those Squares =====&lt;br /&gt;
Now, to finish our work and check if everything works fine, we are going to style our square a little bit in our CSS stylesheet:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#board {&lt;br /&gt;
    width: 536px;&lt;br /&gt;
    height: 528px;&lt;br /&gt;
    background-image: url(&#039;img/board.jpg&#039;);&lt;br /&gt;
    position: relative;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.square {&lt;br /&gt;
    width: 62px;&lt;br /&gt;
    height: 62px;&lt;br /&gt;
    position: absolute;&lt;br /&gt;
    background-color: red;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Explanations:&lt;br /&gt;
* With &amp;quot;position: relative&amp;quot; on board, we ensure square elements are positioned relatively to board.&lt;br /&gt;
* &amp;lt;code&amp;gt;background-color: red;&amp;lt;/code&amp;gt; is used for testing. This allows us to see the invisible elements. (You could instead do something like &amp;lt;code&amp;gt;outline: 2px solid orange;&amp;lt;/code&amp;gt; have fun and be creative)&lt;br /&gt;
&lt;br /&gt;
Let&#039;s refresh and check our (beautiful) squares:&lt;br /&gt;
&lt;br /&gt;
[[File:reversi2.jpg]]&lt;br /&gt;
&lt;br /&gt;
Now that you know the squares are there, you can remove the test line &amp;lt;code&amp;gt;background-color: red;&amp;lt;/code&amp;gt;  from your &amp;lt;code&amp;gt;.square&amp;lt;/code&amp;gt; class in the CSS stylesheet.&lt;br /&gt;
&lt;br /&gt;
===== Not Working? =====&lt;br /&gt;
If the styled squares do not appear, inspect and check your css (Chrome DevTools: Application &amp;gt; Frames &amp;gt; top &amp;gt; Stylesheets &amp;gt; reversi.css). &lt;br /&gt;
&lt;br /&gt;
== The Tokens ==&lt;br /&gt;
&lt;br /&gt;
Now, our board is ready for some tokens!&lt;br /&gt;
&lt;br /&gt;
[Note: Throughout this tutorial, sometimes &amp;quot;tokens&amp;quot; is used, and sometimes &amp;quot;discs&amp;quot; is used. They are often swapped if you&#039;re looking at code in the reversi example project.]&lt;br /&gt;
&lt;br /&gt;
=== Build the Token ===&lt;br /&gt;
There are quite a few steps before the tokens will appear. You may be used to testing after every change, but that won&#039;t work well here. The token will &#039;&#039;&#039;not&#039;&#039;&#039; show until you have add styles to the css, js template to the tpl, utility method in the js,  adjusted the php file, and added the token to the board in the js file.&lt;br /&gt;
&lt;br /&gt;
==== HTML in the .tpl file ====&lt;br /&gt;
At first, we introduce a new &#039;div&#039; element as a child of &amp;quot;board&amp;quot; to host all these tokens (in our template):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;div id=&amp;quot;board&amp;quot;&amp;gt;&lt;br /&gt;
    &lt;br /&gt;
    &amp;lt;div id=&amp;quot;discs&amp;quot;&amp;gt;&lt;br /&gt;
    &amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note: &amp;lt;code&amp;gt;discs&amp;lt;/code&amp;gt; is plural. This div will be used to hold the token divs. Shortly, we will use javascript to add individual tokens to the board.&lt;br /&gt;
&lt;br /&gt;
==== Add Token to img directory ====&lt;br /&gt;
Here&#039;s a new piece of art with the tokens. We need transparency here so we are using a png file:&lt;br /&gt;
&lt;br /&gt;
[[File:tokens.png]]&lt;br /&gt;
&lt;br /&gt;
Upload this image file &amp;lt;code&amp;gt;tokens.png&amp;lt;/code&amp;gt; in your &amp;lt;code&amp;gt;img/&amp;lt;/code&amp;gt; directory.&lt;br /&gt;
&lt;br /&gt;
Important Fun Fact: we are using ONE file for both tokens. It is really important to use a minimum number of graphic files for your game. This is called the &amp;quot;CSS sprite&amp;quot; technique, because it makes the game load faster and more reliable. [http://www.w3schools.com/css/css_image_sprites.asp Read more about CSS sprites].&lt;br /&gt;
&lt;br /&gt;
==== Style the Tokens in .css file ====&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
.disc {&lt;br /&gt;
    width: 56px;&lt;br /&gt;
    height: 56px;&lt;br /&gt;
    position: absolute;&lt;br /&gt;
    background-image: url(&#039;img/tokens.png&#039;);&lt;br /&gt;
    background-size: auto 100%;&lt;br /&gt;
}&lt;br /&gt;
.disc[data-color=&amp;quot;ffffff&amp;quot;] { background-position-x: 0%; }&lt;br /&gt;
.disc[data-color=&amp;quot;000000&amp;quot;] { background-position-x: 100%; }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
With this CSS code, we can set and change the token color by changing the data-color attribute. Using data instead of a class ensures it can be only one of them (the disc cannot be black and white at the same time).&lt;br /&gt;
&lt;br /&gt;
Note the &amp;quot;&amp;lt;code&amp;gt;position: absolute&amp;lt;/code&amp;gt;&amp;quot; which allows us to position tokens on the board and make them &amp;quot;slide&amp;quot; to their positions.&lt;br /&gt;
&lt;br /&gt;
==== Add Token Utility Method in .js file ====&lt;br /&gt;
Now, let&#039;s make the first token appear on our board. Tokens are not visible at the beginning of the game: they appear dynamically during the game. For this reason, we are going to make them appear from our Javascript code, using a template string&lt;br /&gt;
&lt;br /&gt;
Let&#039;s create a method in our Javascript code (in the &amp;lt;code&amp;gt;reversi.js&amp;lt;/code&amp;gt; file) that will make a token appear on the board, using this template. Add under the section //// Utility methods:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
addDiscOnBoard: function( x, y, player )&lt;br /&gt;
{&lt;br /&gt;
    var color = this.gamedatas.players[ player ].color;&lt;br /&gt;
    &lt;br /&gt;
    document.getElementById(&#039;discs&#039;).insertAdjacentHTML(&#039;beforeend&#039;, `&amp;lt;div class=&amp;quot;disc&amp;quot; data-color=&amp;quot;${color}&amp;quot; id=&amp;quot;disc_${x}${y}&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;`);&lt;br /&gt;
    &lt;br /&gt;
    this.placeOnObject( `disc_${x}${y}`, &#039;overall_player_board_&#039;+player );&lt;br /&gt;
    this.slideToObject( `disc_${x}${y}`, &#039;square_&#039;+x+&#039;_&#039;+y ).play();&lt;br /&gt;
},  &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===== Utility Method Explanation =====&lt;br /&gt;
* with &amp;lt;code&amp;gt;element.insertAdjacentHTML&amp;lt;/code&amp;gt; method, we create a HTML piece of code and insert it as a new child of &amp;lt;code&amp;gt;tokens&amp;lt;/code&amp;gt; div element.&lt;br /&gt;
* with &amp;lt;code&amp;gt;this.placeOnObject&amp;lt;/code&amp;gt; BGA method, we place this element over the panel of some player. &lt;br /&gt;
* Immediately after, using &amp;lt;code&amp;gt;this.slideToObject&amp;lt;/code&amp;gt; BGA method, we make the token slide to the &amp;lt;code&amp;gt;square&amp;lt;/code&amp;gt; element, its final destination.&lt;br /&gt;
* &amp;lt;code&amp;gt;&#039;overall_player_board_&#039;+player&amp;lt;/code&amp;gt; refers to the div element that contains each player&#039;s information and avatar. By initially placing the token here, it gives the effect that the player&#039;s avatar is throwing the token onto the board.&lt;br /&gt;
&lt;br /&gt;
Note: don&#039;t forget to call the &amp;lt;code&amp;gt;play()&amp;lt;/code&amp;gt;, otherwise the token will remain at its original location.&lt;br /&gt;
&lt;br /&gt;
Note: during this process, the parent of the new token HTML element will stay &amp;lt;code&amp;gt;tokens&amp;lt;/code&amp;gt;. &amp;lt;code&amp;gt;placeOnObject&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;slideToObject&amp;lt;/code&amp;gt; methods are &#039;&#039;only&#039;&#039; moving the position of elements on screen, and they are &#039;&#039;not&#039;&#039; modifying the HTML tree.&lt;br /&gt;
&lt;br /&gt;
==== Set Token Colors in &amp;lt;code&amp;gt;setupNewGame&amp;lt;/code&amp;gt; in &amp;lt;code&amp;gt;.game.php file&amp;lt;/code&amp;gt; ====&lt;br /&gt;
Before we can show a token, we need to set the player colors in the setupNewGame function in reversi.game.php:&lt;br /&gt;
&lt;br /&gt;
Replace &amp;lt;code&amp;gt;$default_colors = $gameinfos[&#039;player_colors&#039;];&amp;lt;/code&amp;gt; with the following line:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        $default_colors = array( &amp;quot;ffffff&amp;quot;, &amp;quot;000000&amp;quot; );&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note: A few lines below, you may have to remove the line &amp;lt;code&amp;gt;self::reattributeColorsBasedOnPreferences( $players, $gameinfos[&#039;player_colors&#039;] );&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Test the Token ===&lt;br /&gt;
Now, to test if everything works fine&lt;br /&gt;
&lt;br /&gt;
==== addTokenOnBoard() in .js file to Test ====&lt;br /&gt;
In &amp;lt;code&amp;gt;reversi.js&amp;lt;/code&amp;gt;, in &amp;lt;code&amp;gt;setup: function&amp;lt;/code&amp;gt;, under the code we added to generate the squares. &lt;br /&gt;
 this.addDiscOnBoard( 2, 2, this.player_id );&lt;br /&gt;
Now restart the game.&lt;br /&gt;
&lt;br /&gt;
A token should appear and slide immediately to its position, like this:&lt;br /&gt;
&lt;br /&gt;
[[File:reversi3.jpg]]&lt;br /&gt;
&lt;br /&gt;
== The database ==&lt;br /&gt;
&lt;br /&gt;
We did most of the client-side programming, so let&#039;s have a look on the other side now. To design the database model of our game, you will need to access the database. You won&#039;t need to do anything in database UI, yet.&lt;br /&gt;
&lt;br /&gt;
=== Accessing the Database ===&lt;br /&gt;
To access the database, start a game, then click &amp;quot;Go to game database&amp;quot; link at the bottom of our game, to access the database directly with a PhpMyAdmin instance.&lt;br /&gt;
&lt;br /&gt;
After the first time you&#039;ve acess the database, you could skip opening a game and instead, go to https://studio.boardgamearena.com/db/ . Your PhpMyAdmin username/password is in your welcome email.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note&#039;&#039;&#039;: do not remove existing tables&lt;br /&gt;
&lt;br /&gt;
=== Create Table in .sql file ===&lt;br /&gt;
Now, you are able to create the table(s) you need for your game, and report every SQL command used in your &amp;lt;code&amp;gt;dbmodel.sql&amp;lt;/code&amp;gt; file. &lt;br /&gt;
&lt;br /&gt;
The database model of Reversi is short: just one table with the squares of the board. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
CREATE TABLE IF NOT EXISTS `board` (&lt;br /&gt;
  `board_x` smallint(5) unsigned NOT NULL,&lt;br /&gt;
  `board_y` smallint(5) unsigned NOT NULL,&lt;br /&gt;
  `board_player` int(10) unsigned DEFAULT NULL,&lt;br /&gt;
  PRIMARY KEY (`board_x`,`board_y`)&lt;br /&gt;
) ENGINE=InnoDB DEFAULT CHARSET=utf8;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Add the above SQL to &amp;lt;code&amp;gt;dbmodel.sql&amp;lt;/code&amp;gt;. Pay special attention to the backtick &amp;lt;code&amp;gt;`&amp;lt;/code&amp;gt; character vs. the single quote &amp;lt;code&amp;gt;&#039;&amp;lt;/code&amp;gt; when working with SQL. &lt;br /&gt;
&lt;br /&gt;
=== Test the Table ===&lt;br /&gt;
Now, a new database with a &amp;lt;code&amp;gt;board&amp;lt;/code&amp;gt; table will be created each time we start a Reversi game. This is why after modifying our &amp;lt;code&amp;gt;dbmodel.sql&amp;lt;/code&amp;gt; it&#039;s a good time to stop your current game &amp;amp; start a new game.&lt;br /&gt;
&lt;br /&gt;
Start a new game and verify a table is created.&lt;br /&gt;
&lt;br /&gt;
== Setup the initial game position ==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note&#039;&#039;&#039;: From now on, you must launch the game with &#039;&#039;&#039;two players&#039;&#039;&#039; to get two &amp;lt;code&amp;gt;player_id&amp;lt;/code&amp;gt;s within the database. Otherwise, the game will crash.&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;setupNewGame&amp;lt;/code&amp;gt; method of our &amp;lt;code&amp;gt;reversi.game.php&amp;lt;/code&amp;gt; is called during initial setup. This initializes our data and places the starting tokens on the board. At the beginning of the game, there should be 4 tokens on the board.&lt;br /&gt;
&lt;br /&gt;
=== Initialize the Board in .game.php file ===&lt;br /&gt;
Under &amp;lt;code&amp;gt;// TODO: setup the initial game situation here&amp;lt;/code&amp;gt;, initialize the board&amp;lt;pre&amp;gt;&lt;br /&gt;
        // Init the board&lt;br /&gt;
        $sql = &amp;quot;INSERT INTO board (board_x,board_y,board_player) VALUES &amp;quot;;&lt;br /&gt;
        $sql_values = array();&lt;br /&gt;
        list( $blackplayer_id, $whiteplayer_id ) = array_keys( $players );&lt;br /&gt;
        for( $x=1; $x&amp;lt;=8; $x++ )&lt;br /&gt;
        {&lt;br /&gt;
            for( $y=1; $y&amp;lt;=8; $y++ )&lt;br /&gt;
            {&lt;br /&gt;
                $token_value = &amp;quot;NULL&amp;quot;;&lt;br /&gt;
                if( ($x==4 &amp;amp;&amp;amp; $y==4) || ($x==5 &amp;amp;&amp;amp; $y==5) )  // Initial positions of white player&lt;br /&gt;
                    $token_value = &amp;quot;&#039;$whiteplayer_id&#039;&amp;quot;;&lt;br /&gt;
                else if( ($x==4 &amp;amp;&amp;amp; $y==5) || ($x==5 &amp;amp;&amp;amp; $y==4) )  // Initial positions of black player&lt;br /&gt;
                    $token_value = &amp;quot;&#039;$blackplayer_id&#039;&amp;quot;;&lt;br /&gt;
                    &lt;br /&gt;
                $sql_values[] = &amp;quot;(&#039;$x&#039;,&#039;$y&#039;,$token_value)&amp;quot;;&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
        $sql .= implode( &#039;,&#039;, $sql_values );&lt;br /&gt;
        $this-&amp;gt;DbQuery( $sql );&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Board Initialization Explanation ====&lt;br /&gt;
&lt;br /&gt;
* We create one table entry for each square, with a &amp;lt;code&amp;gt;NULL&amp;lt;/code&amp;gt; value which means &amp;quot;empty square&amp;quot;&lt;br /&gt;
* On 4 of the squares, we place an initial token.&lt;br /&gt;
&lt;br /&gt;
After this, we set &amp;lt;code&amp;gt;activeNextPlayer&amp;lt;/code&amp;gt; to make the first player active at the beginning of the game (this line is already present in the default code template).&lt;br /&gt;
&lt;br /&gt;
If you didn&#039;t do it earlier, you need to remove the call to &amp;lt;code&amp;gt;self::reattributeColorsBasedOnPreferences()&amp;lt;/code&amp;gt; in &amp;lt;code&amp;gt;SetupNewGame()&amp;lt;/code&amp;gt;. If you don&#039;t, player color preferences will try (and fail) to override the two colors supported here.&lt;br /&gt;
&lt;br /&gt;
=== Show the Initial Token Setup ===&lt;br /&gt;
Now, we need to make these tokens appear on the client side. The first step is to return the token positions with our &amp;lt;code&amp;gt;getAllDatas()&amp;lt;/code&amp;gt; PHP method. &amp;lt;code&amp;gt;getAllDatas()&amp;lt;/code&amp;gt; is called during each page reload.&lt;br /&gt;
&lt;br /&gt;
In the &amp;lt;code&amp;gt;getAllDatas()&amp;lt;/code&amp;gt; method, after &amp;lt;code&amp;gt;// TODO: Gather all information about current game situation (visible by player $current_player_id)&amp;lt;/code&amp;gt;, add the following lines:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        // Get reversi board token&lt;br /&gt;
        $result[&#039;board&#039;] = self::getObjectListFromDB( &amp;quot;SELECT board_x x, board_y y, board_player player&lt;br /&gt;
                                                       FROM board&lt;br /&gt;
                                                       WHERE board_player IS NOT NULL&amp;quot; );&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Next, you may need to modify the query that gets player information to also get the player&#039;s colors. This is in the variable &amp;lt;code&amp;gt;$sql&amp;lt;/code&amp;gt;, above the lines you just inserted in &amp;lt;code&amp;gt;getAllDatas()&amp;lt;/code&amp;gt;. Below is what the line will look like. Notice how we&#039;ve added &amp;lt;code&amp;gt;player_color color&amp;lt;/code&amp;gt; to the sql query.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$sql = &amp;quot;SELECT player_id id, player_score score, player_color color FROM player &amp;quot;;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
We are using the BGA framework&#039;s &amp;lt;code&amp;gt;getObjectListFromDB()&amp;lt;/code&amp;gt; that formats the result of this SQL query in a PHP array with x, y and player attributes. We add it to the result associative array with the key &amp;lt;code&amp;gt;board&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Last, we process this array client side. Let&#039;s place a token on the board for each array item. We&#039;ll do this in our Javascript &amp;lt;code&amp;gt;setup&amp;lt;/code&amp;gt; method under the code we added to generate the squares. &lt;br /&gt;
&lt;br /&gt;
This will result in a removal or edit of the previously added line &amp;lt;code&amp;gt;this.addDiscOnBoard(2, 2, this.player_id);&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
for( var i in gamedatas.board )&lt;br /&gt;
{&lt;br /&gt;
    var square = gamedatas.board[i];&lt;br /&gt;
    &lt;br /&gt;
    if( square.player !== null )&lt;br /&gt;
    {&lt;br /&gt;
        this.addDiscOnBoard( square.x, square.y, square.player );&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;board&amp;lt;/code&amp;gt; entry created in &amp;lt;code&amp;gt;getAllDatas()&amp;lt;/code&amp;gt; is used here as &amp;lt;code&amp;gt;gamedatas.board&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Test the Game Start ===&lt;br /&gt;
Reload... and here we are:&lt;br /&gt;
&lt;br /&gt;
[[File:reversi5.jpg]]&lt;br /&gt;
&lt;br /&gt;
It starts to feel like Reversi here...&lt;br /&gt;
&lt;br /&gt;
== The game state machine ==&lt;br /&gt;
&lt;br /&gt;
Stop your game, again. You&#039;re about to start the core game logic.&lt;br /&gt;
&lt;br /&gt;
You already read [http://www.slideshare.net/boardgamearena/bga-studio-focus-on-bga-game-state-machine Focus on BGA game state machine], so you know that this is the heart of your game logic. For reversi, it&#039;s relatively simple. Here&#039;s a diagram of our game state machine:&lt;br /&gt;
&lt;br /&gt;
[[File:reversi6.jpg]]&lt;br /&gt;
&lt;br /&gt;
=== Build your States ===&lt;br /&gt;
And here&#039;s our &amp;lt;code&amp;gt;states.inc.php&amp;lt;/code&amp;gt;, according to this diagram:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$machinestates = array(&lt;br /&gt;
&lt;br /&gt;
    ST_BGA_GAME_SETUP =&amp;gt; array(&lt;br /&gt;
        &amp;quot;name&amp;quot; =&amp;gt; &amp;quot;gameSetup&amp;quot;,&lt;br /&gt;
        &amp;quot;description&amp;quot; =&amp;gt; clienttranslate(&amp;quot;Game setup&amp;quot;),&lt;br /&gt;
        &amp;quot;type&amp;quot; =&amp;gt; &amp;quot;manager&amp;quot;,&lt;br /&gt;
        &amp;quot;action&amp;quot; =&amp;gt; &amp;quot;stGameSetup&amp;quot;,&lt;br /&gt;
        &amp;quot;transitions&amp;quot; =&amp;gt; array( &amp;quot;&amp;quot; =&amp;gt; ST_PLAYER_PLAY_DISC )&lt;br /&gt;
    ),&lt;br /&gt;
    &lt;br /&gt;
    ST_PLAYER_PLAY_DISC =&amp;gt; array(&lt;br /&gt;
        &amp;quot;name&amp;quot; =&amp;gt; &amp;quot;playerTurn&amp;quot;,&lt;br /&gt;
		&amp;quot;description&amp;quot; =&amp;gt; clienttranslate(&#039;${actplayer} must play a disc&#039;),&lt;br /&gt;
		&amp;quot;descriptionmyturn&amp;quot; =&amp;gt; clienttranslate(&#039;${you} must play a disc&#039;),&lt;br /&gt;
        &amp;quot;type&amp;quot; =&amp;gt; &amp;quot;activeplayer&amp;quot;,&lt;br /&gt;
        &amp;quot;args&amp;quot; =&amp;gt; &amp;quot;argPlayerTurn&amp;quot;,&lt;br /&gt;
        &amp;quot;possibleactions&amp;quot; =&amp;gt; array( &#039;actPlayDisc&#039; ),&lt;br /&gt;
        &amp;quot;transitions&amp;quot; =&amp;gt; array( &amp;quot;playDisc&amp;quot; =&amp;gt; ST_NEXT_PLAYER, &amp;quot;zombiePass&amp;quot; =&amp;gt; ST_NEXT_PLAYER )&lt;br /&gt;
    ),&lt;br /&gt;
    &lt;br /&gt;
    ST_NEXT_PLAYER =&amp;gt; array(&lt;br /&gt;
        &amp;quot;name&amp;quot; =&amp;gt; &amp;quot;nextPlayer&amp;quot;,&lt;br /&gt;
        &amp;quot;type&amp;quot; =&amp;gt; &amp;quot;game&amp;quot;,&lt;br /&gt;
        &amp;quot;action&amp;quot; =&amp;gt; &amp;quot;stNextPlayer&amp;quot;,&lt;br /&gt;
        &amp;quot;updateGameProgression&amp;quot; =&amp;gt; true,        &lt;br /&gt;
        &amp;quot;transitions&amp;quot; =&amp;gt; array( &amp;quot;nextTurn&amp;quot; =&amp;gt; ST_PLAYER_PLAY_DISC, &amp;quot;cantPlay&amp;quot; =&amp;gt; ST_NEXT_PLAYER, &amp;quot;endGame&amp;quot; =&amp;gt; ST_END_GAME )&lt;br /&gt;
    ),&lt;br /&gt;
   &lt;br /&gt;
    ST_END_GAME =&amp;gt; array(&lt;br /&gt;
        &amp;quot;name&amp;quot; =&amp;gt; &amp;quot;gameEnd&amp;quot;,&lt;br /&gt;
        &amp;quot;description&amp;quot; =&amp;gt; clienttranslate(&amp;quot;End of game&amp;quot;),&lt;br /&gt;
        &amp;quot;type&amp;quot; =&amp;gt; &amp;quot;manager&amp;quot;,&lt;br /&gt;
        &amp;quot;action&amp;quot; =&amp;gt; &amp;quot;stGameEnd&amp;quot;,&lt;br /&gt;
        &amp;quot;args&amp;quot; =&amp;gt; &amp;quot;argGameEnd&amp;quot;&lt;br /&gt;
    )&lt;br /&gt;
&lt;br /&gt;
);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We used constants to give an index to the different states. This is to avoid mistakes when we reuse these indexes on the transitions array.&lt;br /&gt;
&lt;br /&gt;
Let&#039;s create a file you&#039;ll put in modules/php/constants.inc.php :&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;?php&lt;br /&gt;
&lt;br /&gt;
/*&lt;br /&gt;
 * State constants&lt;br /&gt;
 */&lt;br /&gt;
const ST_BGA_GAME_SETUP = 1;&lt;br /&gt;
&lt;br /&gt;
const ST_PLAYER_PLAY_DISC = 10;&lt;br /&gt;
const ST_NEXT_PLAYER = 11;&lt;br /&gt;
&lt;br /&gt;
const ST_END_GAME = 99;&lt;br /&gt;
&lt;br /&gt;
?&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You will also need to add &amp;lt;code&amp;gt;require_once(&amp;quot;modules/php/constants.inc.php&amp;quot;);&amp;lt;/code&amp;gt; at the beginning of the state.inc.php to load these constants.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Now, in &amp;lt;code&amp;gt;reversi.game.php&amp;lt;/code&amp;gt; let&#039;s create the methods that are declared in this game states description file:&lt;br /&gt;
* &amp;lt;code&amp;gt;argPlayerTurn&amp;lt;/code&amp;gt;: referenced in the &amp;lt;code&amp;gt;args&amp;lt;/code&amp;gt; property of the &amp;lt;code&amp;gt;playerTurn&amp;lt;/code&amp;gt; state; this is the name of the method to call to retrieve arguments for this gamestate. Arguments are sent to the client side to be used on &amp;lt;code&amp;gt;onEnteringState&amp;lt;/code&amp;gt; or to set arguments in the gamestate description.&lt;br /&gt;
* &amp;lt;code&amp;gt;stNextPlayer&amp;lt;/code&amp;gt;: referenced in the &amp;lt;code&amp;gt;action&amp;lt;/code&amp;gt; property of the &amp;lt;code&amp;gt;nextPlayer&amp;lt;/code&amp;gt; state; this is the name of the method to call when this game state become the current game state.&lt;br /&gt;
&lt;br /&gt;
=== Test Your States ===&lt;br /&gt;
... and start a new Reversi game.&lt;br /&gt;
&lt;br /&gt;
As you can see on the screen capture below, the BGA framework makes the game jump to our first game state &amp;lt;code&amp;gt;playerTurn&amp;lt;/code&amp;gt; right after the initial setup. That&#039;s why the status bar contains the description of &amp;lt;code&amp;gt;playerTurn&amp;lt;/code&amp;gt; state (&amp;quot;XXXX must play a disc&amp;quot;):&lt;br /&gt;
&lt;br /&gt;
[[File:reversi7.jpg]]&lt;br /&gt;
&lt;br /&gt;
== The rules ==&lt;br /&gt;
&lt;br /&gt;
We will use the &amp;lt;code&amp;gt;getPossibleMoves&amp;lt;/code&amp;gt; PHP method to:&lt;br /&gt;
* Indicate to the current player where she is allowed to play by returning a list of coordinates&lt;br /&gt;
* Check if the player has the right to play in the spot they choose&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;&lt;br /&gt;
Example of getPossibleMoves here https://gist.github.com/leocaseiro/a8bc2851bd0caddd06685b5035937d15&lt;br /&gt;
&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This is pure PHP programming here, and there are no special things from the BGA framework that can be used. This is why we won&#039;t go into details here. The overall idea is:&lt;br /&gt;
* Create a &amp;lt;code&amp;gt;getTurnedOverDiscs(x,y)&amp;lt;/code&amp;gt; method that returns coordinates of discs that would be turned over if a token would be played at &amp;lt;code&amp;gt;x&amp;lt;/code&amp;gt;,&amp;lt;code&amp;gt;y&amp;lt;/code&amp;gt;.&lt;br /&gt;
* Loop through all free squares of the board and call the &amp;lt;code&amp;gt;getTurnedOverDiscs&amp;lt;/code&amp;gt; method on each of them. If at least 1 token is turned over, this is a valid move.&lt;br /&gt;
&lt;br /&gt;
IMPORTANT: Making a database query is slow! Please don&#039;t load the entire game board with a SQL query multiple times. In our implementation, we load the entire board once at the beginning of &amp;lt;code&amp;gt;getPossibleMoves&amp;lt;/code&amp;gt;, and then pass the board as an argument to all methods.&lt;br /&gt;
&lt;br /&gt;
If you want to look into details, please look at the &amp;quot;utility method&amp;quot; sections of &amp;lt;code&amp;gt;reversi.game.php&amp;lt;/code&amp;gt;. If building the tutorial yourself, copy the functions under &amp;quot;Utility functions&amp;quot; comment from the Reversi tutorial.&lt;br /&gt;
&lt;br /&gt;
== Display allowed moves ==&lt;br /&gt;
&lt;br /&gt;
Now we want to highlight the squares where the player can place a disc.&lt;br /&gt;
&lt;br /&gt;
To do this, we add a &amp;lt;code&amp;gt;argPlayerTurn&amp;lt;/code&amp;gt; method in &amp;lt;code&amp;gt;reversi.game.php&amp;lt;/code&amp;gt;. This method is called on the server each time we enter into &amp;lt;code&amp;gt;playerTurn&amp;lt;/code&amp;gt; game state, and its result is transferred automatically to the client-side:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
function argPlayerTurn(): array&lt;br /&gt;
{&lt;br /&gt;
    return [&lt;br /&gt;
        &#039;possibleMoves&#039; =&amp;gt; $this-&amp;gt;getPossibleMoves( intval($this-&amp;gt;getActivePlayerId()) )&lt;br /&gt;
    ];&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We use the &amp;lt;code&amp;gt;getPossibleMoves&amp;lt;/code&amp;gt; method we just developed.&lt;br /&gt;
&lt;br /&gt;
Each time we enter into a new game state, we use the &amp;lt;code&amp;gt;onEnteringState&amp;lt;/code&amp;gt; Javascript method (in the &amp;lt;code&amp;gt;reversi.js&amp;lt;/code&amp;gt; file, under &amp;quot;Game &amp;amp; client states&amp;quot;). This lets us use the data returned by the method above on the client side.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        onEnteringState: function( stateName, args )&lt;br /&gt;
        {&lt;br /&gt;
           console.log( &#039;Entering state: &#039;+stateName );&lt;br /&gt;
            &lt;br /&gt;
            switch( stateName )&lt;br /&gt;
            {&lt;br /&gt;
            case &#039;playerTurn&#039;:&lt;br /&gt;
                this.updatePossibleMoves( args.args.possibleMoves );&lt;br /&gt;
                break;&lt;br /&gt;
            }&lt;br /&gt;
        },&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
So, when we enter into &amp;lt;code&amp;gt;playerTurn&amp;lt;/code&amp;gt; game state, we call our &amp;lt;code&amp;gt;updatePossibleMoves&amp;lt;/code&amp;gt; method (under the &amp;quot;Utility methods&amp;quot; section). This method looks like this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
updatePossibleMoves: function( possibleMoves )&lt;br /&gt;
{&lt;br /&gt;
    // Remove current possible moves&lt;br /&gt;
    document.querySelectorAll(&#039;.possibleMove&#039;).forEach(div =&amp;gt; div.classList.remove(&#039;possibleMove&#039;));&lt;br /&gt;
&lt;br /&gt;
    for( var x in possibleMoves )&lt;br /&gt;
    {&lt;br /&gt;
        for( var y in possibleMoves[ x ] )&lt;br /&gt;
        {&lt;br /&gt;
            // x,y is a possible move&lt;br /&gt;
            document.getElementById(`square_${x}_${y}`).classList.add(&#039;possibleMove&#039;);&lt;br /&gt;
        }            &lt;br /&gt;
    }&lt;br /&gt;
                &lt;br /&gt;
    this.addTooltipToClass( &#039;possibleMove&#039;, &#039;&#039;, _(&#039;Place a disc here&#039;) );&lt;br /&gt;
},&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Here&#039;s what this does. At first, it removes all &amp;lt;code&amp;gt;possibleMove&amp;lt;/code&amp;gt; classes currently applied with the very useful &amp;lt;code&amp;gt;document.querySelectorAll&amp;lt;/code&amp;gt; method.&lt;br /&gt;
&lt;br /&gt;
Then it loops through all possible moves our PHP &amp;lt;code&amp;gt;updatePossibleMoves&amp;lt;/code&amp;gt; function created for us, and adds the &amp;lt;code&amp;gt;possibleMove&amp;lt;/code&amp;gt; class to each corresponding square.&lt;br /&gt;
&lt;br /&gt;
Finally, it uses the BGA framework &amp;lt;code&amp;gt;addTooltipToClass&amp;lt;/code&amp;gt; method to associate a tooltip to all those highlighted squares so that players can understand their meaning.&lt;br /&gt;
&lt;br /&gt;
To see the possible moves we need to create a CSS class (&amp;lt;code&amp;gt;possibleMove&amp;lt;/code&amp;gt;) that can be applied to a &amp;lt;code&amp;gt;square&amp;lt;/code&amp;gt; element to highlight it:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
.possibleMove {&lt;br /&gt;
    background-color: white;&lt;br /&gt;
    opacity: 0.2; &lt;br /&gt;
    cursor: pointer;  &lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
And here we are:&lt;br /&gt;
&lt;br /&gt;
[[File:reversi8.jpg.jpg]]&lt;br /&gt;
&lt;br /&gt;
== Let&#039;s play ==&lt;br /&gt;
&lt;br /&gt;
From now, it&#039;s better to restart a game with 2 players, because we are going to implement a complete Reversi turn. The summary of what we are going to do is:&lt;br /&gt;
* When we click on a &amp;lt;code&amp;gt;possibleMove&amp;lt;/code&amp;gt; square, send the move to the server.&lt;br /&gt;
* Server side, check the move is correct, apply Reversi rules and jump to next player.&lt;br /&gt;
* Client side, change the token position to reflect the move.&lt;br /&gt;
&lt;br /&gt;
First we associate each click on a square to one of our methods using our Javascript &amp;lt;code&amp;gt;setup&amp;lt;/code&amp;gt; method:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
document.querySelectorAll(&#039;.square&#039;).forEach(square =&amp;gt; square.addEventListener(&#039;click&#039;, e =&amp;gt; this.onPlayDisc(e)));&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note the use of the &amp;quot;dojo.query&amp;quot; method to get all HTML elements with &amp;quot;square&amp;quot; class in just one function call. Now, our &amp;quot;onPlayDisc&amp;quot; method is called each time someone clicks on a square.&lt;br /&gt;
&lt;br /&gt;
Here&#039;s our &amp;quot;onPlayDisc&amp;quot; method below:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
onPlayDisc: function( evt )&lt;br /&gt;
{&lt;br /&gt;
    // Stop this event propagation&lt;br /&gt;
    evt.preventDefault();&lt;br /&gt;
    evt.stopPropagation();&lt;br /&gt;
&lt;br /&gt;
    // Get the cliqued square x and y&lt;br /&gt;
    // Note: square id format is &amp;quot;square_X_Y&amp;quot;&lt;br /&gt;
    var coords = evt.currentTarget.id.split(&#039;_&#039;);&lt;br /&gt;
    var x = coords[1];&lt;br /&gt;
    var y = coords[2];&lt;br /&gt;
&lt;br /&gt;
    if(!document.getElementById(`square_${x}_${y}`).classList.contains(&#039;possibleMove&#039;)) {&lt;br /&gt;
        // This is not a possible move =&amp;gt; the click does nothing&lt;br /&gt;
        return ;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    this.bgaPerformAction(&amp;quot;actPlayDisc&amp;quot;, {&lt;br /&gt;
        x:x,&lt;br /&gt;
        y:y&lt;br /&gt;
    });&lt;br /&gt;
},&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
What we do here is:&lt;br /&gt;
* We stop the propagation of the Javascript &amp;lt;code&amp;gt;onclick&amp;lt;/code&amp;gt; event. Otherwise, it can lead to random behavior so it&#039;s always a good idea.&lt;br /&gt;
* We get the x/y coordinates of the square by using &amp;lt;code&amp;gt;evt.currentTarget.id&amp;lt;/code&amp;gt;&lt;br /&gt;
* We check that clicked square has the &amp;lt;code&amp;gt;possibleMove&amp;lt;/code&amp;gt; class, otherwise we know for sure that we can&#039;t play there.&lt;br /&gt;
* Finally, we make a call to the server using BGA &amp;lt;code&amp;gt;bgaPerformAction&amp;lt;/code&amp;gt; method with argument x and y. This call will check that &amp;lt;code&amp;gt;actPlayDisc&amp;lt;/code&amp;gt; action is possible, according to current game state (see &amp;lt;code&amp;gt;possibleactions&amp;lt;/code&amp;gt; entry in our &amp;lt;code&amp;gt;playerTurn&amp;lt;/code&amp;gt; game state defined above). This check is important to avoid issues if a player double clicks on a square.&lt;br /&gt;
&lt;br /&gt;
Now, we have to manage this &amp;lt;code&amp;gt;actPlayDisc&amp;lt;/code&amp;gt; action on the server side. At first, we introduce a &amp;lt;code&amp;gt;actPlayDisc&amp;lt;/code&amp;gt; entry point in our &amp;lt;code&amp;gt;reversi.action.php&amp;lt;/code&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
public function actPlayDisc()&lt;br /&gt;
{&lt;br /&gt;
    $this-&amp;gt;setAjaxMode();&lt;br /&gt;
    $x = (int)$this-&amp;gt;getArg( &amp;quot;x&amp;quot;, AT_posint, true );&lt;br /&gt;
    $y = (int)$this-&amp;gt;getArg( &amp;quot;y&amp;quot;, AT_posint, true );&lt;br /&gt;
    $result = $this-&amp;gt;game-&amp;gt;actPlayDisc( $x, $y );&lt;br /&gt;
    $this-&amp;gt;ajaxResponse( );&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
As you can see, we get the 2 arguments x and y from the javascript call, and call a corresponding &amp;lt;code&amp;gt;actPlayDisc&amp;lt;/code&amp;gt; method in our game logic (&amp;lt;code&amp;gt;reversi.game.php&amp;lt;/code&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
Now, let&#039;s have a look of this &amp;lt;code&amp;gt;actPlayDisc&amp;lt;/code&amp;gt; method:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
function actPlayDisc( int $x, int $y )&lt;br /&gt;
{&lt;br /&gt;
    // Check that this player is active and that this action is possible at this moment&lt;br /&gt;
    $this-&amp;gt;checkAction( &#039;actPlayDisc&#039; );  &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
... at first, we check that this action is possible according to current game state (see &amp;quot;possible action&amp;quot;). We already did it on client side, but it&#039;s important to do it on server side too (otherwise it would be possible to cheat).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        $player_id = intval($this-&amp;gt;getActivePlayerId()); &lt;br /&gt;
        &lt;br /&gt;
        // Now, check if this is a possible move&lt;br /&gt;
        $board = $this-&amp;gt;getBoard();&lt;br /&gt;
        $turnedOverDiscs = $this-&amp;gt;getTurnedOverDiscs( $x, $y, $player_id, $board );&lt;br /&gt;
        &lt;br /&gt;
        if( count( $turnedOverDiscs ) &amp;gt; 0 )&lt;br /&gt;
        {&lt;br /&gt;
            // This move is possible!&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
...now, we are using the &amp;lt;code&amp;gt;getTurnedOverDiscs&amp;lt;/code&amp;gt; method again to check that this move is possible.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
            // Let&#039;s place a disc at x,y and return all &amp;quot;$returned&amp;quot; discs to the active player&lt;br /&gt;
            &lt;br /&gt;
            $sql = &amp;quot;UPDATE board SET board_player=&#039;$player_id&#039;&lt;br /&gt;
                    WHERE ( board_x, board_y) IN ( &amp;quot;;&lt;br /&gt;
            &lt;br /&gt;
            foreach( $turnedOverDiscs as $turnedOver )&lt;br /&gt;
            {&lt;br /&gt;
                $sql .= &amp;quot;(&#039;&amp;quot;.$turnedOver[&#039;x&#039;].&amp;quot;&#039;,&#039;&amp;quot;.$turnedOver[&#039;y&#039;].&amp;quot;&#039;),&amp;quot;;&lt;br /&gt;
            }&lt;br /&gt;
            $sql .= &amp;quot;(&#039;$x&#039;,&#039;$y&#039;) ) &amp;quot;;&lt;br /&gt;
                       &lt;br /&gt;
            $this-&amp;gt;DbQuery( $sql );&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
... we update the database to change the color of all turned over disc + the disc we just placed.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
            // Update scores according to the number of disc on board&lt;br /&gt;
            $sql = &amp;quot;UPDATE player&lt;br /&gt;
                    SET player_score = (&lt;br /&gt;
                    SELECT COUNT( board_x ) FROM board WHERE board_player=player_id&lt;br /&gt;
                    )&amp;quot;;&lt;br /&gt;
            $this-&amp;gt;DbQuery( $sql );&lt;br /&gt;
            &lt;br /&gt;
            // Statistics&lt;br /&gt;
            $this-&amp;gt;incStat( count( $turnedOverDiscs ), &amp;quot;turnedOver&amp;quot;, $player_id );&lt;br /&gt;
            if( ($x==1 &amp;amp;&amp;amp; $y==1) || ($x==8 &amp;amp;&amp;amp; $y==1) || ($x==1 &amp;amp;&amp;amp; $y==8) || ($x==8 &amp;amp;&amp;amp; $y==8) )&lt;br /&gt;
                $this-&amp;gt;incStat( 1, &#039;discPlayedOnCorner&#039;, $player_id );&lt;br /&gt;
            else if( $x==1 || $x==8 || $y==1 || $y==8 )&lt;br /&gt;
                $this-&amp;gt;incStat( 1, &#039;discPlayedOnBorder&#039;, $player_id );&lt;br /&gt;
            else if( $x&amp;gt;=3 &amp;amp;&amp;amp; $x&amp;lt;=6 &amp;amp;&amp;amp; $y&amp;gt;=3 &amp;amp;&amp;amp; $y&amp;lt;=6 )&lt;br /&gt;
                $this-&amp;gt;incStat( 1, &#039;discPlayedOnCenter&#039;, $player_id );&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
... now, we update both player score by counting all disc, and we manage game statistics.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
            // Notify&lt;br /&gt;
            $this-&amp;gt;notifyAllPlayers( &amp;quot;playDisc&amp;quot;, clienttranslate( &#039;${player_name} plays a disc and turns over ${returned_nbr} disc(s)&#039; ), array(&lt;br /&gt;
                &#039;player_id&#039; =&amp;gt; $player_id,&lt;br /&gt;
                &#039;player_name&#039; =&amp;gt; $this-&amp;gt;getActivePlayerName(),&lt;br /&gt;
                &#039;returned_nbr&#039; =&amp;gt; count( $turnedOverDiscs ),&lt;br /&gt;
                &#039;x&#039; =&amp;gt; $x,&lt;br /&gt;
                &#039;y&#039; =&amp;gt; $y&lt;br /&gt;
            ) );&lt;br /&gt;
&lt;br /&gt;
            $this-&amp;gt;notifyAllPlayers( &amp;quot;turnOverDiscs&amp;quot;, &#039;&#039;, array(&lt;br /&gt;
                &#039;player_id&#039; =&amp;gt; $player_id,&lt;br /&gt;
                &#039;turnedOver&#039; =&amp;gt; $turnedOverDiscs&lt;br /&gt;
            ) );&lt;br /&gt;
            &lt;br /&gt;
            $newScores = $this-&amp;gt;getCollectionFromDb( &amp;quot;SELECT player_id, player_score FROM player&amp;quot;, true );&lt;br /&gt;
            $this-&amp;gt;notifyAllPlayers( &amp;quot;newScores&amp;quot;, &amp;quot;&amp;quot;, array(&lt;br /&gt;
                &amp;quot;scores&amp;quot; =&amp;gt; $newScores&lt;br /&gt;
            ) );&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
... then we notify about all these changes. We are using for that 3 notifications (&amp;lt;code&amp;gt;playDisc&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;turnOverDiscs&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;newScores&amp;lt;/code&amp;gt; that we are going to implement on client side later). Note that the description of the &amp;lt;code&amp;gt;playDisc&amp;lt;/code&amp;gt; notification will be logged in the game log.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
            // Then, go to the next state&lt;br /&gt;
            $this-&amp;gt;gamestate-&amp;gt;nextState( &#039;playDisc&#039; );&lt;br /&gt;
        }&lt;br /&gt;
        else&lt;br /&gt;
            throw new BgaSystemException( &amp;quot;Impossible move&amp;quot; );&lt;br /&gt;
    }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
... finally, we jump to the next game state if everything goes fine (&amp;lt;code&amp;gt;playDisc&amp;lt;/code&amp;gt; is the name of a transition in the &amp;lt;code&amp;gt;playerTurn&amp;lt;/code&amp;gt; game state description above which leads to state 11 which is &amp;lt;code&amp;gt;nextPlayer&amp;lt;/code&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
To make the statistics work, we have to initialize them in &amp;lt;code&amp;gt;stats.json&amp;lt;/code&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
  &amp;quot;player&amp;quot;: {&lt;br /&gt;
    &amp;quot;discPlayedOnCorner&amp;quot;: {&lt;br /&gt;
      &amp;quot;id&amp;quot;: 10,&lt;br /&gt;
      &amp;quot;name&amp;quot;: &amp;quot;Discs played on a corner&amp;quot;,&lt;br /&gt;
      &amp;quot;type&amp;quot;: &amp;quot;int&amp;quot;&lt;br /&gt;
    },&lt;br /&gt;
    &amp;quot;discPlayedOnBorder&amp;quot;: {&lt;br /&gt;
      &amp;quot;id&amp;quot;: 11,&lt;br /&gt;
      &amp;quot;name&amp;quot;: &amp;quot;Discs played on a border&amp;quot;,&lt;br /&gt;
      &amp;quot;type&amp;quot;: &amp;quot;int&amp;quot;&lt;br /&gt;
    },&lt;br /&gt;
    &amp;quot;discPlayedOnCenter&amp;quot;: {&lt;br /&gt;
      &amp;quot;id&amp;quot;: 12,&lt;br /&gt;
      &amp;quot;name&amp;quot;: &amp;quot;Discs played on board center part&amp;quot;,&lt;br /&gt;
      &amp;quot;type&amp;quot;: &amp;quot;int&amp;quot;&lt;br /&gt;
    },&lt;br /&gt;
    &amp;quot;turnedOver&amp;quot;: {&lt;br /&gt;
      &amp;quot;id&amp;quot;: 13,&lt;br /&gt;
      &amp;quot;name&amp;quot;: &amp;quot;Number of discs turned over&amp;quot;,&lt;br /&gt;
      &amp;quot;type&amp;quot;: &amp;quot;int&amp;quot;&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
A last thing to do on the server side is to activate the next player when we enter the &amp;lt;code&amp;gt;nextPlayer&amp;lt;/code&amp;gt; game state (in the &amp;lt;code&amp;gt;reversi.game.php&amp;lt;/code&amp;gt; file, under &amp;quot;Game state reactions&amp;quot;):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    function stNextPlayer(): void&lt;br /&gt;
    {&lt;br /&gt;
        // Active next player&lt;br /&gt;
        $player_id = intval($this-&amp;gt;activeNextPlayer());&lt;br /&gt;
&lt;br /&gt;
        // Check if both player has at least 1 discs, and if there are free squares to play&lt;br /&gt;
        $player_to_discs = $this-&amp;gt;getCollectionFromDb( &amp;quot;SELECT board_player, COUNT( board_x )&lt;br /&gt;
                                                       FROM board&lt;br /&gt;
                                                       GROUP BY board_player&amp;quot;, true );&lt;br /&gt;
&lt;br /&gt;
        if( ! isset( $player_to_discs[ null ] ) )&lt;br /&gt;
        {&lt;br /&gt;
            // Index 0 has not been set =&amp;gt; there&#039;s no more free place on the board !&lt;br /&gt;
            // =&amp;gt; end of the game&lt;br /&gt;
            $this-&amp;gt;gamestate-&amp;gt;nextState( &#039;endGame&#039; );&lt;br /&gt;
            return ;&lt;br /&gt;
        }&lt;br /&gt;
        else if( ! isset( $player_to_discs[ $player_id ] ) )&lt;br /&gt;
        {&lt;br /&gt;
            // Active player has no more disc on the board =&amp;gt; he looses immediately&lt;br /&gt;
            $this-&amp;gt;gamestate-&amp;gt;nextState( &#039;endGame&#039; );&lt;br /&gt;
            return ;&lt;br /&gt;
        }&lt;br /&gt;
        &lt;br /&gt;
        // Can this player play?&lt;br /&gt;
&lt;br /&gt;
        $possibleMoves = $this-&amp;gt;getPossibleMoves( $player_id );&lt;br /&gt;
        if( count( $possibleMoves ) == 0 )&lt;br /&gt;
        {&lt;br /&gt;
&lt;br /&gt;
            // This player can&#039;t play&lt;br /&gt;
            // Can his opponent play ?&lt;br /&gt;
            $opponent_id = (int)$this-&amp;gt;getUniqueValueFromDb( &amp;quot;SELECT player_id FROM player WHERE player_id!=&#039;$player_id&#039; &amp;quot; );&lt;br /&gt;
            if( count( $this-&amp;gt;getPossibleMoves( $opponent_id ) ) == 0 )&lt;br /&gt;
            {&lt;br /&gt;
                // Nobody can move =&amp;gt; end of the game&lt;br /&gt;
                $this-&amp;gt;gamestate-&amp;gt;nextState( &#039;endGame&#039; );&lt;br /&gt;
            }&lt;br /&gt;
            else&lt;br /&gt;
            {            &lt;br /&gt;
                // =&amp;gt; pass his turn&lt;br /&gt;
                $this-&amp;gt;gamestate-&amp;gt;nextState( &#039;cantPlay&#039; );&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
        else&lt;br /&gt;
        {&lt;br /&gt;
            // This player can play. Give him some extra time&lt;br /&gt;
            $this-&amp;gt;giveExtraTime( $player_id );&lt;br /&gt;
            $this-&amp;gt;gamestate-&amp;gt;nextState( &#039;nextTurn&#039; );&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Now, when we play a token, the rules are checked and the token appears in the database.&lt;br /&gt;
&lt;br /&gt;
[[File:reversi9.jpg]]&lt;br /&gt;
&lt;br /&gt;
Of course, as we don&#039;t manage notifications on client side, we need to press F5 after each move to see the changes on the board.&lt;br /&gt;
&lt;br /&gt;
== Make the move appear automatically ==&lt;br /&gt;
&lt;br /&gt;
Now, what we have to do is process the notifications sent by the server and make the move appear on the interface.&lt;br /&gt;
&lt;br /&gt;
In our &amp;lt;code&amp;gt;setupNotifications&amp;lt;/code&amp;gt; method in &amp;lt;code&amp;gt;reversi.js&amp;lt;/code&amp;gt;, we register 2 methods for the 2 notifications we created at the previous step (&amp;lt;code&amp;gt;playDisc&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;turnOverDiscs&amp;lt;/code&amp;gt;):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
            const notifs = [&lt;br /&gt;
                [&#039;playDisc&#039;, 500],&lt;br /&gt;
                [&#039;turnOverDiscs&#039;, 1500],&lt;br /&gt;
                [&#039;newScores&#039;, 1],&lt;br /&gt;
            ];&lt;br /&gt;
    &lt;br /&gt;
            notifs.forEach((notif) =&amp;gt; {&lt;br /&gt;
                dojo.subscribe(notif[0], this, `notif_${notif[0]}`);&lt;br /&gt;
                this.notifqueue.setSynchronous(notif[0], notif[1]);&lt;br /&gt;
            });&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We will associate each of our 3 notifications with a method prefixed with &amp;lt;code&amp;gt;notif_&amp;lt;/code&amp;gt;. We also define these notifications as &amp;quot;synchronous&amp;quot;, with a duration in millisecond. It tells the user interface to wait some time after executing the notification, to let the animation end before starting the next notification. In our specific case, the animation will be the following:&lt;br /&gt;
* Make a disc slide from the player panel to its place on the board&lt;br /&gt;
* (wait 500ms)&lt;br /&gt;
* Make all turned over discs blink (and of course turned them over)&lt;br /&gt;
* (wait 1500ms)&lt;br /&gt;
* Update the player scores&lt;br /&gt;
* (no real delay on this one)&lt;br /&gt;
&lt;br /&gt;
The second part of the code is a generic thing to automatically bind the notifs we configured to the &amp;lt;code&amp;gt;notif_&amp;lt;notifName&amp;gt;&amp;lt;/code&amp;gt; functions we are about to create.&lt;br /&gt;
&lt;br /&gt;
Let&#039;s have a look now on the &amp;lt;code&amp;gt;playDisc&amp;lt;/code&amp;gt; notification handler method:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
notif_playDisc: function( notif )&lt;br /&gt;
{&lt;br /&gt;
    // Remove current possible moves (makes the board more clear)&lt;br /&gt;
    document.querySelectorAll(&#039;.possibleMove&#039;).forEach(div =&amp;gt; div.classList.remove(&#039;possibleMove&#039;));&lt;br /&gt;
&lt;br /&gt;
    this.addDiscOnBoard( notif.args.x, notif.args.y, notif.args.player_id );&lt;br /&gt;
},&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
No surprise here, we re-used some existing stuff to:&lt;br /&gt;
* Remove the highlighted squares.&lt;br /&gt;
* Add a new disc on board, coming from player panel.&lt;br /&gt;
&lt;br /&gt;
Now, here&#039;s the method that handles the &amp;lt;code&amp;gt;turnOverDiscs&amp;lt;/code&amp;gt; notification:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
notif_turnOverDiscs: function( notif )&lt;br /&gt;
{&lt;br /&gt;
    // Get the color of the player who is returning the discs&lt;br /&gt;
    var targetColor = this.gamedatas.players[ notif.args.player_id ].color;&lt;br /&gt;
&lt;br /&gt;
    // Made these discs blinking and set them to the specified color&lt;br /&gt;
    for( var i in notif.args.turnedOver )&lt;br /&gt;
    {&lt;br /&gt;
        var disc = notif.args.turnedOver[ i ];&lt;br /&gt;
        &lt;br /&gt;
        // Make the disc blink 2 times&lt;br /&gt;
        var anim = dojo.fx.chain( [&lt;br /&gt;
            dojo.fadeOut( { node: &#039;disc_&#039;+disc.x+&#039;&#039;+disc.y } ),&lt;br /&gt;
            dojo.fadeIn( { node: &#039;disc_&#039;+disc.x+&#039;&#039;+disc.y } ),&lt;br /&gt;
            dojo.fadeOut( { &lt;br /&gt;
                            node: &#039;disc_&#039;+disc.x+&#039;&#039;+disc.y,&lt;br /&gt;
                            onEnd: node =&amp;gt; $(node).dataset.color = targetColor,&lt;br /&gt;
                            } ),&lt;br /&gt;
            dojo.fadeIn( { node: &#039;disc_&#039;+disc.x+&#039;&#039;+disc.y  } )&lt;br /&gt;
                            &lt;br /&gt;
        ] ); // end of dojo.fx.chain&lt;br /&gt;
&lt;br /&gt;
        // ... and launch the animation&lt;br /&gt;
        anim.play();                &lt;br /&gt;
    }&lt;br /&gt;
},&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The list of the discs to be turned over has been made available by our server side code in &amp;lt;code&amp;gt;notif.args.turnedOver&amp;lt;/code&amp;gt; (see previous paragraph). We loop through all these discs, and create a complex animation using &amp;lt;code&amp;gt;dojo.Animation&amp;lt;/code&amp;gt; for each of them. The complete documentation on dojo animations [http://dojotoolkit.org/documentation/tutorials/1.6/animation/ can be found here].&lt;br /&gt;
&lt;br /&gt;
In few words: we create a chain of 4 animations to make the disc fade out, fade in, fade out again, and fade in again. At the end of the second fade out, we change the color of the disc. Finally, we launch the animation with &amp;lt;code&amp;gt;play()&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
And Also the notification to update the scores:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
notif_newScores: function( notif )&lt;br /&gt;
        {&lt;br /&gt;
            for( var player_id in notif.args.scores )&lt;br /&gt;
            {&lt;br /&gt;
                var newScore = notif.args.scores[ player_id ];&lt;br /&gt;
                this.scoreCtrl[ player_id ].toValue( newScore );&lt;br /&gt;
            }&lt;br /&gt;
        },&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Category:Studio]]&lt;/div&gt;</summary>
		<author><name>Sguzzer Gunayer</name></author>
	</entry>
	<entry>
		<id>https://en.doc.boardgamearena.com/index.php?title=Tutorial_reversi&amp;diff=22414</id>
		<title>Tutorial reversi</title>
		<link rel="alternate" type="text/html" href="https://en.doc.boardgamearena.com/index.php?title=Tutorial_reversi&amp;diff=22414"/>
		<updated>2024-09-03T14:50:21Z</updated>

		<summary type="html">&lt;p&gt;Sguzzer Gunayer: /* Utility Method Explanation */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&#039;&#039;&#039;Check out an update version&#039;&#039;&#039; of the [[BGA Type Safe Template: Reversi|Reversi Tutorial]] which uses the [[BGA Type Safe Template]]. {{Studio_Framework_Navigation}}&lt;br /&gt;
&lt;br /&gt;
== Introduction ==&lt;br /&gt;
&lt;br /&gt;
Using this tutorial, you can build a complete working game on the BGA environment: Reversi.&lt;br /&gt;
&lt;br /&gt;
Before you read this tutorial, you must:&lt;br /&gt;
* Read the overall presentations of the BGA Framework ([[Studio|see here]]).&lt;br /&gt;
* Know the [http://en.wikipedia.org/wiki/Reversi#Rules rules of Reversi].&lt;br /&gt;
* Know the languages used on BGA: PHP, SQL, HTML, CSS, Javascript&lt;br /&gt;
* &#039;&#039;&#039;Setup your development environment&#039;&#039;&#039; [http://en.doc.boardgamearena.com/First_steps_with_BGA_Studio First Steps with BGA Studio]&lt;br /&gt;
&lt;br /&gt;
== Create your first game ==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Note: you should already have created a project following instructions in [[First_steps_with_BGA_Studio#Create_a_new_game_project|Create a new game project]]. While you will find a &#039;&#039;&#039;reversi&#039;&#039;&#039; directory in your SFTP folder, do not use it for this tutorial. Instead, use the project you have created as an (empty) starting point.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
With the initial skeleton of code provided in your project, you can already start a game from the BGA Studio:&lt;br /&gt;
* Go to your [https://studio.boardgamearena.com/controlpanel studio Control panel], then Manage games and select your initial project. &#039;&#039;Note: there are warnings displayed about a missing BGG_ID and presentation text. You can ignore that for now.&#039;&#039;&lt;br /&gt;
* Click the Play link next to your project name. This will open the Play page and offer to create a new table for your project. &#039;&#039;Optional: click the Heart icon to add your project to your favorite games list.&#039;&#039;&lt;br /&gt;
* On the Play page, on the top of the page, make sure that your settings are &amp;quot;Simple game&amp;quot;, &amp;quot;Real time&amp;quot; and &amp;quot;Manual&amp;quot;.&lt;br /&gt;
* Click &amp;quot;Create table&amp;quot; to create a table of your project. &lt;br /&gt;
* For now, we are going to work with one player only, so use the (-) button to set the number of players to 1. Most of the time it is simpler to proceed with only one player during the early phase of development of your game, as it&#039;s easy and fast to start/stop games. If you choose to start with 2 players, you should see two names on the right: testdude0 and testdude1. To switch between them, press the red arrow button near their names; it will open another tab. This way you don&#039;t need to login and logout from multiple accounts.) &lt;br /&gt;
* Reminder: Always use the &amp;quot;Express Start&amp;quot; button to start the game.&lt;br /&gt;
&lt;br /&gt;
Thus, you can start a &amp;quot;Reversi&amp;quot; game, and arrive on a void, empty game. Yeah.&lt;br /&gt;
&lt;br /&gt;
End the game by clicking on the game options icon on the top right, and then on &amp;quot;Express Stop&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
== Editing the game information (Optional) ==&lt;br /&gt;
&lt;br /&gt;
This step is optional and will fix the warnings on the project page (missing BGG_ID and presentation).&lt;br /&gt;
&lt;br /&gt;
==== Edits to fix Errors ====&lt;br /&gt;
* Edit your local copy of the &amp;lt;code&amp;gt;gameinfos.inc.php&amp;lt;/code&amp;gt; file:&lt;br /&gt;
** Change the &amp;lt;code&amp;gt;bgg_id&amp;lt;/code&amp;gt; value from &amp;lt;code&amp;gt;0&amp;lt;/code&amp;gt; to &amp;lt;code&amp;gt;2389&amp;lt;/code&amp;gt; - that&#039;s around line 37.&lt;br /&gt;
** Add &amp;lt;code&amp;gt;1,&amp;lt;/code&amp;gt; to the players array - that&#039;s around line 41.&lt;br /&gt;
** Change the presentation array content - that&#039;s around line 134. Uncomment one line and change the text. Remove the final comma if you keep only one line!&lt;br /&gt;
* Upload the &amp;lt;code&amp;gt;gameinfos.inc.php&amp;lt;/code&amp;gt; file to the SFTP server (see [[First_steps_with_BGA_Studio#Connect_to_your_SFTP_folder|Connect to your SFTP folder]]).&lt;br /&gt;
&lt;br /&gt;
==== Test your Edits ====&lt;br /&gt;
* Go back to your project page, and in the &amp;quot;Game Information&amp;quot; section, click &amp;quot;Reload game informations&amp;quot;.&lt;br /&gt;
* Finally, refresh the project page in your browser (usually CTRL-F5).&lt;br /&gt;
&lt;br /&gt;
===== Not working? =====&lt;br /&gt;
Some changes will require bypassing the cache. It is often worth doing a hard refresh to make sure the&lt;br /&gt;
&lt;br /&gt;
Sometimes the cache will keep your changes from showing. Since this is a possibility, it will be useful to know how to bypass the cache. To do so you may manually clear cache or use a shortcut to refresh and ignore the cached version of the page. Here&#039;s how&lt;br /&gt;
&lt;br /&gt;
====== Windows ======&lt;br /&gt;
Chrome, Firefox, or Edge: Press &amp;lt;code&amp;gt;Ctrl+F5&amp;lt;/code&amp;gt; or &amp;lt;code&amp;gt;Shift+F5&amp;lt;/code&amp;gt; or &amp;lt;code&amp;gt;Ctrl+Shift+R&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====== Mac ======&lt;br /&gt;
Chrome or Firefox: Press &amp;lt;code&amp;gt;Shift+Command+R&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Safari for Mac: Press &amp;lt;code&amp;gt;Command+Option+E&amp;lt;/code&amp;gt; to empty the cache, then hold down Shift and click Reload in the toolbar&lt;br /&gt;
&lt;br /&gt;
== Make it look like Reversi ==&lt;br /&gt;
&lt;br /&gt;
Let&#039;s start with the board. This will give you a good idea of how things will look and where tokens should go.&lt;br /&gt;
&lt;br /&gt;
Be careful designing the layout of your game: you must always keep in mind that players with a 1024px screen width must be able to play. Usually, it means that the width of the play area can be 750px (in the worst case).&lt;br /&gt;
&lt;br /&gt;
For Reversi, it&#039;s useless to have a 750x750px board - much too big, so we chose this one which fit perfectly (536x528):&lt;br /&gt;
&lt;br /&gt;
[[File:Board.jpg]]&lt;br /&gt;
&lt;br /&gt;
Note that we are using a jpg file. Jpg files are lighter than png, so they are faster to load. Later, we are going to use PNGs for tokens because they allow for transparency.&lt;br /&gt;
&lt;br /&gt;
==== Add the board ====&lt;br /&gt;
use lowercase file names&lt;br /&gt;
* upload &amp;lt;code&amp;gt;board.jpg&amp;lt;/code&amp;gt; in your &amp;lt;code&amp;gt;img/&amp;lt;/code&amp;gt; directory. &lt;br /&gt;
* edit &amp;lt;code&amp;gt;reversi_reversi.tpl&amp;lt;/code&amp;gt; to add a &amp;lt;code&amp;gt;div&amp;lt;/code&amp;gt; for your board.&lt;br /&gt;
&lt;br /&gt;
Note: If you are building this game by following the tutorial, you will have a different project name than &amp;lt;code&amp;gt;reversi&amp;lt;/code&amp;gt; (i.e. &amp;lt;code&amp;gt;mygame_mygame.tpl&amp;lt;/code&amp;gt;). The file names in your project will be different than shown in this tutorial, replacing &amp;lt;code&amp;gt;reversi&amp;lt;/code&amp;gt; with your project name. Be sure that any code (other than comments) that references &amp;lt;code&amp;gt;reversi&amp;lt;/code&amp;gt; is changed to your actual project name.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;div id=&amp;quot;board&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* edit your &amp;lt;code&amp;gt;reversi.css&amp;lt;/code&amp;gt; file to transform it into a visible board:&lt;br /&gt;
&lt;br /&gt;
 #board {&lt;br /&gt;
    width: 536px;&lt;br /&gt;
    height: 528px;&lt;br /&gt;
    background-image: url(&#039;img/board.jpg&#039;);&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Important: refresh your page.&#039;&#039;&#039; Here&#039;s your board:[[File:reversi1.jpg]]&lt;br /&gt;
&lt;br /&gt;
If the board does not appear, refresh the page (always do this when you update the CSS file), and check the image filename. Remember file names are case sensitive!&lt;br /&gt;
&lt;br /&gt;
==== Code the Grid ====&lt;br /&gt;
Now, we need to create some invisible HTML elements where squares are. These elements will be used as position references for the white and black tokens. &lt;br /&gt;
&lt;br /&gt;
===== Build the grid of squares =====&lt;br /&gt;
The board is 8 squares by 8 squares. This means we need 64 squares. To avoid writing 64 individual &amp;lt;code&amp;gt;div&amp;lt;/code&amp;gt; elements on our template, we are going to generate the squares on JS setup.&lt;br /&gt;
&lt;br /&gt;
We&#039;ll do this in our Javascript &amp;lt;code&amp;gt;setup&amp;lt;/code&amp;gt; method under &amp;lt;code&amp;gt;// TODO: Set up your game interface here, according to &amp;quot;gamedatas&amp;quot;&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
const board = document.getElementById(&#039;board&#039;);&lt;br /&gt;
const hor_scale = 64.8;&lt;br /&gt;
const ver_scale = 64.4;&lt;br /&gt;
for (let x=1; x&amp;lt;=8; x++) {&lt;br /&gt;
    for (let y=1; y&amp;lt;=8; y++) {&lt;br /&gt;
        const left = Math.round((x - 1) * hor_scale + 10);&lt;br /&gt;
        const top = Math.round((y - 1) * ver_scale + 7);&lt;br /&gt;
        // we use afterbegin to make sure squares are placed before discs&lt;br /&gt;
        board.insertAdjacentHTML(`afterbegin`, `&amp;lt;div id=&amp;quot;square_${x}_${y}&amp;quot; class=&amp;quot;square&amp;quot; style=&amp;quot;left: ${left}px; top: ${top}px;&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;`);&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note: as you can see, squares in our &amp;lt;code&amp;gt;board.jpg&amp;lt;/code&amp;gt; files do not have an exact width/height in pixels, and that&#039;s the reason we are using floating point numbers here.&lt;br /&gt;
&lt;br /&gt;
===== Style Those Squares =====&lt;br /&gt;
Now, to finish our work and check if everything works fine, we are going to style our square a little bit in our CSS stylesheet:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#board {&lt;br /&gt;
    width: 536px;&lt;br /&gt;
    height: 528px;&lt;br /&gt;
    background-image: url(&#039;img/board.jpg&#039;);&lt;br /&gt;
    position: relative;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.square {&lt;br /&gt;
    width: 62px;&lt;br /&gt;
    height: 62px;&lt;br /&gt;
    position: absolute;&lt;br /&gt;
    background-color: red;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Explanations:&lt;br /&gt;
* With &amp;quot;position: relative&amp;quot; on board, we ensure square elements are positioned relatively to board.&lt;br /&gt;
* &amp;lt;code&amp;gt;background-color: red;&amp;lt;/code&amp;gt; is used for testing. This allows us to see the invisible elements. (You could instead do something like &amp;lt;code&amp;gt;outline: 2px solid orange;&amp;lt;/code&amp;gt; have fun and be creative)&lt;br /&gt;
&lt;br /&gt;
Let&#039;s refresh and check our (beautiful) squares:&lt;br /&gt;
&lt;br /&gt;
[[File:reversi2.jpg]]&lt;br /&gt;
&lt;br /&gt;
Now that you know the squares are there, you can remove the test line &amp;lt;code&amp;gt;background-color: red;&amp;lt;/code&amp;gt;  from your &amp;lt;code&amp;gt;.square&amp;lt;/code&amp;gt; class in the CSS stylesheet.&lt;br /&gt;
&lt;br /&gt;
===== Not Working? =====&lt;br /&gt;
If the styled squares do not appear, inspect and check your css (Chrome DevTools: Application &amp;gt; Frames &amp;gt; top &amp;gt; Stylesheets &amp;gt; reversi.css). &lt;br /&gt;
&lt;br /&gt;
== The Tokens ==&lt;br /&gt;
&lt;br /&gt;
Now, our board is ready for some tokens!&lt;br /&gt;
&lt;br /&gt;
[Note: Throughout this tutorial, sometimes &amp;quot;tokens&amp;quot; is used, and sometimes &amp;quot;discs&amp;quot; is used. They are often swapped if you&#039;re looking at code in the reversi example project.]&lt;br /&gt;
&lt;br /&gt;
=== Build the Token ===&lt;br /&gt;
There are quite a few steps before the tokens will appear. You may be used to testing after every change, but that won&#039;t work well here. The token will &#039;&#039;&#039;not&#039;&#039;&#039; show until you have add styles to the css, js template to the tpl, utility method in the js,  adjusted the php file, and added the token to the board in the js file.&lt;br /&gt;
&lt;br /&gt;
==== HTML in the .tpl file ====&lt;br /&gt;
At first, we introduce a new &#039;div&#039; element as a child of &amp;quot;board&amp;quot; to host all these tokens (in our template):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;div id=&amp;quot;board&amp;quot;&amp;gt;&lt;br /&gt;
    &lt;br /&gt;
    &amp;lt;div id=&amp;quot;discs&amp;quot;&amp;gt;&lt;br /&gt;
    &amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note: &amp;lt;code&amp;gt;discs&amp;lt;/code&amp;gt; is plural. This div will be used to hold the token divs. Shortly, we will use javascript to add individual tokens to the board.&lt;br /&gt;
&lt;br /&gt;
==== Add Token to img directory ====&lt;br /&gt;
Here&#039;s a new piece of art with the tokens. We need transparency here so we are using a png file:&lt;br /&gt;
&lt;br /&gt;
[[File:tokens.png]]&lt;br /&gt;
&lt;br /&gt;
Upload this image file &amp;lt;code&amp;gt;tokens.png&amp;lt;/code&amp;gt; in your &amp;lt;code&amp;gt;img/&amp;lt;/code&amp;gt; directory.&lt;br /&gt;
&lt;br /&gt;
Important Fun Fact: we are using ONE file for both tokens. It is really important to use a minimum number of graphic files for your game. This is called the &amp;quot;CSS sprite&amp;quot; technique, because it makes the game load faster and more reliable. [http://www.w3schools.com/css/css_image_sprites.asp Read more about CSS sprites].&lt;br /&gt;
&lt;br /&gt;
==== Style the Tokens in .css file ====&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
.disc {&lt;br /&gt;
    width: 56px;&lt;br /&gt;
    height: 56px;&lt;br /&gt;
    position: absolute;&lt;br /&gt;
    background-image: url(&#039;img/tokens.png&#039;);&lt;br /&gt;
    background-size: auto 100%;&lt;br /&gt;
}&lt;br /&gt;
.disc[data-color=&amp;quot;ffffff&amp;quot;] { background-position-x: 0%; }&lt;br /&gt;
.disc[data-color=&amp;quot;000000&amp;quot;] { background-position-x: 100%; }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
With this CSS code, we can set and change the token color by changing the data-color attribute. Using data instead of a class ensures it can be only one of them (the disc cannot be black and white at the same time).&lt;br /&gt;
&lt;br /&gt;
Note the &amp;quot;&amp;lt;code&amp;gt;position: absolute&amp;lt;/code&amp;gt;&amp;quot; which allows us to position tokens on the board and make them &amp;quot;slide&amp;quot; to their positions.&lt;br /&gt;
&lt;br /&gt;
==== Add Token Utility Method in .js file ====&lt;br /&gt;
Now, let&#039;s make the first token appear on our board. Tokens are not visible at the beginning of the game: they appear dynamically during the game. For this reason, we are going to make them appear from our Javascript code, using a template string&lt;br /&gt;
&lt;br /&gt;
Let&#039;s create a method in our Javascript code (in the &amp;lt;code&amp;gt;reversi.js&amp;lt;/code&amp;gt; file) that will make a token appear on the board, using this template. Add under the section //// Utility methods:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
addDiscOnBoard: function( x, y, player )&lt;br /&gt;
{&lt;br /&gt;
    var color = this.gamedatas.players[ player ].color;&lt;br /&gt;
    &lt;br /&gt;
    document.getElementById(&#039;discs&#039;).insertAdjacentHTML(&#039;beforeend&#039;, `&amp;lt;div class=&amp;quot;disc&amp;quot; data-color=&amp;quot;${color}&amp;quot; id=&amp;quot;disc_${x}${y}&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;`);&lt;br /&gt;
    &lt;br /&gt;
    this.placeOnObject( `disc_${x}${y}`, &#039;overall_player_board_&#039;+player );&lt;br /&gt;
    this.slideToObject( `disc_${x}${y}`, &#039;square_&#039;+x+&#039;_&#039;+y ).play();&lt;br /&gt;
},  &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===== Utility Method Explanation =====&lt;br /&gt;
* with &amp;lt;code&amp;gt;element.insertAdjacentHTML&amp;lt;/code&amp;gt; method, we create a HTML piece of code and insert it as a new child of &amp;lt;code&amp;gt;tokens&amp;lt;/code&amp;gt; div element.&lt;br /&gt;
* with &amp;lt;code&amp;gt;this.placeOnObject&amp;lt;/code&amp;gt; BGA method, we place this element over the panel of some player. &lt;br /&gt;
* Immediately after, using &amp;lt;code&amp;gt;this.slideToObject&amp;lt;/code&amp;gt; BGA method, we make the token slide to the &amp;lt;code&amp;gt;square&amp;lt;/code&amp;gt; element, its final destination.&lt;br /&gt;
* &amp;lt;code&amp;gt;&#039;overall_player_board_&#039;+player&amp;lt;/code&amp;gt; refers to the div element that contains each player&#039;s information and avatar. By initially placing the token here, it gives the effect that the player&#039;s avatar is throwing the token onto the board.&lt;br /&gt;
&lt;br /&gt;
Note: don&#039;t forget to call the &amp;lt;code&amp;gt;play()&amp;lt;/code&amp;gt;, otherwise the token will remain at its original location.&lt;br /&gt;
&lt;br /&gt;
Note: during this process, the parent of the new token HTML element will stay &amp;lt;code&amp;gt;tokens&amp;lt;/code&amp;gt;. &amp;lt;code&amp;gt;placeOnObject&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;slideToObject&amp;lt;/code&amp;gt; methods are &#039;&#039;only&#039;&#039; moving the position of elements on screen, and they are &#039;&#039;not&#039;&#039; modifying the HTML tree.&lt;br /&gt;
&lt;br /&gt;
==== Set Token Colors in setupNewGame in .game.php file ====&lt;br /&gt;
Before we can show a token, we need to set the player colors in the setupNewGame function in reversi.game.php:&lt;br /&gt;
&lt;br /&gt;
Replace &amp;lt;code&amp;gt;$default_colors = $gameinfos[&#039;player_colors&#039;];&amp;lt;/code&amp;gt; with the following line:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        $default_colors = array( &amp;quot;ffffff&amp;quot;, &amp;quot;000000&amp;quot; );&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note: A few lines below, you may have to remove the line &amp;lt;code&amp;gt;self::reattributeColorsBasedOnPreferences( $players, $gameinfos[&#039;player_colors&#039;] );&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Test the Token ===&lt;br /&gt;
Now, to test if everything works fine&lt;br /&gt;
&lt;br /&gt;
==== addTokenOnBoard() in .js file to Test ====&lt;br /&gt;
In &amp;lt;code&amp;gt;reversi.js&amp;lt;/code&amp;gt;, in &amp;lt;code&amp;gt;setup: function&amp;lt;/code&amp;gt;, under the code we added to generate the squares. &lt;br /&gt;
 this.addDiscOnBoard( 2, 2, this.player_id );&lt;br /&gt;
Now restart the game.&lt;br /&gt;
&lt;br /&gt;
A token should appear and slide immediately to its position, like this:&lt;br /&gt;
&lt;br /&gt;
[[File:reversi3.jpg]]&lt;br /&gt;
&lt;br /&gt;
== The database ==&lt;br /&gt;
&lt;br /&gt;
We did most of the client-side programming, so let&#039;s have a look on the other side now. To design the database model of our game, you will need to access the database. You won&#039;t need to do anything in database UI, yet.&lt;br /&gt;
&lt;br /&gt;
=== Accessing the Database ===&lt;br /&gt;
To access the database, start a game, then click &amp;quot;Go to game database&amp;quot; link at the bottom of our game, to access the database directly with a PhpMyAdmin instance.&lt;br /&gt;
&lt;br /&gt;
After the first time you&#039;ve acess the database, you could skip opening a game and instead, go to https://studio.boardgamearena.com/db/ . Your PhpMyAdmin username/password is in your welcome email.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note&#039;&#039;&#039;: do not remove existing tables&lt;br /&gt;
&lt;br /&gt;
=== Create Table in .sql file ===&lt;br /&gt;
Now, you are able to create the table(s) you need for your game, and report every SQL command used in your &amp;lt;code&amp;gt;dbmodel.sql&amp;lt;/code&amp;gt; file. &lt;br /&gt;
&lt;br /&gt;
The database model of Reversi is short: just one table with the squares of the board. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
CREATE TABLE IF NOT EXISTS `board` (&lt;br /&gt;
  `board_x` smallint(5) unsigned NOT NULL,&lt;br /&gt;
  `board_y` smallint(5) unsigned NOT NULL,&lt;br /&gt;
  `board_player` int(10) unsigned DEFAULT NULL,&lt;br /&gt;
  PRIMARY KEY (`board_x`,`board_y`)&lt;br /&gt;
) ENGINE=InnoDB DEFAULT CHARSET=utf8;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Add the above SQL to &amp;lt;code&amp;gt;dbmodel.sql&amp;lt;/code&amp;gt;. Pay special attention to the backtick &amp;lt;code&amp;gt;`&amp;lt;/code&amp;gt; character vs. the single quote &amp;lt;code&amp;gt;&#039;&amp;lt;/code&amp;gt; when working with SQL. &lt;br /&gt;
&lt;br /&gt;
=== Test the Table ===&lt;br /&gt;
Now, a new database with a &amp;lt;code&amp;gt;board&amp;lt;/code&amp;gt; table will be created each time we start a Reversi game. This is why after modifying our &amp;lt;code&amp;gt;dbmodel.sql&amp;lt;/code&amp;gt; it&#039;s a good time to stop your current game &amp;amp; start a new game.&lt;br /&gt;
&lt;br /&gt;
Start a new game and verify a table is created.&lt;br /&gt;
&lt;br /&gt;
== Setup the initial game position ==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note&#039;&#039;&#039;: From now on, you must launch the game with &#039;&#039;&#039;two players&#039;&#039;&#039; to get two &amp;lt;code&amp;gt;player_id&amp;lt;/code&amp;gt;s within the database. Otherwise, the game will crash.&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;setupNewGame&amp;lt;/code&amp;gt; method of our &amp;lt;code&amp;gt;reversi.game.php&amp;lt;/code&amp;gt; is called during initial setup. This initializes our data and places the starting tokens on the board. At the beginning of the game, there should be 4 tokens on the board.&lt;br /&gt;
&lt;br /&gt;
=== Initialize the Board in .game.php file ===&lt;br /&gt;
Under &amp;lt;code&amp;gt;// TODO: setup the initial game situation here&amp;lt;/code&amp;gt;, initialize the board&amp;lt;pre&amp;gt;&lt;br /&gt;
        // Init the board&lt;br /&gt;
        $sql = &amp;quot;INSERT INTO board (board_x,board_y,board_player) VALUES &amp;quot;;&lt;br /&gt;
        $sql_values = array();&lt;br /&gt;
        list( $blackplayer_id, $whiteplayer_id ) = array_keys( $players );&lt;br /&gt;
        for( $x=1; $x&amp;lt;=8; $x++ )&lt;br /&gt;
        {&lt;br /&gt;
            for( $y=1; $y&amp;lt;=8; $y++ )&lt;br /&gt;
            {&lt;br /&gt;
                $token_value = &amp;quot;NULL&amp;quot;;&lt;br /&gt;
                if( ($x==4 &amp;amp;&amp;amp; $y==4) || ($x==5 &amp;amp;&amp;amp; $y==5) )  // Initial positions of white player&lt;br /&gt;
                    $token_value = &amp;quot;&#039;$whiteplayer_id&#039;&amp;quot;;&lt;br /&gt;
                else if( ($x==4 &amp;amp;&amp;amp; $y==5) || ($x==5 &amp;amp;&amp;amp; $y==4) )  // Initial positions of black player&lt;br /&gt;
                    $token_value = &amp;quot;&#039;$blackplayer_id&#039;&amp;quot;;&lt;br /&gt;
                    &lt;br /&gt;
                $sql_values[] = &amp;quot;(&#039;$x&#039;,&#039;$y&#039;,$token_value)&amp;quot;;&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
        $sql .= implode( &#039;,&#039;, $sql_values );&lt;br /&gt;
        $this-&amp;gt;DbQuery( $sql );&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Board Initialization Explanation ====&lt;br /&gt;
&lt;br /&gt;
* We create one table entry for each square, with a &amp;lt;code&amp;gt;NULL&amp;lt;/code&amp;gt; value which means &amp;quot;empty square&amp;quot;&lt;br /&gt;
* On 4 of the squares, we place an initial token.&lt;br /&gt;
&lt;br /&gt;
After this, we set &amp;lt;code&amp;gt;activeNextPlayer&amp;lt;/code&amp;gt; to make the first player active at the beginning of the game (this line is already present in the default code template).&lt;br /&gt;
&lt;br /&gt;
If you didn&#039;t do it earlier, you need to remove the call to &amp;lt;code&amp;gt;self::reattributeColorsBasedOnPreferences()&amp;lt;/code&amp;gt; in &amp;lt;code&amp;gt;SetupNewGame()&amp;lt;/code&amp;gt;. If you don&#039;t, player color preferences will try (and fail) to override the two colors supported here.&lt;br /&gt;
&lt;br /&gt;
=== Show the Initial Token Setup ===&lt;br /&gt;
Now, we need to make these tokens appear on the client side. The first step is to return the token positions with our &amp;lt;code&amp;gt;getAllDatas()&amp;lt;/code&amp;gt; PHP method. &amp;lt;code&amp;gt;getAllDatas()&amp;lt;/code&amp;gt; is called during each page reload.&lt;br /&gt;
&lt;br /&gt;
In the &amp;lt;code&amp;gt;getAllDatas()&amp;lt;/code&amp;gt; method, after &amp;lt;code&amp;gt;// TODO: Gather all information about current game situation (visible by player $current_player_id)&amp;lt;/code&amp;gt;, add the following lines:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        // Get reversi board token&lt;br /&gt;
        $result[&#039;board&#039;] = self::getObjectListFromDB( &amp;quot;SELECT board_x x, board_y y, board_player player&lt;br /&gt;
                                                       FROM board&lt;br /&gt;
                                                       WHERE board_player IS NOT NULL&amp;quot; );&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Next, you may need to modify the query that gets player information to also get the player&#039;s colors. This is in the variable &amp;lt;code&amp;gt;$sql&amp;lt;/code&amp;gt;, above the lines you just inserted in &amp;lt;code&amp;gt;getAllDatas()&amp;lt;/code&amp;gt;. Below is what the line will look like. Notice how we&#039;ve added &amp;lt;code&amp;gt;player_color color&amp;lt;/code&amp;gt; to the sql query.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$sql = &amp;quot;SELECT player_id id, player_score score, player_color color FROM player &amp;quot;;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
We are using the BGA framework&#039;s &amp;lt;code&amp;gt;getObjectListFromDB()&amp;lt;/code&amp;gt; that formats the result of this SQL query in a PHP array with x, y and player attributes. We add it to the result associative array with the key &amp;lt;code&amp;gt;board&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Last, we process this array client side. Let&#039;s place a token on the board for each array item. We&#039;ll do this in our Javascript &amp;lt;code&amp;gt;setup&amp;lt;/code&amp;gt; method under the code we added to generate the squares. &lt;br /&gt;
&lt;br /&gt;
This will result in a removal or edit of the previously added line &amp;lt;code&amp;gt;this.addDiscOnBoard(2, 2, this.player_id);&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
for( var i in gamedatas.board )&lt;br /&gt;
{&lt;br /&gt;
    var square = gamedatas.board[i];&lt;br /&gt;
    &lt;br /&gt;
    if( square.player !== null )&lt;br /&gt;
    {&lt;br /&gt;
        this.addDiscOnBoard( square.x, square.y, square.player );&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;board&amp;lt;/code&amp;gt; entry created in &amp;lt;code&amp;gt;getAllDatas()&amp;lt;/code&amp;gt; is used here as &amp;lt;code&amp;gt;gamedatas.board&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Test the Game Start ===&lt;br /&gt;
Reload... and here we are:&lt;br /&gt;
&lt;br /&gt;
[[File:reversi5.jpg]]&lt;br /&gt;
&lt;br /&gt;
It starts to feel like Reversi here...&lt;br /&gt;
&lt;br /&gt;
== The game state machine ==&lt;br /&gt;
&lt;br /&gt;
Stop your game, again. You&#039;re about to start the core game logic.&lt;br /&gt;
&lt;br /&gt;
You already read [http://www.slideshare.net/boardgamearena/bga-studio-focus-on-bga-game-state-machine Focus on BGA game state machine], so you know that this is the heart of your game logic. For reversi, it&#039;s relatively simple. Here&#039;s a diagram of our game state machine:&lt;br /&gt;
&lt;br /&gt;
[[File:reversi6.jpg]]&lt;br /&gt;
&lt;br /&gt;
=== Build your States ===&lt;br /&gt;
And here&#039;s our &amp;lt;code&amp;gt;states.inc.php&amp;lt;/code&amp;gt;, according to this diagram:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$machinestates = array(&lt;br /&gt;
&lt;br /&gt;
    ST_BGA_GAME_SETUP =&amp;gt; array(&lt;br /&gt;
        &amp;quot;name&amp;quot; =&amp;gt; &amp;quot;gameSetup&amp;quot;,&lt;br /&gt;
        &amp;quot;description&amp;quot; =&amp;gt; clienttranslate(&amp;quot;Game setup&amp;quot;),&lt;br /&gt;
        &amp;quot;type&amp;quot; =&amp;gt; &amp;quot;manager&amp;quot;,&lt;br /&gt;
        &amp;quot;action&amp;quot; =&amp;gt; &amp;quot;stGameSetup&amp;quot;,&lt;br /&gt;
        &amp;quot;transitions&amp;quot; =&amp;gt; array( &amp;quot;&amp;quot; =&amp;gt; ST_PLAYER_PLAY_DISC )&lt;br /&gt;
    ),&lt;br /&gt;
    &lt;br /&gt;
    ST_PLAYER_PLAY_DISC =&amp;gt; array(&lt;br /&gt;
        &amp;quot;name&amp;quot; =&amp;gt; &amp;quot;playerTurn&amp;quot;,&lt;br /&gt;
		&amp;quot;description&amp;quot; =&amp;gt; clienttranslate(&#039;${actplayer} must play a disc&#039;),&lt;br /&gt;
		&amp;quot;descriptionmyturn&amp;quot; =&amp;gt; clienttranslate(&#039;${you} must play a disc&#039;),&lt;br /&gt;
        &amp;quot;type&amp;quot; =&amp;gt; &amp;quot;activeplayer&amp;quot;,&lt;br /&gt;
        &amp;quot;args&amp;quot; =&amp;gt; &amp;quot;argPlayerTurn&amp;quot;,&lt;br /&gt;
        &amp;quot;possibleactions&amp;quot; =&amp;gt; array( &#039;actPlayDisc&#039; ),&lt;br /&gt;
        &amp;quot;transitions&amp;quot; =&amp;gt; array( &amp;quot;playDisc&amp;quot; =&amp;gt; ST_NEXT_PLAYER, &amp;quot;zombiePass&amp;quot; =&amp;gt; ST_NEXT_PLAYER )&lt;br /&gt;
    ),&lt;br /&gt;
    &lt;br /&gt;
    ST_NEXT_PLAYER =&amp;gt; array(&lt;br /&gt;
        &amp;quot;name&amp;quot; =&amp;gt; &amp;quot;nextPlayer&amp;quot;,&lt;br /&gt;
        &amp;quot;type&amp;quot; =&amp;gt; &amp;quot;game&amp;quot;,&lt;br /&gt;
        &amp;quot;action&amp;quot; =&amp;gt; &amp;quot;stNextPlayer&amp;quot;,&lt;br /&gt;
        &amp;quot;updateGameProgression&amp;quot; =&amp;gt; true,        &lt;br /&gt;
        &amp;quot;transitions&amp;quot; =&amp;gt; array( &amp;quot;nextTurn&amp;quot; =&amp;gt; ST_PLAYER_PLAY_DISC, &amp;quot;cantPlay&amp;quot; =&amp;gt; ST_NEXT_PLAYER, &amp;quot;endGame&amp;quot; =&amp;gt; ST_END_GAME )&lt;br /&gt;
    ),&lt;br /&gt;
   &lt;br /&gt;
    ST_END_GAME =&amp;gt; array(&lt;br /&gt;
        &amp;quot;name&amp;quot; =&amp;gt; &amp;quot;gameEnd&amp;quot;,&lt;br /&gt;
        &amp;quot;description&amp;quot; =&amp;gt; clienttranslate(&amp;quot;End of game&amp;quot;),&lt;br /&gt;
        &amp;quot;type&amp;quot; =&amp;gt; &amp;quot;manager&amp;quot;,&lt;br /&gt;
        &amp;quot;action&amp;quot; =&amp;gt; &amp;quot;stGameEnd&amp;quot;,&lt;br /&gt;
        &amp;quot;args&amp;quot; =&amp;gt; &amp;quot;argGameEnd&amp;quot;&lt;br /&gt;
    )&lt;br /&gt;
&lt;br /&gt;
);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We used constants to give an index to the different states. This is to avoid mistakes when we reuse these indexes on the transitions array.&lt;br /&gt;
&lt;br /&gt;
Let&#039;s create a file you&#039;ll put in modules/php/constants.inc.php :&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;?php&lt;br /&gt;
&lt;br /&gt;
/*&lt;br /&gt;
 * State constants&lt;br /&gt;
 */&lt;br /&gt;
const ST_BGA_GAME_SETUP = 1;&lt;br /&gt;
&lt;br /&gt;
const ST_PLAYER_PLAY_DISC = 10;&lt;br /&gt;
const ST_NEXT_PLAYER = 11;&lt;br /&gt;
&lt;br /&gt;
const ST_END_GAME = 99;&lt;br /&gt;
&lt;br /&gt;
?&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You will also need to add &amp;lt;code&amp;gt;require_once(&amp;quot;modules/php/constants.inc.php&amp;quot;);&amp;lt;/code&amp;gt; at the beginning of the state.inc.php to load these constants.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Now, in &amp;lt;code&amp;gt;reversi.game.php&amp;lt;/code&amp;gt; let&#039;s create the methods that are declared in this game states description file:&lt;br /&gt;
* &amp;lt;code&amp;gt;argPlayerTurn&amp;lt;/code&amp;gt;: referenced in the &amp;lt;code&amp;gt;args&amp;lt;/code&amp;gt; property of the &amp;lt;code&amp;gt;playerTurn&amp;lt;/code&amp;gt; state; this is the name of the method to call to retrieve arguments for this gamestate. Arguments are sent to the client side to be used on &amp;lt;code&amp;gt;onEnteringState&amp;lt;/code&amp;gt; or to set arguments in the gamestate description.&lt;br /&gt;
* &amp;lt;code&amp;gt;stNextPlayer&amp;lt;/code&amp;gt;: referenced in the &amp;lt;code&amp;gt;action&amp;lt;/code&amp;gt; property of the &amp;lt;code&amp;gt;nextPlayer&amp;lt;/code&amp;gt; state; this is the name of the method to call when this game state become the current game state.&lt;br /&gt;
&lt;br /&gt;
=== Test Your States ===&lt;br /&gt;
... and start a new Reversi game.&lt;br /&gt;
&lt;br /&gt;
As you can see on the screen capture below, the BGA framework makes the game jump to our first game state &amp;lt;code&amp;gt;playerTurn&amp;lt;/code&amp;gt; right after the initial setup. That&#039;s why the status bar contains the description of &amp;lt;code&amp;gt;playerTurn&amp;lt;/code&amp;gt; state (&amp;quot;XXXX must play a disc&amp;quot;):&lt;br /&gt;
&lt;br /&gt;
[[File:reversi7.jpg]]&lt;br /&gt;
&lt;br /&gt;
== The rules ==&lt;br /&gt;
&lt;br /&gt;
We will use the &amp;lt;code&amp;gt;getPossibleMoves&amp;lt;/code&amp;gt; PHP method to:&lt;br /&gt;
* Indicate to the current player where she is allowed to play by returning a list of coordinates&lt;br /&gt;
* Check if the player has the right to play in the spot they choose&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;&lt;br /&gt;
Example of getPossibleMoves here https://gist.github.com/leocaseiro/a8bc2851bd0caddd06685b5035937d15&lt;br /&gt;
&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This is pure PHP programming here, and there are no special things from the BGA framework that can be used. This is why we won&#039;t go into details here. The overall idea is:&lt;br /&gt;
* Create a &amp;lt;code&amp;gt;getTurnedOverDiscs(x,y)&amp;lt;/code&amp;gt; method that returns coordinates of discs that would be turned over if a token would be played at &amp;lt;code&amp;gt;x&amp;lt;/code&amp;gt;,&amp;lt;code&amp;gt;y&amp;lt;/code&amp;gt;.&lt;br /&gt;
* Loop through all free squares of the board and call the &amp;lt;code&amp;gt;getTurnedOverDiscs&amp;lt;/code&amp;gt; method on each of them. If at least 1 token is turned over, this is a valid move.&lt;br /&gt;
&lt;br /&gt;
IMPORTANT: Making a database query is slow! Please don&#039;t load the entire game board with a SQL query multiple times. In our implementation, we load the entire board once at the beginning of &amp;lt;code&amp;gt;getPossibleMoves&amp;lt;/code&amp;gt;, and then pass the board as an argument to all methods.&lt;br /&gt;
&lt;br /&gt;
If you want to look into details, please look at the &amp;quot;utility method&amp;quot; sections of &amp;lt;code&amp;gt;reversi.game.php&amp;lt;/code&amp;gt;. If building the tutorial yourself, copy the functions under &amp;quot;Utility functions&amp;quot; comment from the Reversi tutorial.&lt;br /&gt;
&lt;br /&gt;
== Display allowed moves ==&lt;br /&gt;
&lt;br /&gt;
Now we want to highlight the squares where the player can place a disc.&lt;br /&gt;
&lt;br /&gt;
To do this, we add a &amp;lt;code&amp;gt;argPlayerTurn&amp;lt;/code&amp;gt; method in &amp;lt;code&amp;gt;reversi.game.php&amp;lt;/code&amp;gt;. This method is called on the server each time we enter into &amp;lt;code&amp;gt;playerTurn&amp;lt;/code&amp;gt; game state, and its result is transferred automatically to the client-side:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
function argPlayerTurn(): array&lt;br /&gt;
{&lt;br /&gt;
    return [&lt;br /&gt;
        &#039;possibleMoves&#039; =&amp;gt; $this-&amp;gt;getPossibleMoves( intval($this-&amp;gt;getActivePlayerId()) )&lt;br /&gt;
    ];&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We use the &amp;lt;code&amp;gt;getPossibleMoves&amp;lt;/code&amp;gt; method we just developed.&lt;br /&gt;
&lt;br /&gt;
Each time we enter into a new game state, we use the &amp;lt;code&amp;gt;onEnteringState&amp;lt;/code&amp;gt; Javascript method (in the &amp;lt;code&amp;gt;reversi.js&amp;lt;/code&amp;gt; file, under &amp;quot;Game &amp;amp; client states&amp;quot;). This lets us use the data returned by the method above on the client side.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        onEnteringState: function( stateName, args )&lt;br /&gt;
        {&lt;br /&gt;
           console.log( &#039;Entering state: &#039;+stateName );&lt;br /&gt;
            &lt;br /&gt;
            switch( stateName )&lt;br /&gt;
            {&lt;br /&gt;
            case &#039;playerTurn&#039;:&lt;br /&gt;
                this.updatePossibleMoves( args.args.possibleMoves );&lt;br /&gt;
                break;&lt;br /&gt;
            }&lt;br /&gt;
        },&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
So, when we enter into &amp;lt;code&amp;gt;playerTurn&amp;lt;/code&amp;gt; game state, we call our &amp;lt;code&amp;gt;updatePossibleMoves&amp;lt;/code&amp;gt; method (under the &amp;quot;Utility methods&amp;quot; section). This method looks like this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
updatePossibleMoves: function( possibleMoves )&lt;br /&gt;
{&lt;br /&gt;
    // Remove current possible moves&lt;br /&gt;
    document.querySelectorAll(&#039;.possibleMove&#039;).forEach(div =&amp;gt; div.classList.remove(&#039;possibleMove&#039;));&lt;br /&gt;
&lt;br /&gt;
    for( var x in possibleMoves )&lt;br /&gt;
    {&lt;br /&gt;
        for( var y in possibleMoves[ x ] )&lt;br /&gt;
        {&lt;br /&gt;
            // x,y is a possible move&lt;br /&gt;
            document.getElementById(`square_${x}_${y}`).classList.add(&#039;possibleMove&#039;);&lt;br /&gt;
        }            &lt;br /&gt;
    }&lt;br /&gt;
                &lt;br /&gt;
    this.addTooltipToClass( &#039;possibleMove&#039;, &#039;&#039;, _(&#039;Place a disc here&#039;) );&lt;br /&gt;
},&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Here&#039;s what this does. At first, it removes all &amp;lt;code&amp;gt;possibleMove&amp;lt;/code&amp;gt; classes currently applied with the very useful &amp;lt;code&amp;gt;document.querySelectorAll&amp;lt;/code&amp;gt; method.&lt;br /&gt;
&lt;br /&gt;
Then it loops through all possible moves our PHP &amp;lt;code&amp;gt;updatePossibleMoves&amp;lt;/code&amp;gt; function created for us, and adds the &amp;lt;code&amp;gt;possibleMove&amp;lt;/code&amp;gt; class to each corresponding square.&lt;br /&gt;
&lt;br /&gt;
Finally, it uses the BGA framework &amp;lt;code&amp;gt;addTooltipToClass&amp;lt;/code&amp;gt; method to associate a tooltip to all those highlighted squares so that players can understand their meaning.&lt;br /&gt;
&lt;br /&gt;
To see the possible moves we need to create a CSS class (&amp;lt;code&amp;gt;possibleMove&amp;lt;/code&amp;gt;) that can be applied to a &amp;lt;code&amp;gt;square&amp;lt;/code&amp;gt; element to highlight it:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
.possibleMove {&lt;br /&gt;
    background-color: white;&lt;br /&gt;
    opacity: 0.2; &lt;br /&gt;
    cursor: pointer;  &lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
And here we are:&lt;br /&gt;
&lt;br /&gt;
[[File:reversi8.jpg.jpg]]&lt;br /&gt;
&lt;br /&gt;
== Let&#039;s play ==&lt;br /&gt;
&lt;br /&gt;
From now, it&#039;s better to restart a game with 2 players, because we are going to implement a complete Reversi turn. The summary of what we are going to do is:&lt;br /&gt;
* When we click on a &amp;lt;code&amp;gt;possibleMove&amp;lt;/code&amp;gt; square, send the move to the server.&lt;br /&gt;
* Server side, check the move is correct, apply Reversi rules and jump to next player.&lt;br /&gt;
* Client side, change the token position to reflect the move.&lt;br /&gt;
&lt;br /&gt;
First we associate each click on a square to one of our methods using our Javascript &amp;lt;code&amp;gt;setup&amp;lt;/code&amp;gt; method:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
document.querySelectorAll(&#039;.square&#039;).forEach(square =&amp;gt; square.addEventListener(&#039;click&#039;, e =&amp;gt; this.onPlayDisc(e)));&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note the use of the &amp;quot;dojo.query&amp;quot; method to get all HTML elements with &amp;quot;square&amp;quot; class in just one function call. Now, our &amp;quot;onPlayDisc&amp;quot; method is called each time someone clicks on a square.&lt;br /&gt;
&lt;br /&gt;
Here&#039;s our &amp;quot;onPlayDisc&amp;quot; method below:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
onPlayDisc: function( evt )&lt;br /&gt;
{&lt;br /&gt;
    // Stop this event propagation&lt;br /&gt;
    evt.preventDefault();&lt;br /&gt;
    evt.stopPropagation();&lt;br /&gt;
&lt;br /&gt;
    // Get the cliqued square x and y&lt;br /&gt;
    // Note: square id format is &amp;quot;square_X_Y&amp;quot;&lt;br /&gt;
    var coords = evt.currentTarget.id.split(&#039;_&#039;);&lt;br /&gt;
    var x = coords[1];&lt;br /&gt;
    var y = coords[2];&lt;br /&gt;
&lt;br /&gt;
    if(!document.getElementById(`square_${x}_${y}`).classList.contains(&#039;possibleMove&#039;)) {&lt;br /&gt;
        // This is not a possible move =&amp;gt; the click does nothing&lt;br /&gt;
        return ;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    this.bgaPerformAction(&amp;quot;actPlayDisc&amp;quot;, {&lt;br /&gt;
        x:x,&lt;br /&gt;
        y:y&lt;br /&gt;
    });&lt;br /&gt;
},&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
What we do here is:&lt;br /&gt;
* We stop the propagation of the Javascript &amp;lt;code&amp;gt;onclick&amp;lt;/code&amp;gt; event. Otherwise, it can lead to random behavior so it&#039;s always a good idea.&lt;br /&gt;
* We get the x/y coordinates of the square by using &amp;lt;code&amp;gt;evt.currentTarget.id&amp;lt;/code&amp;gt;&lt;br /&gt;
* We check that clicked square has the &amp;lt;code&amp;gt;possibleMove&amp;lt;/code&amp;gt; class, otherwise we know for sure that we can&#039;t play there.&lt;br /&gt;
* Finally, we make a call to the server using BGA &amp;lt;code&amp;gt;bgaPerformAction&amp;lt;/code&amp;gt; method with argument x and y. This call will check that &amp;lt;code&amp;gt;actPlayDisc&amp;lt;/code&amp;gt; action is possible, according to current game state (see &amp;lt;code&amp;gt;possibleactions&amp;lt;/code&amp;gt; entry in our &amp;lt;code&amp;gt;playerTurn&amp;lt;/code&amp;gt; game state defined above). This check is important to avoid issues if a player double clicks on a square.&lt;br /&gt;
&lt;br /&gt;
Now, we have to manage this &amp;lt;code&amp;gt;actPlayDisc&amp;lt;/code&amp;gt; action on the server side. At first, we introduce a &amp;lt;code&amp;gt;actPlayDisc&amp;lt;/code&amp;gt; entry point in our &amp;lt;code&amp;gt;reversi.action.php&amp;lt;/code&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
public function actPlayDisc()&lt;br /&gt;
{&lt;br /&gt;
    $this-&amp;gt;setAjaxMode();&lt;br /&gt;
    $x = (int)$this-&amp;gt;getArg( &amp;quot;x&amp;quot;, AT_posint, true );&lt;br /&gt;
    $y = (int)$this-&amp;gt;getArg( &amp;quot;y&amp;quot;, AT_posint, true );&lt;br /&gt;
    $result = $this-&amp;gt;game-&amp;gt;actPlayDisc( $x, $y );&lt;br /&gt;
    $this-&amp;gt;ajaxResponse( );&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
As you can see, we get the 2 arguments x and y from the javascript call, and call a corresponding &amp;lt;code&amp;gt;actPlayDisc&amp;lt;/code&amp;gt; method in our game logic (&amp;lt;code&amp;gt;reversi.game.php&amp;lt;/code&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
Now, let&#039;s have a look of this &amp;lt;code&amp;gt;actPlayDisc&amp;lt;/code&amp;gt; method:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
function actPlayDisc( int $x, int $y )&lt;br /&gt;
{&lt;br /&gt;
    // Check that this player is active and that this action is possible at this moment&lt;br /&gt;
    $this-&amp;gt;checkAction( &#039;actPlayDisc&#039; );  &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
... at first, we check that this action is possible according to current game state (see &amp;quot;possible action&amp;quot;). We already did it on client side, but it&#039;s important to do it on server side too (otherwise it would be possible to cheat).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        $player_id = intval($this-&amp;gt;getActivePlayerId()); &lt;br /&gt;
        &lt;br /&gt;
        // Now, check if this is a possible move&lt;br /&gt;
        $board = $this-&amp;gt;getBoard();&lt;br /&gt;
        $turnedOverDiscs = $this-&amp;gt;getTurnedOverDiscs( $x, $y, $player_id, $board );&lt;br /&gt;
        &lt;br /&gt;
        if( count( $turnedOverDiscs ) &amp;gt; 0 )&lt;br /&gt;
        {&lt;br /&gt;
            // This move is possible!&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
...now, we are using the &amp;lt;code&amp;gt;getTurnedOverDiscs&amp;lt;/code&amp;gt; method again to check that this move is possible.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
            // Let&#039;s place a disc at x,y and return all &amp;quot;$returned&amp;quot; discs to the active player&lt;br /&gt;
            &lt;br /&gt;
            $sql = &amp;quot;UPDATE board SET board_player=&#039;$player_id&#039;&lt;br /&gt;
                    WHERE ( board_x, board_y) IN ( &amp;quot;;&lt;br /&gt;
            &lt;br /&gt;
            foreach( $turnedOverDiscs as $turnedOver )&lt;br /&gt;
            {&lt;br /&gt;
                $sql .= &amp;quot;(&#039;&amp;quot;.$turnedOver[&#039;x&#039;].&amp;quot;&#039;,&#039;&amp;quot;.$turnedOver[&#039;y&#039;].&amp;quot;&#039;),&amp;quot;;&lt;br /&gt;
            }&lt;br /&gt;
            $sql .= &amp;quot;(&#039;$x&#039;,&#039;$y&#039;) ) &amp;quot;;&lt;br /&gt;
                       &lt;br /&gt;
            $this-&amp;gt;DbQuery( $sql );&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
... we update the database to change the color of all turned over disc + the disc we just placed.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
            // Update scores according to the number of disc on board&lt;br /&gt;
            $sql = &amp;quot;UPDATE player&lt;br /&gt;
                    SET player_score = (&lt;br /&gt;
                    SELECT COUNT( board_x ) FROM board WHERE board_player=player_id&lt;br /&gt;
                    )&amp;quot;;&lt;br /&gt;
            $this-&amp;gt;DbQuery( $sql );&lt;br /&gt;
            &lt;br /&gt;
            // Statistics&lt;br /&gt;
            $this-&amp;gt;incStat( count( $turnedOverDiscs ), &amp;quot;turnedOver&amp;quot;, $player_id );&lt;br /&gt;
            if( ($x==1 &amp;amp;&amp;amp; $y==1) || ($x==8 &amp;amp;&amp;amp; $y==1) || ($x==1 &amp;amp;&amp;amp; $y==8) || ($x==8 &amp;amp;&amp;amp; $y==8) )&lt;br /&gt;
                $this-&amp;gt;incStat( 1, &#039;discPlayedOnCorner&#039;, $player_id );&lt;br /&gt;
            else if( $x==1 || $x==8 || $y==1 || $y==8 )&lt;br /&gt;
                $this-&amp;gt;incStat( 1, &#039;discPlayedOnBorder&#039;, $player_id );&lt;br /&gt;
            else if( $x&amp;gt;=3 &amp;amp;&amp;amp; $x&amp;lt;=6 &amp;amp;&amp;amp; $y&amp;gt;=3 &amp;amp;&amp;amp; $y&amp;lt;=6 )&lt;br /&gt;
                $this-&amp;gt;incStat( 1, &#039;discPlayedOnCenter&#039;, $player_id );&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
... now, we update both player score by counting all disc, and we manage game statistics.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
            // Notify&lt;br /&gt;
            $this-&amp;gt;notifyAllPlayers( &amp;quot;playDisc&amp;quot;, clienttranslate( &#039;${player_name} plays a disc and turns over ${returned_nbr} disc(s)&#039; ), array(&lt;br /&gt;
                &#039;player_id&#039; =&amp;gt; $player_id,&lt;br /&gt;
                &#039;player_name&#039; =&amp;gt; $this-&amp;gt;getActivePlayerName(),&lt;br /&gt;
                &#039;returned_nbr&#039; =&amp;gt; count( $turnedOverDiscs ),&lt;br /&gt;
                &#039;x&#039; =&amp;gt; $x,&lt;br /&gt;
                &#039;y&#039; =&amp;gt; $y&lt;br /&gt;
            ) );&lt;br /&gt;
&lt;br /&gt;
            $this-&amp;gt;notifyAllPlayers( &amp;quot;turnOverDiscs&amp;quot;, &#039;&#039;, array(&lt;br /&gt;
                &#039;player_id&#039; =&amp;gt; $player_id,&lt;br /&gt;
                &#039;turnedOver&#039; =&amp;gt; $turnedOverDiscs&lt;br /&gt;
            ) );&lt;br /&gt;
            &lt;br /&gt;
            $newScores = $this-&amp;gt;getCollectionFromDb( &amp;quot;SELECT player_id, player_score FROM player&amp;quot;, true );&lt;br /&gt;
            $this-&amp;gt;notifyAllPlayers( &amp;quot;newScores&amp;quot;, &amp;quot;&amp;quot;, array(&lt;br /&gt;
                &amp;quot;scores&amp;quot; =&amp;gt; $newScores&lt;br /&gt;
            ) );&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
... then we notify about all these changes. We are using for that 3 notifications (&amp;lt;code&amp;gt;playDisc&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;turnOverDiscs&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;newScores&amp;lt;/code&amp;gt; that we are going to implement on client side later). Note that the description of the &amp;lt;code&amp;gt;playDisc&amp;lt;/code&amp;gt; notification will be logged in the game log.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
            // Then, go to the next state&lt;br /&gt;
            $this-&amp;gt;gamestate-&amp;gt;nextState( &#039;playDisc&#039; );&lt;br /&gt;
        }&lt;br /&gt;
        else&lt;br /&gt;
            throw new BgaSystemException( &amp;quot;Impossible move&amp;quot; );&lt;br /&gt;
    }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
... finally, we jump to the next game state if everything goes fine (&amp;lt;code&amp;gt;playDisc&amp;lt;/code&amp;gt; is the name of a transition in the &amp;lt;code&amp;gt;playerTurn&amp;lt;/code&amp;gt; game state description above which leads to state 11 which is &amp;lt;code&amp;gt;nextPlayer&amp;lt;/code&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
To make the statistics work, we have to initialize them in &amp;lt;code&amp;gt;stats.json&amp;lt;/code&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
  &amp;quot;player&amp;quot;: {&lt;br /&gt;
    &amp;quot;discPlayedOnCorner&amp;quot;: {&lt;br /&gt;
      &amp;quot;id&amp;quot;: 10,&lt;br /&gt;
      &amp;quot;name&amp;quot;: &amp;quot;Discs played on a corner&amp;quot;,&lt;br /&gt;
      &amp;quot;type&amp;quot;: &amp;quot;int&amp;quot;&lt;br /&gt;
    },&lt;br /&gt;
    &amp;quot;discPlayedOnBorder&amp;quot;: {&lt;br /&gt;
      &amp;quot;id&amp;quot;: 11,&lt;br /&gt;
      &amp;quot;name&amp;quot;: &amp;quot;Discs played on a border&amp;quot;,&lt;br /&gt;
      &amp;quot;type&amp;quot;: &amp;quot;int&amp;quot;&lt;br /&gt;
    },&lt;br /&gt;
    &amp;quot;discPlayedOnCenter&amp;quot;: {&lt;br /&gt;
      &amp;quot;id&amp;quot;: 12,&lt;br /&gt;
      &amp;quot;name&amp;quot;: &amp;quot;Discs played on board center part&amp;quot;,&lt;br /&gt;
      &amp;quot;type&amp;quot;: &amp;quot;int&amp;quot;&lt;br /&gt;
    },&lt;br /&gt;
    &amp;quot;turnedOver&amp;quot;: {&lt;br /&gt;
      &amp;quot;id&amp;quot;: 13,&lt;br /&gt;
      &amp;quot;name&amp;quot;: &amp;quot;Number of discs turned over&amp;quot;,&lt;br /&gt;
      &amp;quot;type&amp;quot;: &amp;quot;int&amp;quot;&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
A last thing to do on the server side is to activate the next player when we enter the &amp;lt;code&amp;gt;nextPlayer&amp;lt;/code&amp;gt; game state (in the &amp;lt;code&amp;gt;reversi.game.php&amp;lt;/code&amp;gt; file, under &amp;quot;Game state reactions&amp;quot;):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    function stNextPlayer(): void&lt;br /&gt;
    {&lt;br /&gt;
        // Active next player&lt;br /&gt;
        $player_id = intval($this-&amp;gt;activeNextPlayer());&lt;br /&gt;
&lt;br /&gt;
        // Check if both player has at least 1 discs, and if there are free squares to play&lt;br /&gt;
        $player_to_discs = $this-&amp;gt;getCollectionFromDb( &amp;quot;SELECT board_player, COUNT( board_x )&lt;br /&gt;
                                                       FROM board&lt;br /&gt;
                                                       GROUP BY board_player&amp;quot;, true );&lt;br /&gt;
&lt;br /&gt;
        if( ! isset( $player_to_discs[ null ] ) )&lt;br /&gt;
        {&lt;br /&gt;
            // Index 0 has not been set =&amp;gt; there&#039;s no more free place on the board !&lt;br /&gt;
            // =&amp;gt; end of the game&lt;br /&gt;
            $this-&amp;gt;gamestate-&amp;gt;nextState( &#039;endGame&#039; );&lt;br /&gt;
            return ;&lt;br /&gt;
        }&lt;br /&gt;
        else if( ! isset( $player_to_discs[ $player_id ] ) )&lt;br /&gt;
        {&lt;br /&gt;
            // Active player has no more disc on the board =&amp;gt; he looses immediately&lt;br /&gt;
            $this-&amp;gt;gamestate-&amp;gt;nextState( &#039;endGame&#039; );&lt;br /&gt;
            return ;&lt;br /&gt;
        }&lt;br /&gt;
        &lt;br /&gt;
        // Can this player play?&lt;br /&gt;
&lt;br /&gt;
        $possibleMoves = $this-&amp;gt;getPossibleMoves( $player_id );&lt;br /&gt;
        if( count( $possibleMoves ) == 0 )&lt;br /&gt;
        {&lt;br /&gt;
&lt;br /&gt;
            // This player can&#039;t play&lt;br /&gt;
            // Can his opponent play ?&lt;br /&gt;
            $opponent_id = (int)$this-&amp;gt;getUniqueValueFromDb( &amp;quot;SELECT player_id FROM player WHERE player_id!=&#039;$player_id&#039; &amp;quot; );&lt;br /&gt;
            if( count( $this-&amp;gt;getPossibleMoves( $opponent_id ) ) == 0 )&lt;br /&gt;
            {&lt;br /&gt;
                // Nobody can move =&amp;gt; end of the game&lt;br /&gt;
                $this-&amp;gt;gamestate-&amp;gt;nextState( &#039;endGame&#039; );&lt;br /&gt;
            }&lt;br /&gt;
            else&lt;br /&gt;
            {            &lt;br /&gt;
                // =&amp;gt; pass his turn&lt;br /&gt;
                $this-&amp;gt;gamestate-&amp;gt;nextState( &#039;cantPlay&#039; );&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
        else&lt;br /&gt;
        {&lt;br /&gt;
            // This player can play. Give him some extra time&lt;br /&gt;
            $this-&amp;gt;giveExtraTime( $player_id );&lt;br /&gt;
            $this-&amp;gt;gamestate-&amp;gt;nextState( &#039;nextTurn&#039; );&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Now, when we play a token, the rules are checked and the token appears in the database.&lt;br /&gt;
&lt;br /&gt;
[[File:reversi9.jpg]]&lt;br /&gt;
&lt;br /&gt;
Of course, as we don&#039;t manage notifications on client side, we need to press F5 after each move to see the changes on the board.&lt;br /&gt;
&lt;br /&gt;
== Make the move appear automatically ==&lt;br /&gt;
&lt;br /&gt;
Now, what we have to do is process the notifications sent by the server and make the move appear on the interface.&lt;br /&gt;
&lt;br /&gt;
In our &amp;lt;code&amp;gt;setupNotifications&amp;lt;/code&amp;gt; method in &amp;lt;code&amp;gt;reversi.js&amp;lt;/code&amp;gt;, we register 2 methods for the 2 notifications we created at the previous step (&amp;lt;code&amp;gt;playDisc&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;turnOverDiscs&amp;lt;/code&amp;gt;):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
            const notifs = [&lt;br /&gt;
                [&#039;playDisc&#039;, 500],&lt;br /&gt;
                [&#039;turnOverDiscs&#039;, 1500],&lt;br /&gt;
                [&#039;newScores&#039;, 1],&lt;br /&gt;
            ];&lt;br /&gt;
    &lt;br /&gt;
            notifs.forEach((notif) =&amp;gt; {&lt;br /&gt;
                dojo.subscribe(notif[0], this, `notif_${notif[0]}`);&lt;br /&gt;
                this.notifqueue.setSynchronous(notif[0], notif[1]);&lt;br /&gt;
            });&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We will associate each of our 3 notifications with a method prefixed with &amp;lt;code&amp;gt;notif_&amp;lt;/code&amp;gt;. We also define these notifications as &amp;quot;synchronous&amp;quot;, with a duration in millisecond. It tells the user interface to wait some time after executing the notification, to let the animation end before starting the next notification. In our specific case, the animation will be the following:&lt;br /&gt;
* Make a disc slide from the player panel to its place on the board&lt;br /&gt;
* (wait 500ms)&lt;br /&gt;
* Make all turned over discs blink (and of course turned them over)&lt;br /&gt;
* (wait 1500ms)&lt;br /&gt;
* Update the player scores&lt;br /&gt;
* (no real delay on this one)&lt;br /&gt;
&lt;br /&gt;
The second part of the code is a generic thing to automatically bind the notifs we configured to the &amp;lt;code&amp;gt;notif_&amp;lt;notifName&amp;gt;&amp;lt;/code&amp;gt; functions we are about to create.&lt;br /&gt;
&lt;br /&gt;
Let&#039;s have a look now on the &amp;lt;code&amp;gt;playDisc&amp;lt;/code&amp;gt; notification handler method:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
notif_playDisc: function( notif )&lt;br /&gt;
{&lt;br /&gt;
    // Remove current possible moves (makes the board more clear)&lt;br /&gt;
    document.querySelectorAll(&#039;.possibleMove&#039;).forEach(div =&amp;gt; div.classList.remove(&#039;possibleMove&#039;));&lt;br /&gt;
&lt;br /&gt;
    this.addDiscOnBoard( notif.args.x, notif.args.y, notif.args.player_id );&lt;br /&gt;
},&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
No surprise here, we re-used some existing stuff to:&lt;br /&gt;
* Remove the highlighted squares.&lt;br /&gt;
* Add a new disc on board, coming from player panel.&lt;br /&gt;
&lt;br /&gt;
Now, here&#039;s the method that handles the &amp;lt;code&amp;gt;turnOverDiscs&amp;lt;/code&amp;gt; notification:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
notif_turnOverDiscs: function( notif )&lt;br /&gt;
{&lt;br /&gt;
    // Get the color of the player who is returning the discs&lt;br /&gt;
    var targetColor = this.gamedatas.players[ notif.args.player_id ].color;&lt;br /&gt;
&lt;br /&gt;
    // Made these discs blinking and set them to the specified color&lt;br /&gt;
    for( var i in notif.args.turnedOver )&lt;br /&gt;
    {&lt;br /&gt;
        var disc = notif.args.turnedOver[ i ];&lt;br /&gt;
        &lt;br /&gt;
        // Make the disc blink 2 times&lt;br /&gt;
        var anim = dojo.fx.chain( [&lt;br /&gt;
            dojo.fadeOut( { node: &#039;disc_&#039;+disc.x+&#039;&#039;+disc.y } ),&lt;br /&gt;
            dojo.fadeIn( { node: &#039;disc_&#039;+disc.x+&#039;&#039;+disc.y } ),&lt;br /&gt;
            dojo.fadeOut( { &lt;br /&gt;
                            node: &#039;disc_&#039;+disc.x+&#039;&#039;+disc.y,&lt;br /&gt;
                            onEnd: node =&amp;gt; $(node).dataset.color = targetColor,&lt;br /&gt;
                            } ),&lt;br /&gt;
            dojo.fadeIn( { node: &#039;disc_&#039;+disc.x+&#039;&#039;+disc.y  } )&lt;br /&gt;
                            &lt;br /&gt;
        ] ); // end of dojo.fx.chain&lt;br /&gt;
&lt;br /&gt;
        // ... and launch the animation&lt;br /&gt;
        anim.play();                &lt;br /&gt;
    }&lt;br /&gt;
},&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The list of the discs to be turned over has been made available by our server side code in &amp;lt;code&amp;gt;notif.args.turnedOver&amp;lt;/code&amp;gt; (see previous paragraph). We loop through all these discs, and create a complex animation using &amp;lt;code&amp;gt;dojo.Animation&amp;lt;/code&amp;gt; for each of them. The complete documentation on dojo animations [http://dojotoolkit.org/documentation/tutorials/1.6/animation/ can be found here].&lt;br /&gt;
&lt;br /&gt;
In few words: we create a chain of 4 animations to make the disc fade out, fade in, fade out again, and fade in again. At the end of the second fade out, we change the color of the disc. Finally, we launch the animation with &amp;lt;code&amp;gt;play()&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
And Also the notification to update the scores:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
notif_newScores: function( notif )&lt;br /&gt;
        {&lt;br /&gt;
            for( var player_id in notif.args.scores )&lt;br /&gt;
            {&lt;br /&gt;
                var newScore = notif.args.scores[ player_id ];&lt;br /&gt;
                this.scoreCtrl[ player_id ].toValue( newScore );&lt;br /&gt;
            }&lt;br /&gt;
        },&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Category:Studio]]&lt;/div&gt;</summary>
		<author><name>Sguzzer Gunayer</name></author>
	</entry>
</feed>