<?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=Tisaac</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=Tisaac"/>
	<link rel="alternate" type="text/html" href="https://en.doc.boardgamearena.com/Special:Contributions/Tisaac"/>
	<updated>2026-10-20T21:38:35Z</updated>
	<subtitle>User contributions</subtitle>
	<generator>MediaWiki 1.39.0</generator>
	<entry>
		<id>https://en.doc.boardgamearena.com/index.php?title=Practical_debugging&amp;diff=20863</id>
		<title>Practical debugging</title>
		<link rel="alternate" type="text/html" href="https://en.doc.boardgamearena.com/index.php?title=Practical_debugging&amp;diff=20863"/>
		<updated>2024-04-23T09:29:37Z</updated>

		<summary type="html">&lt;p&gt;Tisaac: /* Fully automated version */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This page gives you practical tips to debug your game during development. Don&#039;t hesitate to share your difficulties with us so that we can improve this section.&lt;br /&gt;
&lt;br /&gt;
__TOC__&lt;br /&gt;
&lt;br /&gt;
== Tools ==&lt;br /&gt;
&lt;br /&gt;
To work on BGA Studio, we recommend that you use [http://www.google.com/chrome Google Chrome] as it&#039;s currently the fastest browser for the BGA platform, and it&#039;s available for all OSes.&lt;br /&gt;
&lt;br /&gt;
Another reason to use Chrome is that it embeds all the tools you need to work on BGA Studio. You can see them by pressing &amp;quot;F12&amp;quot; or from the menu (&amp;quot;Tools &amp;gt; Development tools&amp;quot;).&lt;br /&gt;
&lt;br /&gt;
A good practice is to use a second browser to develop the game, in order to verify that your game is working fine on this browser too.&lt;br /&gt;
&lt;br /&gt;
To debug with Firefox browser, we advise you to use these 2 extensions:&lt;br /&gt;
* [https://addons.mozilla.org/firefox/addon/firebug/ Firebug]&lt;br /&gt;
* [https://addons.mozilla.org/firefox/addon/web-developer/ Web developer]&lt;br /&gt;
&lt;br /&gt;
To debug with other browsers (IE, Edge, Opera), we advise you to use one of the most recent versions. Latest versions of the browser will likely have better development tools than the previous ones...&lt;br /&gt;
&lt;br /&gt;
== General tip for debugging ==&lt;br /&gt;
&lt;br /&gt;
=== Save &amp;amp; Restore ===&lt;br /&gt;
&lt;br /&gt;
In general for debugging, think of using the &#039;[[Tools_and_tips_of_BGA_Studio#Save_.26_restore_state|save &amp;amp; restore]] state&#039; functionality. It enables you to save the state of your game just before the issue you are investigating, then come back to that point with one click as many times as needed to understand what is going wrong.&lt;br /&gt;
&lt;br /&gt;
You can save up to 3 different states.&lt;br /&gt;
&lt;br /&gt;
=== Refresh ===&lt;br /&gt;
&lt;br /&gt;
If something does not seems to work properly even you &amp;quot;fixed it&amp;quot;, it may be refresh issue. Not all files born equal. Some require a lot more steps to get into the game.&lt;br /&gt;
&lt;br /&gt;
See https://en.doc.boardgamearena.com/Studio_file_reference for information on how to &amp;quot;refresh&amp;quot; each files.&lt;br /&gt;
&lt;br /&gt;
== Debugging my game when it cannot start ==&lt;br /&gt;
&lt;br /&gt;
If your game won&#039;t start because of an error, you are probably in one of these situations:&lt;br /&gt;
* There is a SQL error in your dbmodel.sql file.&lt;br /&gt;
* You have a syntax error in your PHP file.&lt;br /&gt;
* Your PHP &amp;quot;setupNewGame&amp;quot; generates exception&lt;br /&gt;
* You transition to new game state from the initial state which generates exception (or state is misconfigured)&lt;br /&gt;
* You transition to player state from the initial state which has excpetion in arg* or action* method (or state is misconfigured)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
If the error is not explicitly displayed when you click on &amp;quot;Express start&amp;quot;, you should check the &amp;quot;Gameserver error log&amp;quot; as per [[Studio logs]].&lt;br /&gt;
However errors and logs generated by setupNewGame not always (almost never) there, so see Debug setupNewGame session.&lt;br /&gt;
More cases of why game can&#039;t start are described on the [[Troubleshooting]] page.&lt;br /&gt;
&lt;br /&gt;
== Debugging an issue with the waiting screen ==&lt;br /&gt;
&lt;br /&gt;
BGA displays a waiting screen during a few seconds inviting free players to become premium when they are playing a lot.&lt;br /&gt;
&lt;br /&gt;
This waiting screen should not in principle impact your game, but in some cases it might.&lt;br /&gt;
&lt;br /&gt;
To test the waiting screen on the studio, you can set the desired duration by adding the get parameter studioLockingDuration with the number of seconds for the lock screen to be displayed. For example to have a 10 seconds waiting screen when you launch a game on the studio:&lt;br /&gt;
https://studio.boardgamearena.com?studioLockingDuration=10&lt;br /&gt;
&lt;br /&gt;
Then you can just set it back to zero in the same way with https://studio.boardgamearena.com?studioLockingDuration=0 (or restart your browser to clear the session value).&lt;br /&gt;
&lt;br /&gt;
== Debugging my PHP game logic (or my view) ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Add traces to your code ===&lt;br /&gt;
&lt;br /&gt;
You can use the following functions in your game to add server side logging:&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;$this-&amp;gt;dump( &#039;name_of_variable&#039;, $variable );&#039;&#039;&#039;  // dump variable, like var_dump but in the log debug level logging, goes to [[Studio_logs|BGA request&amp;amp;SQL logs]]&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;$this-&amp;gt;debug( $message );&#039;&#039;&#039;  // debug level logging, goes to [[Studio_logs|BGA request&amp;amp;SQL logs]]&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;$this-&amp;gt;trace( $message );&#039;&#039;&#039;  // info level logging, goes to [[Studio_logs|BGA request&amp;amp;SQL logs]]&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;$this-&amp;gt;warn( $message );&#039;&#039;&#039;   // warning level logging, goes to [[Studio_logs#BGA_unexpected_exceptions_logs|BGA unexpected exceptions log]]&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;$this-&amp;gt;error( $message );&#039;&#039;&#039;  // error level logging, goes to [[Studio_logs#BGA_unexpected_exceptions_logs|BGA unexpected exceptions log]]&lt;br /&gt;
&lt;br /&gt;
Check [[Studio logs]] for more details on how to access your logs.&lt;br /&gt;
&lt;br /&gt;
This can be useful when you need to follow the flow of your code and not just stop it to see how it goes at some point.&lt;br /&gt;
&lt;br /&gt;
Only the error log level will appear in production. This level should be used only for critical problems. &lt;br /&gt;
Other levels will show only in the development environment and can be used as you see fit.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;WARNING&#039;&#039;&#039;: tracing does not work in constructor, setupNewGame and game states immediately following starting state (not sure why). Use other method described below in this case (seciton &amp;quot;Debugging setupNewGame&amp;quot;).&lt;br /&gt;
&lt;br /&gt;
=== Call php functions from chat ===&lt;br /&gt;
&lt;br /&gt;
This is best feature ever, you can call individual function in your game.php from chat window, see details&lt;br /&gt;
at https://en.doc.boardgamearena.com/Tools_and_tips_of_BGA_Studio#Run_PHP_functions_from_the_chat&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Dump data and die ===&lt;br /&gt;
First, make sure you can reproduce the needed game situation with one click.  Use Save (&amp;quot;[[Tools_and_tips_of_BGA_Studio#Save_.26_restore_state|save &amp;amp; restore]]&amp;quot;) function before doing some &amp;quot;test actions&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
If you want to see what data looks like on some path you can simply throw this in exception, i.e.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$value = var_export($my_var, true);&lt;br /&gt;
throw new BgaUserException(&#039;I am here: &#039;.$value);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Alternately use json instead of php formaing:&lt;br /&gt;
    $value = json_encode($my_var, JSON_PRETTY_PRINT);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Another possibility for this is to place a &#039;&#039;&#039;die(&#039;ok&#039;)&#039;&#039;&#039; and &#039;&#039;&#039;var_dump(...)&#039;&#039;&#039; functions&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 echo &amp;quot;&amp;lt;pre&amp;gt;&amp;quot;;&lt;br /&gt;
 var_dump( $my_variable );&lt;br /&gt;
 echo &amp;quot;&amp;amp;lt;/pre&amp;gt;&amp;quot;;&lt;br /&gt;
 die(&#039;ok&#039;);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Note: since this text will be returned back to client it will usually choke on this, but you can actually see it better if you wrap it some html (hence the &amp;amp;lt;pre&amp;gt; tag)&lt;br /&gt;
&lt;br /&gt;
=== Debug at home ===&lt;br /&gt;
&lt;br /&gt;
If you develop some complex logic it is better sometimes to stub all external calls and debug it locally using command line or IDE debugger for php.&lt;br /&gt;
You can get some basic stubs here https://github.com/elaskavaia/bga-sharedcode/raw/master/misc/module/table/table.game.php&lt;br /&gt;
&lt;br /&gt;
To run php locally you need to wrap it into test or something, see example https://en.doc.boardgamearena.com/BGA_Studio_Cookbook#Creating_a_test_class_to_run_PHP_locally&lt;br /&gt;
&lt;br /&gt;
=== Debugging setupNewGame ===&lt;br /&gt;
&lt;br /&gt;
This is separate section because tracing method do not work in this function.&lt;br /&gt;
Recommended way to debug it &lt;br /&gt;
* leave  setupNewGame exactly as in template (inlcuding setting up player table and activating first player), and add a single call at the end&lt;br /&gt;
  $this-&amp;gt;initMyTables();&lt;br /&gt;
This will be your own function which you will be changing, so you don&#039;t touch setupNewGame anymore.&lt;br /&gt;
&lt;br /&gt;
Remember that this function cannot send notification or query active or current player. If you need to get player data use $this-&amp;gt;loadPlayersBasicInfos().&lt;br /&gt;
&lt;br /&gt;
    function initMyTables() {&lt;br /&gt;
        try {&lt;br /&gt;
           $players = $this-&amp;gt;loadPlayersBasicInfos();&lt;br /&gt;
          // ... code the function&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;
&lt;br /&gt;
Create a code for this function, and if it does not work run it from the chat window of the just created game (i.e. &#039;initMyTables()&#039; without quotes). That way you can see debug output!&lt;br /&gt;
The only trick is you have to clear all your tables in the begging so when you run it multiple times your db does not puke.&lt;br /&gt;
If your game does not start at all - do not even call it from setupNewGame, comment it out and only call from chat window until it works.&lt;br /&gt;
Don&#039;t forget you can also look at tables in db using php-admin tool (link at the bottom of the game table in studio).&lt;br /&gt;
&lt;br /&gt;
The same problem exists if you game state immediately follow starting state (problem of debugging it without the logs), in this case create a dummy player state in which player just press OK that will transition&lt;br /&gt;
to you game state, after you done debugging it remove the state and shortcut the transition to your game state.&lt;br /&gt;
&lt;br /&gt;
Instead of calling initMyTables directly you can call helper function instead from chat window which will also reset the client, i.e.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    function debug_initMyTables() {&lt;br /&gt;
        $this-&amp;gt;deleteAllTables(); // this suppose to delete/reset all data - you have to implement this function&lt;br /&gt;
        $this-&amp;gt;initMyTables();&lt;br /&gt;
        $newGameDatas = $this-&amp;gt;getAllTableDatas(); // this is framework function&lt;br /&gt;
        $this-&amp;gt;notifyPlayer($this-&amp;gt;getActivePlayerId(), &#039;resetInterfaceWithAllDatas&#039;, &#039;&#039;, $newGameDatas); // this is notification to reset all data &lt;br /&gt;
        $this-&amp;gt;notifyAllPlayers(&amp;quot;message&amp;quot;,&#039;setup called&#039;,[]);&lt;br /&gt;
    }&lt;br /&gt;
&amp;lt;/pre&amp;gt;HINT: This is a great suggestion. If you make any simple mistake in any code in setupNewGame, you may see &amp;quot;BGA Service Exception&amp;quot; instead of anything very useful, since setupNewGame failed. For example, even sending a bad SQL string to $this-&amp;gt;dbQuery() will generate this error. Very hard to debug!&lt;br /&gt;
&lt;br /&gt;
=== Debugging endOfGame ===&lt;br /&gt;
&lt;br /&gt;
Debugging end of game is hard if game ends! Make sure it does not end, then you can restore to previous state using saved states.&lt;br /&gt;
In php file:&lt;br /&gt;
&lt;br /&gt;
    $this-&amp;gt;processEndOfGame();&lt;br /&gt;
    if ($this-&amp;gt;getBgaEnvironment() == &#039;studio&#039;)&lt;br /&gt;
       $this-&amp;gt;gamestate-&amp;gt;nextState(&#039;debuglast&#039;); // debug end&lt;br /&gt;
    else&lt;br /&gt;
       $this-&amp;gt;gamestate-&amp;gt;nextState(&#039;last&#039;); // real end&lt;br /&gt;
&lt;br /&gt;
You have to add a special user state in states.inc.php file (note: this snippet uses php constants instead of state numbers)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        STATE_GAME_TURN_NEXT_PLAYER =&amp;gt; array( // normal 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; &#039;&#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; array(&lt;br /&gt;
                        &amp;quot;next&amp;quot; =&amp;gt; STATE_PLAYER_TURN_ACTION,&lt;br /&gt;
                        &amp;quot;loopback&amp;quot; =&amp;gt;  STATE_GAME_TURN_NEXT_PLAYER,&lt;br /&gt;
                        &amp;quot;last&amp;quot; =&amp;gt; STATE_END_GAME,&lt;br /&gt;
                        &amp;quot;debuglast&amp;quot; =&amp;gt; STATE_PLAYER_GAME_END // for debugging on studio&lt;br /&gt;
                        ), &lt;br /&gt;
        ),&lt;br /&gt;
        // for debugging end of game&lt;br /&gt;
        STATE_PLAYER_GAME_END =&amp;gt; array(&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;Game Over&#039;),&lt;br /&gt;
                &amp;quot;descriptionmyturn&amp;quot; =&amp;gt; clienttranslate(&#039;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_playerTurnAction&amp;quot;,&lt;br /&gt;
                &amp;quot;possibleactions&amp;quot; =&amp;gt; array( &amp;quot;end&amp;quot;),&lt;br /&gt;
                &amp;quot;transitions&amp;quot; =&amp;gt;&lt;br /&gt;
                array(&lt;br /&gt;
                        &amp;quot;next&amp;quot; =&amp;gt; STATE_END_GAME,&lt;br /&gt;
                        &amp;quot;loopback&amp;quot;=&amp;gt; STATE_PLAYER_GAME_END)&lt;br /&gt;
        ),&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Debugging my HTML/CSS layout ==&lt;br /&gt;
&lt;br /&gt;
Example situations&lt;br /&gt;
&lt;br /&gt;
* Why doesn&#039;t my game element show up in the interface?&lt;br /&gt;
* Why hasn&#039;t my CSS property been applied to this element?&lt;br /&gt;
* Why is this game element displayed at this position?&lt;br /&gt;
&lt;br /&gt;
A useful tip when an element does not show up in the interface is to give it a red background:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#my_element {&lt;br /&gt;
  ... some CSS definitions ...&lt;br /&gt;
  background-color: red;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This way, you know if the element is not visible because of some CSS property or because of something else.&lt;br /&gt;
&lt;br /&gt;
Another tip: sometimes, changing a CSS property has no visible effect on your interface. In that case, add a &amp;quot;display:none&amp;quot; property. If your element does not disappear, the bug probably comes from your CSS selector and not from your CSS property.&lt;br /&gt;
&lt;br /&gt;
Using Chrome &amp;quot;Elements&amp;quot; tab (the first one), you can:&lt;br /&gt;
* See the CURRENT HTML of your page. Remember that the classical &amp;quot;show page source&amp;quot; is inefficient with BGA as you are modifying the page source with your Javascript code.&lt;br /&gt;
* Using the &amp;quot;magnifying glass&amp;quot;, you can click on any part of your game interface and check its HTML code and associated CSS styles.&lt;br /&gt;
* You can even modify directly some CSS properties and see how it looks immediately in the game interface.&lt;br /&gt;
&lt;br /&gt;
When changing css you have to force reload (Ctrl+R). But it also reloads all images which is long, if you want it faster you can click the Reload CSS button.&lt;br /&gt;
=== Debugging Toolips CSS/Layout ===&lt;br /&gt;
&lt;br /&gt;
To inspect tooltip you need to pin it so it does not disappear.&lt;br /&gt;
* Chrome tools:&lt;br /&gt;
** Open dev tools and switch to Source tab to engage with debugger&lt;br /&gt;
** Hover over you element until tooltip showing&lt;br /&gt;
** Press F8 - that stops the JS, so tooltip should freeze&lt;br /&gt;
** Now you can go to Elements tab and find your tooltip at the botton in dijitTooltip div&lt;br /&gt;
** Don&#039;t forget to resume it again to continue (F8 again or resume button)&lt;br /&gt;
* Other method: Open the console (dev tools) large enough window, hover to make the tooltip appear and alt + tab to focus the console that will cover the tooltip. That way the onmouseout will never be triggered.&lt;br /&gt;
&lt;br /&gt;
=== Debugging my Javascript game interface logic ===&lt;br /&gt;
&lt;br /&gt;
To debug javascript you just use embedded browser debugger, usually found in Source tab of dev tools (F12)&lt;br /&gt;
&lt;br /&gt;
Modern browsers also allow you to put breakpoints in your js code. It is in source tab, but its a bit difficult to find (your code that is), see picture below on how to insert breakpoints.&lt;br /&gt;
&lt;br /&gt;
You can do this by pressing Ctrl + B when your cursor is on the line where you want to set the breakpoint, or by clicking just to the left of the line number. One thing to be aware of is that refreshing via F5 removes set breakpoints, due to some cache busting values added to the URL. This can be remedied by adding this line to the end of your javascript source file, which enables the proper source mapping:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;//# sourceURL=myjsfile.js&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:Bga-debug.jpg]]&lt;br /&gt;
&lt;br /&gt;
The easier method is to add breakpoint directly into your code and reload.&lt;br /&gt;
&lt;br /&gt;
In Chrome, to add a breakpoint: add a line to your .js file&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;debugger; &amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Refresh the page F5, and make sure you have the Developer tools window open, press F12. &lt;br /&gt;
When the break-point is hit you can then step through your code and visualise variables, etc.&lt;br /&gt;
&lt;br /&gt;
=== Do complex things on the PHP side ===&lt;br /&gt;
&lt;br /&gt;
The most frequent case is the following: you want to compute possible moves in a game situation. Doing it in Javascript is a nightmare. Do it in PHP, and transfer the results to your client interface using the &amp;quot;args&amp;quot; game state property.&lt;br /&gt;
&lt;br /&gt;
Note: See the Reversi tutorial for an example.&lt;br /&gt;
&lt;br /&gt;
=== Add traces in your code ===&lt;br /&gt;
&lt;br /&gt;
You can use the following:&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;console.log( variable_to_inspect )&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
It will give you the object structure of the variable in the Javascript console, without blocking the execution.&lt;br /&gt;
&lt;br /&gt;
It&#039;s often a good idea to precede this call with a console.log( &#039;### HERE ###&#039; ); to find more easily the appropriate line in the console log.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;alert( variable_to_inspect )&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
It will popup what you wish and pause the execution until you click ok.&lt;br /&gt;
&lt;br /&gt;
This won&#039;t be useful for complex structures; only native types will be plainly displayed. But this is sometimes useful just with messages to make sure which way the execution goes.&lt;br /&gt;
&lt;br /&gt;
== Online format checkers ==&lt;br /&gt;
Copy and paste code for a quick code sanity check like the right number of brackets.&lt;br /&gt;
&lt;br /&gt;
PHP: [https://phpcodechecker.com/ https://phpcodechecker.com/]&lt;br /&gt;
&lt;br /&gt;
JS:  [http://esprima.org/demo/validate.html http://esprima.org/demo/validate.html]&lt;br /&gt;
&lt;br /&gt;
Checks for proper attributes values and browser&#039;s compatibility&lt;br /&gt;
&lt;br /&gt;
CSS: http://jigsaw.w3.org/css-validator/&lt;br /&gt;
&lt;br /&gt;
== Some frequent errors ==&lt;br /&gt;
&lt;br /&gt;
See [[Troubleshooting]].&lt;br /&gt;
&lt;br /&gt;
== Get the database matching a bug report ==&lt;br /&gt;
&lt;br /&gt;
When a player creates a bug report in production, a snapshot of the game database is taken. You can get access to this snapshot from the studio by following the steps below:&lt;br /&gt;
* Create a table in the studio with the same game and number of players as the table for which the report has been written. Launch this table.&lt;br /&gt;
* Open another tab on the studio and go to &amp;quot;Manage game&amp;quot; page for your project (you have to be admin for this project)&lt;br /&gt;
* In the &amp;quot;Errors in production&amp;quot; section, fill up the fields &amp;quot;Bug report ID&amp;quot; (this is the ID of the bug report in production) and &amp;quot;Studio table ID&amp;quot; (this is the ID of the table you created above) then click the &amp;quot;⇨ Load bug report state into this table save slot #1&amp;quot; button.&lt;br /&gt;
* If the snapshot is correctly retrieved, you see a &amp;quot;Done!&amp;quot; message.&lt;br /&gt;
* Go back to the tab with your studio table and click &amp;quot;Load 1&amp;quot;.&lt;br /&gt;
* The page refreshes automatically and is broken. This is normal, as the player ids from the snapshot are the player ids of the production, not those of the studio. We&#039;ll need to update them.&lt;br /&gt;
** &#039;&#039;&#039;Important note:&#039;&#039;&#039; if you see a &amp;quot;Done!&amp;quot; message but clicking &amp;quot;Load 1&amp;quot; doesn&#039;t bring any change, it&#039;s that the snapshot is unfortunately not available (most likely because the bug report was declared too long after the game ended and the database had already been garbage collected to reclaim space).&lt;br /&gt;
* Click on the &amp;quot;Go to game database&amp;quot; button&lt;br /&gt;
* For each table using player_ids, you&#039;ll need to update the player_ids from the production to use the player_ids from the studio. You can see the player_ids from the table page before entering the game by hovering over the player names.&lt;br /&gt;
* Tables to update:&lt;br /&gt;
** player&lt;br /&gt;
** global (value with ID 2 is the active player)&lt;br /&gt;
** stats&lt;br /&gt;
** tables specific to your schema that use player_ids&lt;br /&gt;
* If your changes to player_ids are not taken into account, it may be a cache problem: use the &amp;quot;Clear PHP cache&amp;quot; button on your &amp;quot;Manage game&amp;quot; page.&lt;br /&gt;
* Then you should be able to play with the same state of the game as when the report was created in production.&lt;br /&gt;
* If the game has ended, you can place it again in the game state you want to debug by setting the value with ID 1 in the global table to the appropriate state value, and the value with ID 2 to the player you want active).&lt;br /&gt;
*&lt;br /&gt;
* Below is an example php function you may want to make. You can call this function from the chat window: LoadDebug()  &lt;br /&gt;
* change instances of 2308257, and 2308258 to you own BGA Studio logins YourLogin0 and YourLogin1&lt;br /&gt;
* change $id0 and $id1 to the player_ids from the table you want to debug, and have recently imported.&lt;br /&gt;
* Before you load Slot1, open a second tab with the table, because after loading the slot, that tab will be unusable. In the second tab you can call LoadDebug() in the chat window&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
	public function LoadDebug()&lt;br /&gt;
	{&lt;br /&gt;
		// These are the id&#039;s from the BGAtable I need to debug.&lt;br /&gt;
		// you can get them by running this query : SELECT JSON_ARRAYAGG(`player_id`) FROM `player`&lt;br /&gt;
		$ids = [&lt;br /&gt;
			86107517,&lt;br /&gt;
			86872172,&lt;br /&gt;
			85086097,&lt;br /&gt;
			84380410,&lt;br /&gt;
			11000525&lt;br /&gt;
		];&lt;br /&gt;
                // You can also get the ids automatically with $ids = array_map(fn($dbPlayer) =&amp;gt; intval($dbPlayer[&#039;player_id&#039;]), array_values($this-&amp;gt;getCollectionFromDb(&#039;select player_id from player order by player_no&#039;)));&lt;br /&gt;
&lt;br /&gt;
		// Id of the first player in BGA Studio&lt;br /&gt;
		$sid = 2296755;&lt;br /&gt;
		&lt;br /&gt;
		foreach ($ids as $id) {&lt;br /&gt;
			// basic tables&lt;br /&gt;
			$this-&amp;gt;DbQuery(&amp;quot;UPDATE player SET player_id=$sid WHERE player_id = $id&amp;quot; );&lt;br /&gt;
			$this-&amp;gt;DbQuery(&amp;quot;UPDATE global SET global_value=$sid WHERE global_value = $id&amp;quot; );&lt;br /&gt;
			$this-&amp;gt;DbQuery(&amp;quot;UPDATE stats SET stats_player_id=$sid WHERE stats_player_id = $id&amp;quot; );&lt;br /&gt;
&lt;br /&gt;
			// &#039;other&#039; game specific tables. example:&lt;br /&gt;
			// tables specific to your schema that use player_ids&lt;br /&gt;
			$this-&amp;gt;DbQuery(&amp;quot;UPDATE card SET card_location_arg=$sid WHERE card_location_arg = $id&amp;quot; );&lt;br /&gt;
			&lt;br /&gt;
			++$sid;&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Fully automated version===&lt;br /&gt;
Thanks to quietmint for [https://boardgamearena.com/forum/viewtopic.php?f=12&amp;amp;t=16454#p63167 coming up] with that!&lt;br /&gt;
(updated and working on 05/06/2922)&lt;br /&gt;
&lt;br /&gt;
CAREFUL: due to php8, the URL might be different depending whether you have php8 enabled or not on studio.&lt;br /&gt;
&lt;br /&gt;
If you use php8, make sure to update the 3rd URL below like this : https://studio.boardgamearena.com/2/$game/$game/...  (replace /1/ by /2/)&lt;br /&gt;
&lt;br /&gt;
; In ggg.php&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  /*&lt;br /&gt;
   * loadBug: in studio, type loadBug(20762) into the table chat to load a bug report from production&lt;br /&gt;
   * client side JavaScript will fetch each URL below in sequence, then refresh the page&lt;br /&gt;
   */&lt;br /&gt;
  public function loadBug($reportId)&lt;br /&gt;
  {&lt;br /&gt;
    $db = explode(&#039;_&#039;, $this-&amp;gt;getUniqueValueFromDB(&amp;quot;SELECT SUBSTRING_INDEX(DATABASE(), &#039;_&#039;, -2)&amp;quot;));&lt;br /&gt;
    $game = $db[0];&lt;br /&gt;
    $tableId = $db[1];&lt;br /&gt;
    $this-&amp;gt;notifyAllPlayers(&#039;loadBug&#039;, &amp;quot;Trying to load &amp;lt;a href=&#039;https://boardgamearena.com/bug?id=$reportId&#039; target=&#039;_blank&#039;&amp;gt;bug report $reportId&amp;lt;/a&amp;gt;&amp;quot;, [&lt;br /&gt;
      &#039;urls&#039; =&amp;gt; [&lt;br /&gt;
        // Emulates &amp;quot;load bug report&amp;quot; in control panel&lt;br /&gt;
        &amp;quot;https://studio.boardgamearena.com/admin/studio/getSavedGameStateFromProduction.html?game=$game&amp;amp;report_id=$reportId&amp;amp;table_id=$tableId&amp;quot;,&lt;br /&gt;
        &lt;br /&gt;
        // Emulates &amp;quot;load 1&amp;quot; at this table&lt;br /&gt;
        &amp;quot;https://studio.boardgamearena.com/table/table/loadSaveState.html?table=$tableId&amp;amp;state=1&amp;quot;,&lt;br /&gt;
        &lt;br /&gt;
        // Calls the function below to update SQL&lt;br /&gt;
        &amp;quot;https://studio.boardgamearena.com/1/$game/$game/loadBugSQL.html?table=$tableId&amp;amp;report_id=$reportId&amp;quot;,&lt;br /&gt;
        &lt;br /&gt;
        // Emulates &amp;quot;clear PHP cache&amp;quot; in control panel&lt;br /&gt;
        // Needed at the end because BGA is caching player info&lt;br /&gt;
        &amp;quot;https://studio.boardgamearena.com/admin/studio/clearGameserverPhpCache.html?game=$game&amp;quot;,&lt;br /&gt;
      ]&lt;br /&gt;
    ]);&lt;br /&gt;
  }&lt;br /&gt;
  &lt;br /&gt;
  /*&lt;br /&gt;
   * loadBugSQL: in studio, this is one of the URLs triggered by loadBug() above&lt;br /&gt;
   */&lt;br /&gt;
  public function loadBugSQL($reportId)&lt;br /&gt;
  {&lt;br /&gt;
    $studioPlayer = $this-&amp;gt;getCurrentPlayerId();&lt;br /&gt;
    $players = $this-&amp;gt;getObjectListFromDb(&amp;quot;SELECT player_id FROM player&amp;quot;, true);&lt;br /&gt;
  &lt;br /&gt;
    // Change for your game&lt;br /&gt;
    // We are setting the current state to match the start of a player&#039;s turn if it&#039;s already game over&lt;br /&gt;
    $sql = [&lt;br /&gt;
      &amp;quot;UPDATE global SET global_value=2 WHERE global_id=1 AND global_value=99&amp;quot;&lt;br /&gt;
    ];&lt;br /&gt;
    foreach ($players as $pId) {&lt;br /&gt;
      // All games can keep this SQL&lt;br /&gt;
      $sql[] = &amp;quot;UPDATE player SET player_id=$studioPlayer WHERE player_id=$pId&amp;quot;;&lt;br /&gt;
      $sql[] = &amp;quot;UPDATE global SET global_value=$studioPlayer WHERE global_value=$pId&amp;quot;;&lt;br /&gt;
      $sql[] = &amp;quot;UPDATE stats SET stats_player_id=$studioPlayer WHERE stats_player_id=$pId&amp;quot;;&lt;br /&gt;
      $sql[] = &amp;quot;UPDATE gamelog SET gamelog_player=$studioPlayer WHERE gamelog_player=$pId&amp;quot;;&lt;br /&gt;
      $sql[] = &amp;quot;UPDATE gamelog SET gamelog_current_player=$studioPlayer WHERE gamelog_current_player=$pId&amp;quot;;&lt;br /&gt;
      $sql[] = &amp;quot;UPDATE gamelog SET gamelog_notification=REPLACE(gamelog_notification, $pId, $studioPlayer)&amp;quot;;&lt;br /&gt;
  &lt;br /&gt;
      // TODO Add game-specific SQL updates for the tables, everywhere players ids are used in your game &lt;br /&gt;
      $sql[] = &amp;quot;UPDATE deck SET card_location_arg=$studioPlayer WHERE card_location_arg=$pId&amp;quot;;&lt;br /&gt;
      $sql[] = &amp;quot;UPDATE card SET card_location_arg=$studioPlayer WHERE card_location_arg=$pId&amp;quot;;&lt;br /&gt;
      $sql[] = &amp;quot;UPDATE piece SET player_id=$studioPlayer WHERE player_id=$pId&amp;quot;;&lt;br /&gt;
      $sql[] = &amp;quot;UPDATE log SET player_id=$studioPlayer WHERE player_id=$pId&amp;quot;;&lt;br /&gt;
      $sql[] = &amp;quot;UPDATE log SET action_arg=REPLACE(action_arg, $pId, $studioPlayer)&amp;quot;;&lt;br /&gt;
  &lt;br /&gt;
      // This could be improved, it assumes you had sequential studio accounts before loading&lt;br /&gt;
      // e.g., quietmint0, quietmint1, quietmint2, etc. are at the table&lt;br /&gt;
      $studioPlayer++;&lt;br /&gt;
    }&lt;br /&gt;
    $msg = &amp;lt;nowiki&amp;gt;&amp;quot;&amp;lt;b&amp;gt;Loaded &amp;lt;a href=&#039;https://boardgamearena.com/bug?id=$reportId&#039; target=&#039;_blank&#039;&amp;gt;bug report $reportId&amp;lt;/a&amp;gt;&amp;lt;/b&amp;gt;&amp;lt;hr&amp;gt;&amp;lt;ul&amp;gt;&amp;lt;li&amp;gt;&amp;quot; . implode(&#039;;&amp;lt;/li&amp;gt;&amp;lt;li&amp;gt;&#039;, $sql) . &#039;;&amp;lt;/li&amp;gt;&amp;lt;/ul&amp;gt;&#039;;&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
    $this-&amp;gt;warn($msg);&lt;br /&gt;
    $this-&amp;gt;notifyAllPlayers(&#039;message&#039;, $msg, []);&lt;br /&gt;
  &lt;br /&gt;
    foreach ($sql as $q) {&lt;br /&gt;
      $this-&amp;gt;DbQuery($q);&lt;br /&gt;
    }&lt;br /&gt;
    $this-&amp;gt;reloadPlayersBasicInfos();&lt;br /&gt;
    $this-&amp;gt;gamestate-&amp;gt;reloadState();&lt;br /&gt;
  }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
; In ggg.action.php&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  public function loadBugSQL() {&lt;br /&gt;
    $this-&amp;gt;setAjaxMode(false);&lt;br /&gt;
    $reportId = (int) $this-&amp;gt;getArg(&#039;report_id&#039;, AT_int, true);&lt;br /&gt;
    $this-&amp;gt;game-&amp;gt;loadBugSQL($reportId);&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;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  // Load production bug report handler&lt;br /&gt;
  const self = this; // save the `this` context in a variable&lt;br /&gt;
  dojo.subscribe(&amp;quot;loadBug&amp;quot;, this, function loadBug(n) {&lt;br /&gt;
    function fetchNextUrl() {&lt;br /&gt;
      var url = n.args.urls.shift();&lt;br /&gt;
      console.log(&amp;quot;Fetching URL&amp;quot;, url, &amp;quot;...&amp;quot;);&lt;br /&gt;
      // all the calls have to be made with ajaxcall in order to add the csrf token, otherwise you&#039;ll get &amp;quot;Invalid session information for this action. Please try reloading the page or logging in again&amp;quot;&lt;br /&gt;
      self.ajaxcall(url,&lt;br /&gt;
      {&lt;br /&gt;
         lock: true,&lt;br /&gt;
      },&lt;br /&gt;
      self,&lt;br /&gt;
      function (success) {&lt;br /&gt;
        console.log(&amp;quot;=&amp;gt; Success &amp;quot;, success);&lt;br /&gt;
&lt;br /&gt;
        if (n.args.urls.length &amp;gt; 1) {&lt;br /&gt;
          fetchNextUrl();&lt;br /&gt;
        }&lt;br /&gt;
        else if (n.args.urls.length &amp;gt; 0) {&lt;br /&gt;
          //except the last one, clearing php cache&lt;br /&gt;
          url = n.args.urls.shift();&lt;br /&gt;
          dojo.xhrGet({&lt;br /&gt;
            url: url,&lt;br /&gt;
            headers: {&lt;br /&gt;
                &amp;quot;X-Request-Token&amp;quot;: bgaConfig.requestToken&lt;br /&gt;
            },&lt;br /&gt;
            load: function (success) {&lt;br /&gt;
              console.log(&amp;quot;Success for URL&amp;quot;, url, success);&lt;br /&gt;
              console.log(&amp;quot;Done, reloading page&amp;quot;);&lt;br /&gt;
              window.location.reload();&lt;br /&gt;
            },&lt;br /&gt;
            handleAs: &amp;quot;text&amp;quot;,&lt;br /&gt;
            error: function (error) {&lt;br /&gt;
              console.log(&amp;quot;Error while loading : &amp;quot;, error);&lt;br /&gt;
            }&lt;br /&gt;
          });&lt;br /&gt;
       }&lt;br /&gt;
     }&lt;br /&gt;
     ,&lt;br /&gt;
     function (error) {&lt;br /&gt;
       if (error)&lt;br /&gt;
          console.log(&amp;quot;=&amp;gt; Error &amp;quot;, error);&lt;br /&gt;
       }&lt;br /&gt;
     );&lt;br /&gt;
   }&lt;br /&gt;
  console.log(&amp;quot;Notif: load bug&amp;quot;, n.args);&lt;br /&gt;
  fetchNextUrl();&lt;br /&gt;
  });&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Studio environment ==&lt;br /&gt;
&lt;br /&gt;
Some developers have requested a method allowing to know which environment the module is running on. While in general, your code should be the same on all environments so that the validation process makes sense, this may allow for example to display some helpers for testing during development while being sure that they&#039;ll never show up outside of the studio.&lt;br /&gt;
&lt;br /&gt;
From your &amp;lt;gamename&amp;gt;.game.php file you can use:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;if ($this-&amp;gt;getBgaEnvironment() == &#039;studio&#039;) { ... }&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Or if needed from your &amp;lt;gamename&amp;gt;.view.php file:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;if ($this-&amp;gt;game-&amp;gt;getBgaEnvironment() == &#039;studio&#039;) { ... }&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Category:Studio]]&lt;/div&gt;</summary>
		<author><name>Tisaac</name></author>
	</entry>
	<entry>
		<id>https://en.doc.boardgamearena.com/index.php?title=BGA_Code_Sharing&amp;diff=12934</id>
		<title>BGA Code Sharing</title>
		<link rel="alternate" type="text/html" href="https://en.doc.boardgamearena.com/index.php?title=BGA_Code_Sharing&amp;diff=12934"/>
		<updated>2022-05-01T12:33:56Z</updated>

		<summary type="html">&lt;p&gt;Tisaac: /* Community shared components, pens, etc */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Studio_Framework_Navigation}}&lt;br /&gt;
&lt;br /&gt;
This page is for listing of externally hosted bga projects, tools and resources, as well as internal project&lt;br /&gt;
intended for sharing&lt;br /&gt;
&lt;br /&gt;
== Community shared components, pens, etc ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! NAME&lt;br /&gt;
! CODE LINK&lt;br /&gt;
! DESCRIPTION&lt;br /&gt;
|-&lt;br /&gt;
! colspan=&amp;quot;3&amp;quot; | Dice models and animation&lt;br /&gt;
|-&lt;br /&gt;
| Die: 4 sided &lt;br /&gt;
| https://codepen.io/mrkiffie/pen/doVZgW&lt;br /&gt;
| code pen&lt;br /&gt;
|-&lt;br /&gt;
| Die: 6 sided &lt;br /&gt;
| https://github.com/elaskavaia/bga-sharedcode&lt;br /&gt;
| Code can be found in project&lt;br /&gt;
|-&lt;br /&gt;
| Die: 12 sided (dodecahedron) &lt;br /&gt;
| https://codepen.io/VictoriaLa/pen/xxLLxOP&lt;br /&gt;
| Code pen&lt;br /&gt;
|- &lt;br /&gt;
| Die: 20 sided &lt;br /&gt;
| https://codepen.io/vicentemundim/details/cenIh&lt;br /&gt;
| Code pen&lt;br /&gt;
|-&lt;br /&gt;
! colspan=&amp;quot;3&amp;quot; | Moving object using CSS animation (mostly)&lt;br /&gt;
|-&lt;br /&gt;
| Phantom object move on oversurface &lt;br /&gt;
| https://codepen.io/VictoriaLa/pen/gORvdJo&lt;br /&gt;
| This technique creates clone of the object it moves it on another surface. It works well when parents that css transform applies such as scale and rotate&lt;br /&gt;
|-&lt;br /&gt;
| Move object directly using positioning &lt;br /&gt;
| https://codepen.io/VictoriaLa/pen/dyzgKVX&lt;br /&gt;
| This technique is modification of BGA framework method to allow mobile object not to have absolute position before or after the move (and uses css animation not dojo). Methods slideToObjectRelative, attachToNewObjectNoDestroy&lt;br /&gt;
|-&lt;br /&gt;
! colspan=&amp;quot;3&amp;quot; | Responsive layout for game boards&lt;br /&gt;
|-&lt;br /&gt;
|Flex Layout&lt;br /&gt;
|https://codepen.io/VictoriaLa/pen/XWjJJgG&lt;br /&gt;
|Example on how to create flexible layout just by using css&lt;br /&gt;
|-&lt;br /&gt;
! colspan=&amp;quot;3&amp;quot; | Algorithms&lt;br /&gt;
|-&lt;br /&gt;
|Hex grid&lt;br /&gt;
|tapestry,...&lt;br /&gt;
|&lt;br /&gt;
|-&lt;br /&gt;
|Shortest path on hex grid&lt;br /&gt;
|memoir 44&lt;br /&gt;
| Disjktra&lt;br /&gt;
|-&lt;br /&gt;
|Largest area on hex grid&lt;br /&gt;
|tapestry, ...&lt;br /&gt;
|&lt;br /&gt;
|-&lt;br /&gt;
|Largest area on square grid&lt;br /&gt;
|king domino, ...&lt;br /&gt;
|&lt;br /&gt;
|-&lt;br /&gt;
|Tetris pieces&lt;br /&gt;
|patchwork, ...&lt;br /&gt;
|Matrix manupations to rotate, flip and fit tetris pieces&lt;br /&gt;
|-&lt;br /&gt;
|Line of sights on hex grid&lt;br /&gt;
|memoir 44&lt;br /&gt;
|Find intersecting hexes on a line between two cells&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Projects hosted not in studio ==&lt;br /&gt;
&lt;br /&gt;
See the table a link and nickname of the developer on bga (same as used for dev forum), and short description. See [[Tools_and_tips_of_BGA_Studio#Version_Control]] for some suggestions on how and where to publish your code externally. Also see the [https://github.com/topics/boardgamearena boardgamearena] tag on github.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Important notice about artwork on BGA Open Source projects: original hi-resolution images from publishers must not be published on the repositories. In addition, it is better to specify that the images derivated from publishers artwork are copyrighted and cannot be licensed under a free license like Creative Commons.&lt;br /&gt;
&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! NON-GAME PROJECTS&lt;br /&gt;
! CODE LINK&lt;br /&gt;
! DEVELOPER&lt;br /&gt;
! COMMENT&lt;br /&gt;
|-&lt;br /&gt;
| Shared Code (not a game)&lt;br /&gt;
| https://github.com/elaskavaia/bga-sharedcode&lt;br /&gt;
| Victoria_La&lt;br /&gt;
| Examples of various game components and PHP stubs of framework code to make IDE happy&lt;br /&gt;
|-&lt;br /&gt;
| BoardGameArena Workbench (not a game)&lt;br /&gt;
| https://github.com/danielholmes/bga-workbench&lt;br /&gt;
| Daniel Holmes (dhau)&lt;br /&gt;
|-&lt;br /&gt;
! GAME&lt;br /&gt;
! CODE LINK&lt;br /&gt;
! DEVELOPER&lt;br /&gt;
! COMMENT&lt;br /&gt;
|-&lt;br /&gt;
| 99 (Trick-taking Card Game)&lt;br /&gt;
| https://github.com/ekelly/bga-ninetynine&lt;br /&gt;
| QuasarDukeDev&lt;br /&gt;
|-&lt;br /&gt;
| Assyria &lt;br /&gt;
| https://github.com/sebastien-prudhomme/bga-assyria&lt;br /&gt;
| daikinee &lt;br /&gt;
|-&lt;br /&gt;
| Aura&lt;br /&gt;
| https://github.com/micahstairs/bga-aura&lt;br /&gt;
| Micah Stairs (micahstairs)&lt;br /&gt;
|-&lt;br /&gt;
| Bandido &lt;br /&gt;
| https://github.com/opheliehb/BandidoBGA&lt;br /&gt;
| ophelopede &amp;amp; Harkle &lt;br /&gt;
|-&lt;br /&gt;
| The Battle for Hill 218&lt;br /&gt;
| https://github.com/danielholmes/battle-for-hill-218&lt;br /&gt;
| Daniel Holmes (dhau)&lt;br /&gt;
|-&lt;br /&gt;
| Bonbons&lt;br /&gt;
| https://github.com/AntonioSoler/bga-bonbons&lt;br /&gt;
| Morgalad &lt;br /&gt;
|-&lt;br /&gt;
| Coinche&lt;br /&gt;
| https://github.com/drasill/bga-coinche&lt;br /&gt;
| Draasill&lt;br /&gt;
|-&lt;br /&gt;
| Coup: City State&lt;br /&gt;
| https://github.com/quietmint/bga-coupcitystate&lt;br /&gt;
| quietmint&lt;br /&gt;
|-&lt;br /&gt;
| Dungeon Roll&lt;br /&gt;
| https://github.com/MartinGoulet/bga-dungeonroll&lt;br /&gt;
| MGoulet&lt;br /&gt;
|-&lt;br /&gt;
| Egyptian Ratscrew&lt;br /&gt;
| https://github.com/0BuRner/bga-egyptianratscrew&lt;br /&gt;
| 0BuRner&lt;br /&gt;
|-&lt;br /&gt;
| Eruption&lt;br /&gt;
| https://github.com/AndyKerrison/bga-eruption&lt;br /&gt;
| Andy_K&lt;br /&gt;
|-&lt;br /&gt;
| A Fistful Of Gold&lt;br /&gt;
| https://bitbucket.org/Joel_L/fistfulofgold&lt;br /&gt;
| Brainchild&lt;br /&gt;
|-&lt;br /&gt;
| Florenza: The Card Game&lt;br /&gt;
| https://github.com/alberto-bottarini/bga-florenza&lt;br /&gt;
| tarini &lt;br /&gt;
|-&lt;br /&gt;
| Hearts &#039;&#039;&#039;(Tutorial)&#039;&#039;&#039;&lt;br /&gt;
| https://github.com/elaskavaia/bga-heartsla&lt;br /&gt;
| Victoria_La&lt;br /&gt;
|-&lt;br /&gt;
| Homesteaders&lt;br /&gt;
| https://github.com/npatron/bga-homesteaders&lt;br /&gt;
| TheBoot&lt;br /&gt;
|-&lt;br /&gt;
| Incan Gold&lt;br /&gt;
| https://github.com/AntonioSoler/bga-incangold&lt;br /&gt;
| Morgalad &lt;br /&gt;
|-&lt;br /&gt;
| Innovation&lt;br /&gt;
| https://github.com/micahstairs/bga-innovation&lt;br /&gt;
| Micah Stairs (micahstairs)&lt;br /&gt;
|-&lt;br /&gt;
| Mapmaker: The Gerrymandering Game&lt;br /&gt;
| https://github.com/gzhang01/bga-mapmaker&lt;br /&gt;
| gkz&lt;br /&gt;
|-&lt;br /&gt;
| Marco Polo&lt;br /&gt;
| https://github.com/rcitaliano/MarcoPolo&lt;br /&gt;
| rcitaliano&lt;br /&gt;
|-&lt;br /&gt;
| Nile&lt;br /&gt;
| https://github.com/AndyKerrison/bga-nile&lt;br /&gt;
| Andy_K&lt;br /&gt;
|-&lt;br /&gt;
| Noir: Killer vs Inspector&lt;br /&gt;
| https://bitbucket.org/chhuang76/bga_noirkvi&lt;br /&gt;
| ch huang&lt;br /&gt;
|-&lt;br /&gt;
| Penny Press&lt;br /&gt;
| https://github.com/AdamNovotny/bga-blooms&lt;br /&gt;
| A-dam&lt;br /&gt;
|-&lt;br /&gt;
| P.I.&lt;br /&gt;
| https://gitlab.com/fa81/bga-pi, https://github.com/hellp/bga-pi (mirror)&lt;br /&gt;
| Fabian Neumann (fa81)&lt;br /&gt;
|-&lt;br /&gt;
| Santorini&lt;br /&gt;
| https://github.com/AntonioSoler/bga-santorini&lt;br /&gt;
| Morgalad, quietmint, Tisaac&lt;br /&gt;
|-&lt;br /&gt;
| Tablut&lt;br /&gt;
| https://github.com/Lucas-C/tablut&lt;br /&gt;
| Lucas-C &amp;amp; ntaffore&lt;br /&gt;
|-&lt;br /&gt;
| Takara Island&lt;br /&gt;
| https://github.com/AntonioSoler/bga-takaraisland&lt;br /&gt;
| Morgalad&lt;br /&gt;
|-&lt;br /&gt;
| Taluva&lt;br /&gt;
| https://github.com/quietmint/bga-taluva&lt;br /&gt;
| Morgalad &amp;amp; quietmint&lt;br /&gt;
|-&lt;br /&gt;
| Teotihuacan: City of Gods&lt;br /&gt;
| https://github.com/Trompetenhut/bga-teotihuacan&lt;br /&gt;
| Trompetenhut&lt;br /&gt;
|-&lt;br /&gt;
| Texas 42 (domino game, still under development)&lt;br /&gt;
| https://github.com/ishermandom/bga-42&lt;br /&gt;
| Stardust Spikes, Jason Turner-Maier, Ilya Sherman&lt;br /&gt;
|-&lt;br /&gt;
| Uptown&lt;br /&gt;
| https://github.com/elliotkendall/bga-uptown&lt;br /&gt;
| SpottedShroom&lt;br /&gt;
|-&lt;br /&gt;
| Via Magica&lt;br /&gt;
| https://github.com/christopherburke/bga_viamagica&lt;br /&gt;
| CuriousTerran&lt;br /&gt;
|-&lt;br /&gt;
| Just Desserts&lt;br /&gt;
| https://github.com/mizutismask/bga-just-desserts&lt;br /&gt;
| mizutismask&lt;br /&gt;
|-&lt;br /&gt;
| The King&#039;s Guild&lt;br /&gt;
| https://github.com/AdamNovotny/BGG-KingsGuild&lt;br /&gt;
| A-dam&lt;br /&gt;
|-&lt;br /&gt;
| Get the MacGuffin&lt;br /&gt;
| https://github.com/mizutismask/bga-get-the-MacGuffin&lt;br /&gt;
| mizutismask&lt;br /&gt;
|-&lt;br /&gt;
| President&lt;br /&gt;
| https://github.com/quaresma95/president&lt;br /&gt;
| quaresma95&lt;br /&gt;
|-&lt;br /&gt;
| Hardback&lt;br /&gt;
| https://github.com/quietmint/bga-hardback&lt;br /&gt;
| quietmint&lt;br /&gt;
|-&lt;br /&gt;
| Dice Summoners&lt;br /&gt;
| https://github.com/eoincos/bga-dicesummoners&lt;br /&gt;
| eoincos&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Projects on studio ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Any developer can add themselves to a project as read-only from https://studio.boardgamearena.com/#!projects page (almost any project).&lt;br /&gt;
The list below are no-games which do not have bgg id and not showing up there.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! NAME&lt;br /&gt;
! CODE LINK&lt;br /&gt;
! DEVELOPER&lt;br /&gt;
|-&lt;br /&gt;
| Shared Code&lt;br /&gt;
| https://studio.boardgamearena.com/gamepanel?game=sharedcode&lt;br /&gt;
| Victoria_La&lt;br /&gt;
|-&lt;br /&gt;
| Original BGA template&lt;br /&gt;
| https://studio.boardgamearena.com/gamepanel?game=template&lt;br /&gt;
| Victoria_La&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Other useful resources ==&lt;br /&gt;
&lt;br /&gt;
Moved to [[Tools_and_tips_of_BGA_Studio]]&lt;/div&gt;</summary>
		<author><name>Tisaac</name></author>
	</entry>
	<entry>
		<id>https://en.doc.boardgamearena.com/index.php?title=BGA_Code_Sharing&amp;diff=12933</id>
		<title>BGA Code Sharing</title>
		<link rel="alternate" type="text/html" href="https://en.doc.boardgamearena.com/index.php?title=BGA_Code_Sharing&amp;diff=12933"/>
		<updated>2022-05-01T12:32:50Z</updated>

		<summary type="html">&lt;p&gt;Tisaac: /* Community shared components, pens, etc */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Studio_Framework_Navigation}}&lt;br /&gt;
&lt;br /&gt;
This page is for listing of externally hosted bga projects, tools and resources, as well as internal project&lt;br /&gt;
intended for sharing&lt;br /&gt;
&lt;br /&gt;
== Community shared components, pens, etc ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! NAME&lt;br /&gt;
! CODE LINK&lt;br /&gt;
! DESCRIPTION&lt;br /&gt;
|-&lt;br /&gt;
! colspan=&amp;quot;3&amp;quot; | Dice models and animation&lt;br /&gt;
|-&lt;br /&gt;
| Die: 4 sided &lt;br /&gt;
| https://codepen.io/mrkiffie/pen/doVZgW&lt;br /&gt;
| code pen&lt;br /&gt;
|-&lt;br /&gt;
| Die: 6 sided &lt;br /&gt;
| https://github.com/elaskavaia/bga-sharedcode&lt;br /&gt;
| Code can be found in project&lt;br /&gt;
|-&lt;br /&gt;
| Die: 12 sided (dodecahedron) &lt;br /&gt;
| https://codepen.io/VictoriaLa/pen/xxLLxOP&lt;br /&gt;
| Code pen&lt;br /&gt;
|- &lt;br /&gt;
| Die: 20 sided &lt;br /&gt;
| https://codepen.io/vicentemundim/details/cenIh&lt;br /&gt;
| Code pen&lt;br /&gt;
|-&lt;br /&gt;
! colspan=&amp;quot;3&amp;quot; | Moving object using CSS animation (mostly)&lt;br /&gt;
|-&lt;br /&gt;
| Phantom object move on oversurface &lt;br /&gt;
| https://codepen.io/VictoriaLa/pen/gORvdJo&lt;br /&gt;
| This technique creates clone of the object it moves it on another surface. It works well when parents that css transform applies such as scale and rotate&lt;br /&gt;
|-&lt;br /&gt;
| Move object directly using positioning &lt;br /&gt;
| https://codepen.io/VictoriaLa/pen/dyzgKVX&lt;br /&gt;
| This technique is modification of BGA framework method to allow mobile object not to have absolute position before or after the move (and uses css animation not dojo). Methods slideToObjectRelative, attachToNewObjectNoDestroy&lt;br /&gt;
|-&lt;br /&gt;
! colspan=&amp;quot;3&amp;quot; | Responsive layout for game boards&lt;br /&gt;
|-&lt;br /&gt;
|Flex Layout&lt;br /&gt;
|https://codepen.io/VictoriaLa/pen/XWjJJgG&lt;br /&gt;
|Example on how to create flexible layout just by using css&lt;br /&gt;
|-&lt;br /&gt;
! colspan=&amp;quot;3&amp;quot; | Algorithms&lt;br /&gt;
|-&lt;br /&gt;
|Hex grid&lt;br /&gt;
|tapestry,...&lt;br /&gt;
|&lt;br /&gt;
|-&lt;br /&gt;
|Shortest path on hex grid&lt;br /&gt;
|memoir 44&lt;br /&gt;
|(add your games already in bga here)&lt;br /&gt;
|-&lt;br /&gt;
|Largest area on hex grid&lt;br /&gt;
|tapestry, ...&lt;br /&gt;
|&lt;br /&gt;
|-&lt;br /&gt;
|Largest area on square grid&lt;br /&gt;
|king domino, ...&lt;br /&gt;
|&lt;br /&gt;
|-&lt;br /&gt;
|Tetris pieces&lt;br /&gt;
|patchwork, ...&lt;br /&gt;
|Matrix manupations to rotate, flip and fit tetris pieces&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Projects hosted not in studio ==&lt;br /&gt;
&lt;br /&gt;
See the table a link and nickname of the developer on bga (same as used for dev forum), and short description. See [[Tools_and_tips_of_BGA_Studio#Version_Control]] for some suggestions on how and where to publish your code externally. Also see the [https://github.com/topics/boardgamearena boardgamearena] tag on github.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Important notice about artwork on BGA Open Source projects: original hi-resolution images from publishers must not be published on the repositories. In addition, it is better to specify that the images derivated from publishers artwork are copyrighted and cannot be licensed under a free license like Creative Commons.&lt;br /&gt;
&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! NON-GAME PROJECTS&lt;br /&gt;
! CODE LINK&lt;br /&gt;
! DEVELOPER&lt;br /&gt;
! COMMENT&lt;br /&gt;
|-&lt;br /&gt;
| Shared Code (not a game)&lt;br /&gt;
| https://github.com/elaskavaia/bga-sharedcode&lt;br /&gt;
| Victoria_La&lt;br /&gt;
| Examples of various game components and PHP stubs of framework code to make IDE happy&lt;br /&gt;
|-&lt;br /&gt;
| BoardGameArena Workbench (not a game)&lt;br /&gt;
| https://github.com/danielholmes/bga-workbench&lt;br /&gt;
| Daniel Holmes (dhau)&lt;br /&gt;
|-&lt;br /&gt;
! GAME&lt;br /&gt;
! CODE LINK&lt;br /&gt;
! DEVELOPER&lt;br /&gt;
! COMMENT&lt;br /&gt;
|-&lt;br /&gt;
| 99 (Trick-taking Card Game)&lt;br /&gt;
| https://github.com/ekelly/bga-ninetynine&lt;br /&gt;
| QuasarDukeDev&lt;br /&gt;
|-&lt;br /&gt;
| Assyria &lt;br /&gt;
| https://github.com/sebastien-prudhomme/bga-assyria&lt;br /&gt;
| daikinee &lt;br /&gt;
|-&lt;br /&gt;
| Aura&lt;br /&gt;
| https://github.com/micahstairs/bga-aura&lt;br /&gt;
| Micah Stairs (micahstairs)&lt;br /&gt;
|-&lt;br /&gt;
| Bandido &lt;br /&gt;
| https://github.com/opheliehb/BandidoBGA&lt;br /&gt;
| ophelopede &amp;amp; Harkle &lt;br /&gt;
|-&lt;br /&gt;
| The Battle for Hill 218&lt;br /&gt;
| https://github.com/danielholmes/battle-for-hill-218&lt;br /&gt;
| Daniel Holmes (dhau)&lt;br /&gt;
|-&lt;br /&gt;
| Bonbons&lt;br /&gt;
| https://github.com/AntonioSoler/bga-bonbons&lt;br /&gt;
| Morgalad &lt;br /&gt;
|-&lt;br /&gt;
| Coinche&lt;br /&gt;
| https://github.com/drasill/bga-coinche&lt;br /&gt;
| Draasill&lt;br /&gt;
|-&lt;br /&gt;
| Coup: City State&lt;br /&gt;
| https://github.com/quietmint/bga-coupcitystate&lt;br /&gt;
| quietmint&lt;br /&gt;
|-&lt;br /&gt;
| Dungeon Roll&lt;br /&gt;
| https://github.com/MartinGoulet/bga-dungeonroll&lt;br /&gt;
| MGoulet&lt;br /&gt;
|-&lt;br /&gt;
| Egyptian Ratscrew&lt;br /&gt;
| https://github.com/0BuRner/bga-egyptianratscrew&lt;br /&gt;
| 0BuRner&lt;br /&gt;
|-&lt;br /&gt;
| Eruption&lt;br /&gt;
| https://github.com/AndyKerrison/bga-eruption&lt;br /&gt;
| Andy_K&lt;br /&gt;
|-&lt;br /&gt;
| A Fistful Of Gold&lt;br /&gt;
| https://bitbucket.org/Joel_L/fistfulofgold&lt;br /&gt;
| Brainchild&lt;br /&gt;
|-&lt;br /&gt;
| Florenza: The Card Game&lt;br /&gt;
| https://github.com/alberto-bottarini/bga-florenza&lt;br /&gt;
| tarini &lt;br /&gt;
|-&lt;br /&gt;
| Hearts &#039;&#039;&#039;(Tutorial)&#039;&#039;&#039;&lt;br /&gt;
| https://github.com/elaskavaia/bga-heartsla&lt;br /&gt;
| Victoria_La&lt;br /&gt;
|-&lt;br /&gt;
| Homesteaders&lt;br /&gt;
| https://github.com/npatron/bga-homesteaders&lt;br /&gt;
| TheBoot&lt;br /&gt;
|-&lt;br /&gt;
| Incan Gold&lt;br /&gt;
| https://github.com/AntonioSoler/bga-incangold&lt;br /&gt;
| Morgalad &lt;br /&gt;
|-&lt;br /&gt;
| Innovation&lt;br /&gt;
| https://github.com/micahstairs/bga-innovation&lt;br /&gt;
| Micah Stairs (micahstairs)&lt;br /&gt;
|-&lt;br /&gt;
| Mapmaker: The Gerrymandering Game&lt;br /&gt;
| https://github.com/gzhang01/bga-mapmaker&lt;br /&gt;
| gkz&lt;br /&gt;
|-&lt;br /&gt;
| Marco Polo&lt;br /&gt;
| https://github.com/rcitaliano/MarcoPolo&lt;br /&gt;
| rcitaliano&lt;br /&gt;
|-&lt;br /&gt;
| Nile&lt;br /&gt;
| https://github.com/AndyKerrison/bga-nile&lt;br /&gt;
| Andy_K&lt;br /&gt;
|-&lt;br /&gt;
| Noir: Killer vs Inspector&lt;br /&gt;
| https://bitbucket.org/chhuang76/bga_noirkvi&lt;br /&gt;
| ch huang&lt;br /&gt;
|-&lt;br /&gt;
| Penny Press&lt;br /&gt;
| https://github.com/AdamNovotny/bga-blooms&lt;br /&gt;
| A-dam&lt;br /&gt;
|-&lt;br /&gt;
| P.I.&lt;br /&gt;
| https://gitlab.com/fa81/bga-pi, https://github.com/hellp/bga-pi (mirror)&lt;br /&gt;
| Fabian Neumann (fa81)&lt;br /&gt;
|-&lt;br /&gt;
| Santorini&lt;br /&gt;
| https://github.com/AntonioSoler/bga-santorini&lt;br /&gt;
| Morgalad, quietmint, Tisaac&lt;br /&gt;
|-&lt;br /&gt;
| Tablut&lt;br /&gt;
| https://github.com/Lucas-C/tablut&lt;br /&gt;
| Lucas-C &amp;amp; ntaffore&lt;br /&gt;
|-&lt;br /&gt;
| Takara Island&lt;br /&gt;
| https://github.com/AntonioSoler/bga-takaraisland&lt;br /&gt;
| Morgalad&lt;br /&gt;
|-&lt;br /&gt;
| Taluva&lt;br /&gt;
| https://github.com/quietmint/bga-taluva&lt;br /&gt;
| Morgalad &amp;amp; quietmint&lt;br /&gt;
|-&lt;br /&gt;
| Teotihuacan: City of Gods&lt;br /&gt;
| https://github.com/Trompetenhut/bga-teotihuacan&lt;br /&gt;
| Trompetenhut&lt;br /&gt;
|-&lt;br /&gt;
| Texas 42 (domino game, still under development)&lt;br /&gt;
| https://github.com/ishermandom/bga-42&lt;br /&gt;
| Stardust Spikes, Jason Turner-Maier, Ilya Sherman&lt;br /&gt;
|-&lt;br /&gt;
| Uptown&lt;br /&gt;
| https://github.com/elliotkendall/bga-uptown&lt;br /&gt;
| SpottedShroom&lt;br /&gt;
|-&lt;br /&gt;
| Via Magica&lt;br /&gt;
| https://github.com/christopherburke/bga_viamagica&lt;br /&gt;
| CuriousTerran&lt;br /&gt;
|-&lt;br /&gt;
| Just Desserts&lt;br /&gt;
| https://github.com/mizutismask/bga-just-desserts&lt;br /&gt;
| mizutismask&lt;br /&gt;
|-&lt;br /&gt;
| The King&#039;s Guild&lt;br /&gt;
| https://github.com/AdamNovotny/BGG-KingsGuild&lt;br /&gt;
| A-dam&lt;br /&gt;
|-&lt;br /&gt;
| Get the MacGuffin&lt;br /&gt;
| https://github.com/mizutismask/bga-get-the-MacGuffin&lt;br /&gt;
| mizutismask&lt;br /&gt;
|-&lt;br /&gt;
| President&lt;br /&gt;
| https://github.com/quaresma95/president&lt;br /&gt;
| quaresma95&lt;br /&gt;
|-&lt;br /&gt;
| Hardback&lt;br /&gt;
| https://github.com/quietmint/bga-hardback&lt;br /&gt;
| quietmint&lt;br /&gt;
|-&lt;br /&gt;
| Dice Summoners&lt;br /&gt;
| https://github.com/eoincos/bga-dicesummoners&lt;br /&gt;
| eoincos&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Projects on studio ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Any developer can add themselves to a project as read-only from https://studio.boardgamearena.com/#!projects page (almost any project).&lt;br /&gt;
The list below are no-games which do not have bgg id and not showing up there.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! NAME&lt;br /&gt;
! CODE LINK&lt;br /&gt;
! DEVELOPER&lt;br /&gt;
|-&lt;br /&gt;
| Shared Code&lt;br /&gt;
| https://studio.boardgamearena.com/gamepanel?game=sharedcode&lt;br /&gt;
| Victoria_La&lt;br /&gt;
|-&lt;br /&gt;
| Original BGA template&lt;br /&gt;
| https://studio.boardgamearena.com/gamepanel?game=template&lt;br /&gt;
| Victoria_La&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Other useful resources ==&lt;br /&gt;
&lt;br /&gt;
Moved to [[Tools_and_tips_of_BGA_Studio]]&lt;/div&gt;</summary>
		<author><name>Tisaac</name></author>
	</entry>
	<entry>
		<id>https://en.doc.boardgamearena.com/index.php?title=Players_actions:_yourgamename.action.php&amp;diff=8290</id>
		<title>Players actions: yourgamename.action.php</title>
		<link rel="alternate" type="text/html" href="https://en.doc.boardgamearena.com/index.php?title=Players_actions:_yourgamename.action.php&amp;diff=8290"/>
		<updated>2021-05-18T19:36:43Z</updated>

		<summary type="html">&lt;p&gt;Tisaac: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Studio_Framework_Navigation}}&lt;br /&gt;
&lt;br /&gt;
== Purpose of this file ==&lt;br /&gt;
&lt;br /&gt;
With this file, you define all the player entry points (i.e., possible game actions) for your game.&lt;br /&gt;
&lt;br /&gt;
This file is a sort of &amp;quot;bridge&amp;quot; between the AJAX calls you perform from the Javascript client side, and your main PHP code in &amp;quot;yourgame.game.php&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
The role of the methods defined in this file is to filter the arguments, format them a bit, and then call a corresponding PHP method from your main game logic (&amp;quot;yourgame.game.php&amp;quot; file).&lt;br /&gt;
&lt;br /&gt;
Methods in this file should be short: no game logic must be introduced here.&lt;br /&gt;
&lt;br /&gt;
== Example of typical action method ==&lt;br /&gt;
&lt;br /&gt;
(from Reversi example)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    public function playDisc()&lt;br /&gt;
    {&lt;br /&gt;
        self::setAjaxMode();     &lt;br /&gt;
        $x = self::getArg( &amp;quot;x&amp;quot;, AT_posint, true );&lt;br /&gt;
        $y = self::getArg( &amp;quot;y&amp;quot;, AT_posint, true );&lt;br /&gt;
        $result = $this-&amp;gt;game-&amp;gt;playDisc( $x, $y );&lt;br /&gt;
        self::ajaxResponse( );&lt;br /&gt;
    }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Methods to use in action methods ==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;function setAjaxMode()&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Must be used at the beginning of each action method.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;function ajaxResponse()&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Must be used at the end of each action method.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;function getArg( $argName, $argType, $mandatory=false, $default=NULL, $argTypeDetails=array(), $bCanFail=false  )&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
This method must be used to retrieve the arguments sent with your AJAX query.&lt;br /&gt;
&lt;br /&gt;
You must &#039;&#039;not&#039;&#039; use &amp;quot;_GET&amp;quot;, &amp;quot;_POST&amp;quot; or equivalent PHP variables to do this, as it is unsafe.&lt;br /&gt;
&lt;br /&gt;
This method uses the following arguments:&lt;br /&gt;
&lt;br /&gt;
* argName: the name of the argument to retrieve.&lt;br /&gt;
* argType: the type of the argument. You should use one of the following:&lt;br /&gt;
  &#039;AT_int&#039; for an integer&lt;br /&gt;
  &#039;AT_posint&#039; for a positive integer &lt;br /&gt;
  &#039;AT_float&#039; for a float&lt;br /&gt;
  &#039;AT_bool&#039; for 1/0/true/false&lt;br /&gt;
  &#039;AT_enum&#039; for an enumeration (argTypeDetails lists the possible values as an array)&lt;br /&gt;
  &#039;AT_alphanum&#039; for a string with 0-9a-zA-Z_ and space&lt;br /&gt;
  &#039;AT_alphanum_dash&#039; for a string with 0-9a-zA-Z_- and space&lt;br /&gt;
  &#039;AT_numberlist&#039; for a list of numbers separated with &amp;quot;,&amp;quot; or &amp;quot;;&amp;quot; (example: 1,4;2,3;-1,2)&lt;br /&gt;
  &#039;AT_base64&#039; for a base64-encoded string (SECURITY WARNING*)&lt;br /&gt;
  &#039;AT_json&#039; for a JSON stringified string (SECURITY WARNING**)&lt;br /&gt;
&lt;br /&gt;
* mandatory: specify &amp;quot;true&amp;quot; if the argument is mandatory.&lt;br /&gt;
* default: if mandatory=false, you can specify here a default value in case the argument is not present.&lt;br /&gt;
* argTypeDetails: see AT_enum above.&lt;br /&gt;
* bCanFail: if true, specify that it may be possible that the argument won&#039;t be of the type specified by argType (and then do not log this as a fatal error in the system, and return a standard exception to the player).&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;SECURITY WARNING&#039;&#039;&#039;: If using AT_base64 or AT_json, or other undocumented unchecked types you must perform validation on unpacked data, i.e. do not use any of it unchecked, i.e. pass to DB queries or return back in notifications.&lt;br /&gt;
&lt;br /&gt;
Here is an example of a sanity check for JSON : &lt;br /&gt;
&#039;&#039;&#039;&lt;br /&gt;
  public function actMyAction()&lt;br /&gt;
  {&lt;br /&gt;
    self::setAjaxMode();&lt;br /&gt;
    $args = self::getArg(&#039;actionArgs&#039;, AT_json, true);&lt;br /&gt;
    $this-&amp;gt;validateJSonAlphaNum($args, &#039;actionArgs&#039;);&lt;br /&gt;
    $this-&amp;gt;game-&amp;gt;actMyAction($args);&lt;br /&gt;
    self::ajaxResponse();&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  public function validateJSonAlphaNum($value, $argName = &#039;unknown&#039;)&lt;br /&gt;
  {&lt;br /&gt;
    if (is_array($value)) {&lt;br /&gt;
      foreach ($value as $key =&amp;gt; $v) {&lt;br /&gt;
        $this-&amp;gt;validateJSonAlphaNum($key, $argName);&lt;br /&gt;
        $this-&amp;gt;validateJSonAlphaNum($v, $argName);&lt;br /&gt;
      }&lt;br /&gt;
      return true;&lt;br /&gt;
    }&lt;br /&gt;
    if (is_int($value)) {&lt;br /&gt;
      return true;&lt;br /&gt;
    }&lt;br /&gt;
    $bValid = preg_match(&amp;quot;/^[_0-9a-zA-Z- ]*$/&amp;quot;, $value) === 1;&lt;br /&gt;
    if (!$bValid) {&lt;br /&gt;
      throw new feException(&amp;quot;Bad value for: $argName&amp;quot;, true, true, FEX_bad_input_argument);&lt;br /&gt;
    }&lt;br /&gt;
    return true;&lt;br /&gt;
  }&lt;br /&gt;
&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;function isArg( $argName )&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
This is a useful method when you only want to check if an argument is present or not present in your AJAX request (and don&#039;t care about the value).&lt;br /&gt;
&lt;br /&gt;
It returns &amp;quot;true&amp;quot; or &amp;quot;false&amp;quot; according to whether &amp;quot;argName&amp;quot; has been specified as an argument of the AJAX request or not.&lt;br /&gt;
&lt;br /&gt;
== Useful tip: retrieve a list of numbers ==&lt;br /&gt;
&lt;br /&gt;
If your Javascript sends a list of integers separated by &amp;quot;;&amp;quot; (example: &amp;quot;1;2;3;4&amp;quot;) as an argument, you can transform them into a PHP array with the following:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    public function playCards()&lt;br /&gt;
    {&lt;br /&gt;
        self::setAjaxMode();     &lt;br /&gt;
&lt;br /&gt;
        $card_ids_raw = self::getArg( &amp;quot;card_ids&amp;quot;, AT_numberlist, true );&lt;br /&gt;
        &lt;br /&gt;
        // Removing last &#039;;&#039; if exists&lt;br /&gt;
        if( substr( $card_ids_raw, -1 ) == &#039;;&#039; )&lt;br /&gt;
            $card_ids_raw = substr( $card_ids_raw, 0, -1 );&lt;br /&gt;
        if( $card_ids_raw == &#039;&#039; )&lt;br /&gt;
            $card_ids = array();&lt;br /&gt;
        else&lt;br /&gt;
            $card_ids = explode( &#039;;&#039;, $card_ids_raw );&lt;br /&gt;
&lt;br /&gt;
        $this-&amp;gt;game-&amp;gt;playCards( $card_ids );&lt;br /&gt;
        self::ajaxResponse( );&lt;br /&gt;
    }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Example pass array of Id&#039;s ==&lt;br /&gt;
&lt;br /&gt;
If your Javascript sends a list of object denomated by alphanumerical tokenId, you can use AT_alphanum type and space as array separator:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    // sending &#039;card_ids&#039; =&amp;gt; &amp;quot;card_1 card_23 card_12&amp;quot;&lt;br /&gt;
    public function playCards()   {&lt;br /&gt;
        self::setAjaxMode();     &lt;br /&gt;
&lt;br /&gt;
        $card_ids_raw = self::getArg( &amp;quot;card_ids&amp;quot;, AT_alphanum, true );&lt;br /&gt;
        $card_ids_raw = trim($card_ids_raw);&lt;br /&gt;
&lt;br /&gt;
        if( $card_ids_raw == &#039;&#039; )&lt;br /&gt;
            $card_ids = array();&lt;br /&gt;
        else&lt;br /&gt;
            $card_ids = explode( &#039; &#039;, $card_ids_raw );&lt;br /&gt;
&lt;br /&gt;
        $this-&amp;gt;game-&amp;gt;playCards( $card_ids );&lt;br /&gt;
        self::ajaxResponse( );&lt;br /&gt;
    }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Retrieving data from ajax call ==&lt;br /&gt;
&lt;br /&gt;
Note that this is not possible to return any result from a player action: it should return nothing (action went fine) or an exception (action unsuccessful).&lt;br /&gt;
&lt;br /&gt;
The typical way to implement this is using games states with game state arguments. Eventually, use player notifications.&lt;br /&gt;
&lt;br /&gt;
== Game action handler ==&lt;br /&gt;
This is note on what you should be doing and not doing ggg.game.php action handler vs action.php handler&lt;br /&gt;
&lt;br /&gt;
action.php&lt;br /&gt;
* action handler in action.php should very simple and it should ONLY extract arguments from ajax call, pass them down to game handler&lt;br /&gt;
* it should not implement any game logic or check for validity beyong the syntax. I.e. DO NOT put checkAction this action.php&lt;br /&gt;
&lt;br /&gt;
game.php&lt;br /&gt;
* call checkAction(&#039;myAction&#039;) first&lt;br /&gt;
* check arguments for game validity (i.e. player is not cheating), throw system exceptions if it is (usually this cases where JS side won&#039;t be sending it but you still have to check for it)&lt;br /&gt;
* perfom action and update database, can do more check if throw user exception if this is not valid move by the rules&lt;br /&gt;
* send notifications &lt;br /&gt;
* transition to new state&lt;/div&gt;</summary>
		<author><name>Tisaac</name></author>
	</entry>
	<entry>
		<id>https://en.doc.boardgamearena.com/index.php?title=I_wish_I_knew_this_when_I_started&amp;diff=7760</id>
		<title>I wish I knew this when I started</title>
		<link rel="alternate" type="text/html" href="https://en.doc.boardgamearena.com/index.php?title=I_wish_I_knew_this_when_I_started&amp;diff=7760"/>
		<updated>2021-03-28T19:09:10Z</updated>

		<summary type="html">&lt;p&gt;Tisaac: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This page contains most &amp;quot;I wish I knew this before...&amp;quot; momentics (in regards to BGA studio game development). One line per statement please with doc references. Docs can be outside of BGA wiki.&lt;br /&gt;
Can you add your name at the end of &amp;quot;quote&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
* Browser caches images and css, to force re-cache use Ctrl+F5, and sometimes it&#039;s not enough so go to the web console &amp;gt; Network &amp;gt; check &amp;quot;disable cache&amp;quot;&lt;br /&gt;
* Browser has powerful embeded dev tools for inspection of dom, css and js, you can debug js right in browser&lt;br /&gt;
* You don&#039;t have to login with another dev account to play test the game under development, little colored arrows on studio panel switch between test accounts&lt;br /&gt;
* You can run PHP functions from chat&lt;/div&gt;</summary>
		<author><name>Tisaac</name></author>
	</entry>
	<entry>
		<id>https://en.doc.boardgamearena.com/index.php?title=Pre-release_checklist&amp;diff=6181</id>
		<title>Pre-release checklist</title>
		<link rel="alternate" type="text/html" href="https://en.doc.boardgamearena.com/index.php?title=Pre-release_checklist&amp;diff=6181"/>
		<updated>2020-11-18T20:19:01Z</updated>

		<summary type="html">&lt;p&gt;Tisaac: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Studio_Framework_Navigation}}&lt;br /&gt;
&lt;br /&gt;
If you think your game is ready to be reviewed by by BGA admins and/or Publisher please consult this checklist first&lt;br /&gt;
&lt;br /&gt;
* Metadata and graphics&lt;br /&gt;
** [[Game_meta-information: gameinfos.inc.php]] has correct and up to date information about the game&lt;br /&gt;
** Game box graphics is 3D version of the game box (if available) and publisher icon is correct (see [[Game art: img directory]]). Space around the box has to be transparent, not white.&lt;br /&gt;
** You have added a game_banner.jpg and some game_displayX.jpg images to make the game page pretty (NB: on the studio, you have to create a build for these images to appear on the studio game page)&lt;br /&gt;
** There is no images in img directory which are not needed anymore&lt;br /&gt;
** Multiple images (i.e. cards) are compressed in &amp;quot;Sprite&amp;quot; (see [[Game art: img directory]])&lt;br /&gt;
** Each image should not exceed 4M&lt;br /&gt;
** Total size should not exceed 10M, image compression should be used otherwise&lt;br /&gt;
* Server side&lt;br /&gt;
** When giving their turn to a player, you give them some extra time with the giveExtraTime() function&lt;br /&gt;
** Game progression is implemented (getGameProgression() in php)&lt;br /&gt;
** Zombie turn is implemented (zombieTurn() in php). Note: it can only be tested if you explicitly click on the quit button to create a zombie. If you are expelled it does not generated a Zombie.&lt;br /&gt;
** You have defined and implemented some meaningful statistics for your game (i.e. total points, point from source A, B, C...)&lt;br /&gt;
** Game has meaningful notification messages (but don&#039;t overkill it, more user logs will slow down the loading)&lt;br /&gt;
** You implemented tiebreaking (using aux score field) and updated tiebreaker description in meta-data&lt;br /&gt;
* Special testing&lt;br /&gt;
** Game is tested with spectator (non player observer): change the testuser in the URL to see the game as another user (same URL as when clicking on red arrow)&lt;br /&gt;
** Game is tested with in-game replay from last move feature (by clicking on notification log items)&lt;br /&gt;
** Game works in Chrome and Firefox browsers at least. Also very recommended to test in IE 11 and Edge.&lt;br /&gt;
** Game works on mobile device (if you don&#039;t have mobile device to test at least test in Chrome with smaller screen, they have a mode for that)&lt;br /&gt;
** Test your game in realtime mode. Usually people will run out of time if you use default times unless you add call giveExtraTime($active_player_id) before each turn&lt;br /&gt;
** Test your game in 3D mode (if it makes sense; 3D mode can also be disabled through the &#039;enable_3d&#039; parameter for gameinfos.inc.php, but if it &amp;quot;mostly works&amp;quot;, it can be nice to keep it activated even if 2D is more appropriate for the game, just because it&#039;s fun to look at)&lt;br /&gt;
* Cleanup&lt;br /&gt;
** Remove all extra console.log from your js code&lt;br /&gt;
** Remove all unnecessary debug logging from your php code&lt;br /&gt;
** Copyright headers in all source files have your name&lt;br /&gt;
* User Interface&lt;br /&gt;
** Review BGA UI design Guidelines [[BGA_Studio_Guidelines]]&lt;br /&gt;
** Check all your english message for proper use of punctuation, capitalization, usage of present tense in notification (not past) and gender nuturality. See [[Translations]] for English rules.&lt;br /&gt;
** If the elements in your game zone don&#039;t occupy all the available horizontal space, &#039;&#039;&#039;they should be centered&#039;&#039;&#039;.&lt;br /&gt;
** If your game elements become blurry or pixellated when using the browser zoom, you may want to consider [[Game_art:_img_directory#Use_background-size | higher resolution images with background-size]]&lt;br /&gt;
** Non-self explanatory graphic elements should have tooltips&lt;br /&gt;
** If graphic elements appear in notification log they should have titles (i.e. title attribute of div) so can be read in non rendered form (i.e. as text only)&lt;br /&gt;
** Strings in your source code are ready for translation. See [[Translations]]. You can generate dummy translations for checking that everything is ready for translation from your &amp;quot;Manage game&amp;quot; page.&lt;br /&gt;
** A prefix for example a trigram for your game that you append to all the css classes to avoid namespace conflicts, i.e. vla_selected vs selected&lt;br /&gt;
** If you are looking for advice on design and some 3rd party testing you can post a message on the developers forum, and ask other developers, there are a lot of people who will gladly do it.&lt;br /&gt;
* Finally move to Alpha status&lt;br /&gt;
** If possible (meaning if there is not already a project with that name) copy your project to a new project &#039;&#039;&#039;matching exactly the name of the game&#039;&#039;&#039; (no prefix or suffix). If not possible move on to the next steps, admin will have to retrieve the other project and overwrite it.&lt;br /&gt;
** Create a build for your game from the &amp;quot;manage game&amp;quot; page (using the &#039;&#039;&#039;Build a new release version&#039;&#039;&#039; section) and check the log to make sure that everything builds fine (after a successful build, you should see a new version in &amp;quot;Versions available for production&amp;quot;).&lt;br /&gt;
** Send an e-mail to studio@boardgamearena.com asking to move the project forward for review. You cannot deploy yourself from the &amp;quot;manage game&amp;quot; page until a first deploy has been done by the admins. Please note that &#039;&#039;&#039;everything must be OK on the licensing&#039;&#039;&#039; side for a project to be moved to production.&lt;br /&gt;
** When admins publish (push to alpha) they will send an email to the developer with all relevant information about the next steps.&lt;/div&gt;</summary>
		<author><name>Tisaac</name></author>
	</entry>
	<entry>
		<id>https://en.doc.boardgamearena.com/index.php?title=Tools_and_tips_of_BGA_Studio&amp;diff=6180</id>
		<title>Tools and tips of BGA Studio</title>
		<link rel="alternate" type="text/html" href="https://en.doc.boardgamearena.com/index.php?title=Tools_and_tips_of_BGA_Studio&amp;diff=6180"/>
		<updated>2020-11-18T20:16:11Z</updated>

		<summary type="html">&lt;p&gt;Tisaac: /* Switching between users */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Studio_Framework_Navigation}}&lt;br /&gt;
&lt;br /&gt;
== Server Tools and Tips ==&lt;br /&gt;
=== Starting a game in one click ===&lt;br /&gt;
&lt;br /&gt;
To start a game:&lt;br /&gt;
* Go to Play now and configure game type: Simple game -&amp;gt; Turn-based -&amp;gt; Manual&lt;br /&gt;
* Select your game and click on &amp;quot;Create&amp;quot;.&lt;br /&gt;
* If you want to play a game with 3 players, specify that you want a maximum of 3 players at this table.&lt;br /&gt;
* Click on &amp;quot;Express Start&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
=== Stopping a game in one click ===&lt;br /&gt;
&lt;br /&gt;
* Click on the &amp;quot;quit&amp;quot; icon on the top right of the screen.&lt;br /&gt;
* Click on &amp;quot;Express Stop&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
=== Switching between users ===&lt;br /&gt;
&lt;br /&gt;
When running a game on Studio, you can use the little red arrow near each player&#039;s name to open a new tab with this player&#039;s perspective.&lt;br /&gt;
You can also modify the URL to view the table as any user you want (changing &amp;amp;testuser=myid in the URL), allowing to easily test as a spectator.&lt;br /&gt;
&lt;br /&gt;
=== Access to game database and Logs ===&lt;br /&gt;
&lt;br /&gt;
At the bottom of the game area, there is section without a title containing 3 useful links:&lt;br /&gt;
&lt;br /&gt;
  Go to game database • BGA request&amp;amp;SQL logs • BGA unexpected exceptions logs&lt;br /&gt;
&lt;br /&gt;
* &amp;quot;Go to game database&amp;quot; link is an immediate access to the PhpMyAdmin tool to view/edit the tables of the current game&lt;br /&gt;
* BGA request&amp;amp;SQL logs - link to your studio PHP log - all tables, all severities. Anything you print using debugging and tracing functions from PHP and some framework logs&lt;br /&gt;
* BGA unexpected exceptions logs - same log as above but only severity warning and higher&lt;br /&gt;
&lt;br /&gt;
See [[Practical debugging]] for more info about it.&lt;br /&gt;
&lt;br /&gt;
=== Save &amp;amp; restore state ===&lt;br /&gt;
&lt;br /&gt;
Using links of this section, you can save the complete current (database) state of your game, then restore it later.&lt;br /&gt;
&lt;br /&gt;
This is particularly useful when you want to develop a part of the game that is difficult to reproduce: you just have to save the situation just before, and then restore it until this part works fine.&lt;br /&gt;
&lt;br /&gt;
We provide you 3 &amp;quot;slots&amp;quot;: 1, 2 and 3. This way, you can save 3 different game situations.&lt;br /&gt;
&lt;br /&gt;
Limits:&lt;br /&gt;
* the &amp;quot;restore&amp;quot; function does not work anymore when the game is over.&lt;br /&gt;
* a saved situation from a given table cannot be restored in another table.&lt;br /&gt;
* when you &amp;quot;restore&amp;quot; a situation, the current browser page is refreshed to reflect the updated game situation, but you have to refresh you other tabs/pages manually.&lt;br /&gt;
&lt;br /&gt;
=== Input/Output debugging section ===&lt;br /&gt;
&lt;br /&gt;
This section shows you:&lt;br /&gt;
* The AJAX calls made by your game interface to the game server. AJAX calls (outputs) begins with &amp;quot;&amp;gt;&amp;quot;&lt;br /&gt;
* The notifications received by your game interface. Notifications (inputs) begins with &amp;quot;&amp;lt;&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
Note: if you click on some notification title, you can resend it immediately to the user interface.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Run PHP functions from the chat ===&lt;br /&gt;
&lt;br /&gt;
On BGA Studio, you can directly run a PHP method from the table chat.&lt;br /&gt;
&lt;br /&gt;
For example, if on your PHP you have this method:&lt;br /&gt;
   &lt;br /&gt;
   function giveMoneyToPlayer($player_id, $amount) { ... }&lt;br /&gt;
&lt;br /&gt;
You can call this method directly from the chat like this: &lt;br /&gt;
&lt;br /&gt;
  giveMoneyToPlayer(2564,2)&lt;br /&gt;
&lt;br /&gt;
Note: this is not a real php statement, you cannot use self::, you cannot use &amp;quot;;&amp;quot; at the end and you cannot use quotes,&lt;br /&gt;
if you need to pass a string skip the quotes, like this&lt;br /&gt;
  &lt;br /&gt;
  giveToActivePlayer(money,2)&lt;br /&gt;
&lt;br /&gt;
=== Stopping Hanging Game ===&lt;br /&gt;
&lt;br /&gt;
If game is hanging and you cannot enter it to stop you can type this URL (replace 12345 with your table number),&lt;br /&gt;
which should bring you to a place where you can stop it without entering:&lt;br /&gt;
&lt;br /&gt;
  &amp;lt;nowiki&amp;gt;http://en.studio.boardgamearena.com/#!table?table=12345&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Desktop and Web Tools ==&lt;br /&gt;
=== Code Editors and IDEs ===&lt;br /&gt;
==== Eclipse For PHP Developers ====&lt;br /&gt;
&lt;br /&gt;
Eclipse PHP package can be starting point for development you need. You may also want to &lt;br /&gt;
install Tern JS plugins to understand dojo style JS. All desktops.&lt;br /&gt;
https://projects.eclipse.org/projects/tools.pdt&lt;br /&gt;
&lt;br /&gt;
==== Visual Studio Code ====&lt;br /&gt;
&lt;br /&gt;
Microsoft Visual Studio Code is light weight IDE/Editor. All desktops.&lt;br /&gt;
https://code.visualstudio.com&lt;br /&gt;
&lt;br /&gt;
==== Gedit (Ubuntu) ====&lt;br /&gt;
&#039;&#039;&#039;Edit TPL&#039;&#039;&#039;&lt;br /&gt;
To edit TPL with HTML code highlightings in Gedit under Ubuntu:&lt;br /&gt;
&lt;br /&gt;
find gtksourceview directory in /usr/share, depending on your version (2.0, 3.0,...).&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Here it&#039;s 3.0, then type in a terminal window:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    sudo gedit /usr/share/gtksourceview-3.0/language-specs/html.lang&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
then find &#039;globs&#039; section, and change:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    &amp;lt;property name=&amp;quot;globs&amp;quot;&amp;gt;*.html;*.htm;*.tpl&amp;lt;/property&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== File Sync ===&lt;br /&gt;
&lt;br /&gt;
==== File Sync on Windows ====&lt;br /&gt;
&lt;br /&gt;
Install [http://winscp.net/ WinSCP]. Map a remote directory to a local one and enable continuous sync (one way). You need SFTP password you get when you registered dev account.&lt;br /&gt;
&lt;br /&gt;
==== File Sync on Linux ====&lt;br /&gt;
&lt;br /&gt;
===== Option 1 - Nautilus (file manager) =====&lt;br /&gt;
You can just use Nautilus &amp;quot;connect to a server&amp;quot; function with URL sftp://1.studio.boardgamearena.com&lt;br /&gt;
Then you&#039;ll get a mounted local folder mapping your studio folder and you can use any editor you like without further need for sync. Downside - if connection goes down you cannot work on source code, no local copy.&lt;br /&gt;
&lt;br /&gt;
===== Option 2 - sftp and rsync =====&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#!/bin/bash&lt;br /&gt;
BASEDIR=`dirname $0`&lt;br /&gt;
REMOTE=$BASEDIR/remote&lt;br /&gt;
LOCAL=$BASEDIR/workspace&lt;br /&gt;
GAME=mygamenamehere&lt;br /&gt;
&lt;br /&gt;
#mount remote&lt;br /&gt;
fusermount -u $REMOTE #this unmounts dir&lt;br /&gt;
echo LongDevPassword | sshfs -o password_stdin myusernamehere@1.studio.boardgamearena.com: $REMOTE&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
#this starts auto-sync from local to remote mount&lt;br /&gt;
killall lsyncd&lt;br /&gt;
lsyncd -delay 1 -rsync $LOCAL/$GAME/ $REMOTE/$GAME&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This can be able run on startup, so you don&#039;t have to do anything manually. However sshfs is not very stable you&lt;br /&gt;
have to kill and restart it sometimes. And remote goes away sometimes due to connection issues with studio. &lt;br /&gt;
In this case its handy to have a local copy, which is what lsyncd for.&lt;br /&gt;
&lt;br /&gt;
You can also sync on demand (from a build script or editor command) using&lt;br /&gt;
 rsync -vlrt $LOCAL/$GAME/ $REMOTE/$GAME&lt;br /&gt;
&lt;br /&gt;
===== Option 3 - lftp =====&lt;br /&gt;
&lt;br /&gt;
[https://lftp.yar.ru/ lftp] is a fast command-line file transfer program. It&#039;s a much better choice than rsync for BGA Studio since it supports parallel threads, transferring multiple files at a time.&lt;br /&gt;
&lt;br /&gt;
* Linux: Install using your package manager, for example: &#039;&#039;&#039;sudo apt-get install lftp&#039;&#039;&#039;&lt;br /&gt;
* Mac: Install [https://brew.sh/ Homebrew], then install lftp using &#039;&#039;&#039;brew install lftp&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
To upload your project to BGA studio, use the &amp;quot;mirror&amp;quot; command like this:&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;lftp sftp://&amp;lt;span style=&amp;quot;color:blue&amp;quot;&amp;gt;myuser&amp;lt;/span&amp;gt;:&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;mypassword&amp;lt;/span&amp;gt;@1.studio.boardgamearena.com/ -e &amp;quot;mirror --reverse --parallel=10 --delete &amp;lt;span style=&amp;quot;color:orange&amp;quot;&amp;gt;/local/path/to/myproject&amp;lt;/span&amp;gt;/ &amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt;myproject&amp;lt;/span&amp;gt;/; exit&amp;quot;&lt;br /&gt;
&lt;br /&gt;
Be sure to include the trailing &#039;&#039;&#039;/&#039;&#039;&#039; after both directory names.&lt;br /&gt;
&lt;br /&gt;
By default, if a file already exists on BGA Studio with the same time + size it assumed to be the same and won&#039;t be transferred. This makes the transfer process much quicker after the first time. If you&#039;re working with multiple developers on the same project and you find that it is transfers all files every time, you may want to add the option &#039;&#039;&#039;--ignore-time&#039;&#039;&#039; (if a file already exist on BGA Studio with the same size it is assumed to be the same and won&#039;t be transferred). Read [https://lftp.yar.ru/lftp-man.html the manual] for more details.&lt;br /&gt;
&lt;br /&gt;
==== File Sync using VSCode ====&lt;br /&gt;
You might rely on your IDE to sync the files with the SFTP server. Each time you &amp;quot;save&amp;quot; a file with your modifications, the IDE will also submit it to the sFTP server. These are instructions for VS Code&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Install this extension&#039;&#039;&#039; https://marketplace.visualstudio.com/items?itemName=liximomo.sftp (File-&amp;gt;Preferences-&amp;gt;Extensions ... type SFTP and Install)&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Open VSCode on an empty folder&#039;&#039;&#039; that will be the local root of your project.&lt;br /&gt;
&lt;br /&gt;
* Execute Ctrl+Shift+P on Windows/Linux or Cmd+Shift+P on Mac to open the command palette, and the type/run : &#039;&#039;&#039;&amp;quot;SFTP: config&amp;quot;&#039;&#039;&#039; - the edit will open with json config&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Update the json&#039;&#039;&#039; as below: &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
    &amp;quot;name&amp;quot;: &amp;quot;BGA&amp;quot;,&lt;br /&gt;
    &amp;quot;host&amp;quot;: &amp;quot;1.studio.boardgamearena.com&amp;quot;,&lt;br /&gt;
    &amp;quot;protocol&amp;quot;: &amp;quot;sftp&amp;quot;,&lt;br /&gt;
    &amp;quot;port&amp;quot;: 22,&lt;br /&gt;
    &amp;quot;username&amp;quot;: &amp;quot;&amp;lt;your SFTP username&amp;gt;&amp;quot;,&lt;br /&gt;
    &amp;quot;password&amp;quot;: &amp;quot;&amp;lt;your SFTP password&amp;gt;&amp;quot;,&lt;br /&gt;
    &amp;quot;remotePath&amp;quot;: &amp;quot;/&amp;lt;your project name&amp;gt;/&amp;quot;,&lt;br /&gt;
    &amp;quot;uploadOnSave&amp;quot;: true,&lt;br /&gt;
    &amp;quot;ignore&amp;quot;: [&lt;br /&gt;
        &amp;quot;.vscode&amp;quot;,&lt;br /&gt;
        &amp;quot;.git&amp;quot;,&lt;br /&gt;
        &amp;quot;.DS_Store&amp;quot;&lt;br /&gt;
    ]&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
- Execute Ctrl+Shift+P on Windows/Linux or Cmd+Shift+P on Mac to open the command palette, and the type/run : &#039;&#039;&#039;&amp;quot;SFTP: Download Project&amp;quot;&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
This will download all the files locally, and each time you modify/save a file in VSCode, it will upload it to the SFTP Server.&lt;br /&gt;
&lt;br /&gt;
=== Debuggers ===&lt;br /&gt;
&lt;br /&gt;
Browser is the best tool for JS/HTML5 debugging, see [[Practical debugging]] for details.&lt;br /&gt;
&lt;br /&gt;
=== Version Control ===&lt;br /&gt;
Studio provides svn for you code on server, there are some limited abilities there to see history and restore. I recommend to also keep your code in another repository, which allows keeping more fine-grained history and can simplify collaboration.&lt;br /&gt;
&lt;br /&gt;
A quick option is to use a local repo, which you can sync to cloud or backup.&lt;br /&gt;
&lt;br /&gt;
Other option is to host source code on github. If you do, the convention is to use github.com/&amp;lt;yourname&amp;gt;/bga-&amp;lt;yourgame&amp;gt;. It is recommended to add the [https://github.com/topics/boardgamearena boardgamearena] tag and add your repo to the list on the [[BGA_Code_Sharing]] page.&lt;br /&gt;
&lt;br /&gt;
If you publish the source somewhere externally, make sure you &#039;&#039;&#039;don&#039;t post high-res publisher graphics&#039;&#039;&#039;, only web resources, and post a separate license for graphics files. Also, &#039;&#039;&#039;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;
&lt;br /&gt;
You can also configure github to automatically deploy to BGA whenever you push to a branch. See [https://forum.boardgamearena.com/viewtopic.php?f=12&amp;amp;t=13370&amp;amp;start=10#p59537 this forum post] for instructions.&lt;br /&gt;
&lt;br /&gt;
=== PHP CLI ===&lt;br /&gt;
Its handy to have php cli (command line) tools install to run php locally, so you can test some stuff without deployment cycle, or create some scripts that generate code or markup.&lt;br /&gt;
&lt;br /&gt;
=== Image Manipulation ===&lt;br /&gt;
==== ImageMagick ====&lt;br /&gt;
Handy set of image manipulation &#039;&#039;&#039;command line&#039;&#039;&#039; tools, useful to for example to stitch together bunch of images and re-size, to use as sprite (in Stock component for example). I.e. you got a graphics file from publisher where every tile is 600x600 PNG file in separate file. You want .jpg instead of .png to make it not like 20Mb, and combine all images in one column and re-size to 128x128:&lt;br /&gt;
&lt;br /&gt;
(Linux example)&lt;br /&gt;
 /usr/bin/montage  `ls Tiles*.png` -tile 1 -geometry 128x128+0+0 out/tiles128.jpg&lt;br /&gt;
&lt;br /&gt;
https://www.imagemagick.org/script/download.php&lt;br /&gt;
&lt;br /&gt;
==== Gimp ====&lt;br /&gt;
&lt;br /&gt;
GUI tool, very complex but will do ALL what you possibly need to do with game graphics&lt;br /&gt;
&lt;br /&gt;
https://www.gimp.org/&lt;br /&gt;
&lt;br /&gt;
==== Shrinking ====&lt;br /&gt;
&lt;br /&gt;
Shrink images without loss of quality https://tinypng.com/ or http://www.iloveimg.com/ &lt;br /&gt;
&lt;br /&gt;
==== PDF Scrapper ====&lt;br /&gt;
extract images from PDF file (i.e. game rulebook) :&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
https://www.ilovepdf.com/&lt;br /&gt;
&lt;br /&gt;
http://www.extractpdf.com/&lt;br /&gt;
&lt;br /&gt;
==== Rename/Copy project ====&lt;br /&gt;
&lt;br /&gt;
Edit: there is project override command now available on control panel on studio&lt;br /&gt;
&lt;br /&gt;
There is a script available in sharedcode project to do the renaming which can be called in command line if you have php command line installed.&lt;br /&gt;
You need to have php clt (command line interface) installed, then you can download script and run it.&lt;br /&gt;
&lt;br /&gt;
https://github.com/elaskavaia/bga-sharedcode/blob/master/misc/bgaprojectrename.php&lt;br /&gt;
&lt;br /&gt;
Usage:&lt;br /&gt;
 php bgaprojectrename.php &amp;lt;originalProjectPath&amp;gt; &amp;lt;copyOfProjectRenamedPath&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Example on how to call it in command line  if you project name is &amp;quot;heartsmyproject&amp;quot;&lt;br /&gt;
&lt;br /&gt;
 php7.0 git/bga-sharedcode/tools/bgaprojectrename.php remote/hearts/ remote/heartsmyproject/&lt;br /&gt;
&lt;br /&gt;
==== BGA Workbench ====&lt;br /&gt;
&lt;br /&gt;
PHP library providing tools to help manage BGA Studio projects including deployment and test utilities. https://github.com/danielholmes/bga-workbench&lt;br /&gt;
&lt;br /&gt;
== Client Tips ==&lt;br /&gt;
&lt;br /&gt;
=== Speed up game re-loading by disabling Input/Output debug section ===&lt;br /&gt;
&lt;br /&gt;
Development UI have few sections for debugging only, such as &#039;Input/Output debugging section&#039;. Loading this data will significantly slow down&lt;br /&gt;
your reload. I did some profiling and my reloading (i.e. F5) took 14 seconds, 12 of which it was dealing with loading this section. &lt;br /&gt;
If you not using it you can disable it. In your JavaScript code, in the begging of &#039;setup&#039; method add this code&lt;br /&gt;
&lt;br /&gt;
         dojo.destroy(&#039;debug_output&#039;);&lt;br /&gt;
&lt;br /&gt;
That should get rid of this section and overhead associated with loading it (it may have some other side-effects, I have not explored all of them)&lt;br /&gt;
&lt;br /&gt;
=== Speed up CSS development and layout ===&lt;br /&gt;
&lt;br /&gt;
Syncing files to server and refreshing is relative fast but still can take up to 20 seconds which is annoying.&lt;br /&gt;
If you working&lt;br /&gt;
a lot on css/images/layout you can speed it up by coping html in some state of the game to your local folder.&lt;br /&gt;
I.e. in your  project folder create directory misc/ and save your html as misc/test.html and changing path to css to load from local disk (and it will load your images to from local disk as well). &lt;br /&gt;
I.e. find something like&lt;br /&gt;
&lt;br /&gt;
  &amp;lt;link rel=&amp;quot;stylesheet&amp;quot; type=&amp;quot;text/css&amp;quot; href=&amp;quot;http://1.studio.boardgamearena.com:8081/data/themereleases/151226-1240/games/mygame/999999-9999/mygame.css&amp;quot;/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
and replace with&lt;br /&gt;
   &amp;lt;link rel=&amp;quot;stylesheet&amp;quot; type=&amp;quot;text/css&amp;quot; href=&amp;quot;../mygame.css&amp;quot;/&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
You project structure will look like this&lt;br /&gt;
&lt;br /&gt;
 mygame&lt;br /&gt;
   img/ &amp;lt;-- your images&lt;br /&gt;
   mygame.css  &amp;lt;-- your original css&lt;br /&gt;
   ...&lt;br /&gt;
   misc/&lt;br /&gt;
     test.html &amp;lt;-- your test html&lt;br /&gt;
&lt;br /&gt;
It is a bit tricky to save html exact state, if you do save as it also pulls all resources sometimes.&lt;/div&gt;</summary>
		<author><name>Tisaac</name></author>
	</entry>
	<entry>
		<id>https://en.doc.boardgamearena.com/index.php?title=Translations&amp;diff=6135</id>
		<title>Translations</title>
		<link rel="alternate" type="text/html" href="https://en.doc.boardgamearena.com/index.php?title=Translations&amp;diff=6135"/>
		<updated>2020-11-12T14:42:01Z</updated>

		<summary type="html">&lt;p&gt;Tisaac: &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;
== How translation works? ==&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;
Before the release of the game, BGA team will do the French translation of the game.&lt;br /&gt;
&lt;br /&gt;
After the release of the game, the BGA players community will translate the game in every language.&lt;br /&gt;
&lt;br /&gt;
== What should be translated? ==&lt;br /&gt;
&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;
This does NOT include error messages that are not supposed to happen (unexpected errors).&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 dot &#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 dot&lt;br /&gt;
** If a sentence is followed or could be followed by another sentence in the same interface space =&amp;gt; final dot.&lt;br /&gt;
&lt;br /&gt;
* In detail:&lt;br /&gt;
** No final dot:&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 action in the status bar&lt;br /&gt;
** Final dot:&lt;br /&gt;
*** complete explanation sentence, that can be chained with another sentence&lt;br /&gt;
** We can tolerate a dot or no dot (but it should be consistent inside the game) for:&lt;br /&gt;
*** isolated tooltip / isolated small sentence&lt;br /&gt;
*** game log (no dot is usually preferable)&lt;br /&gt;
*** error messages (except if more than one sentence in the error message =&amp;gt; final dot 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 English rulebook and game material of the game.&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;
== WARNING: how to make sure your strings will be translated ==&lt;br /&gt;
&lt;br /&gt;
For each game, our translation tool is doing a full scan of the code, looking for translator markers like &amp;quot;_()&amp;quot; or &amp;quot;clientranslate()&amp;quot;... (see below the list of translation markers).&lt;br /&gt;
&lt;br /&gt;
If your original string is not &amp;quot;physically&amp;quot; inside one of this marker, 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 bordered by 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 ) ); // Same thing&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== How to not make translators crazy ;) ==&lt;br /&gt;
&lt;br /&gt;
* When you need the same string twice, try to reuse exactly the same string (with the same case) to minimize the number of strings.&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;
* 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 more the string is a short insignificant string, the more difficult is the task for them. As a rule of thumb, try to avoid insignificant short strings. You can also leave a comment on what is the context of the string in the translation program (English to English) if you are the developer of the game.&lt;br /&gt;
* The BGA translation policy is to be flexible on grammar... We prefer to write &amp;quot;player gets 1 coin(s)&amp;quot; than write two versions of the same string for plural and singular - it reduces the number of strings to translate.&lt;br /&gt;
* Instead of writing nice strings like &amp;quot;With the effect of ZZZ, player XXX gets 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, i.e. &amp;quot;player gets wood&amp;quot; instead of &amp;quot;player got wood&amp;quot;&lt;br /&gt;
* Avoid using gender specific pronouns, i.e.  instead of &amp;quot;player returns card to *his* hand&amp;quot; use &amp;quot;player returns card to *their* hand&amp;quot; or just avoid using it, i.e. &amp;quot;player picks up the card&amp;quot;&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&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;
&#039;&#039;&#039;clienttranslate( &amp;quot;my string to translate&amp;quot; ):&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
This function is &#039;&#039;&#039;transparent&#039;&#039;&#039;: it will return the original English string without any change. It&#039;s 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;
* On your states.inc.php, for field &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;
* On &amp;quot;material.inc.php&amp;quot;, when defining texts for game material that must be displayed on client side.&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(&amp;quot;Amulet of Air&amp;quot;), // 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 &amp;quot;notifyAllPlayers&amp;quot; or &amp;quot;notifyPlayer&amp;quot;, for 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(&amp;quot;Everyone draw cards from his library&amp;quot;), array() );&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, i.e.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    notif=&amp;quot;foo&amp;quot;; self::notifyAllPlayers( &#039;log&#039;, clienttraslate(notif)); // BAD&lt;br /&gt;
    notif=clienttranslate(&amp;quot;foo&amp;quot;); self::notifyAllPlayers( &#039;log&#039;, notif); // GOOD&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Translating arguments is a little bit more complex. It is using the &amp;quot;i18n&amp;quot; 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 &#039;i18n&#039; argument when translating argument for client : do NOT use same argument for both translation AND key code for client side action (like using &#039;card_name&#039; to move it on 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 name 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 clienttranslate, 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;
&#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;
Most of the time, you don&#039;t need to translate strings on server side, except on the following 3 situations:&lt;br /&gt;
* When 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;
&lt;br /&gt;
// ... notice the use of BgaUserException that signals that this exception is &amp;quot;expected&amp;quot;. In theory, all exception that are expected should be translated.&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* In &amp;quot;yourgame.view.php&amp;quot;, when creating the labels for the game interface used in your template (.tpl) file.&lt;br /&gt;
&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;
* Eventually, 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;
* Eventually, 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;
&#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;
&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;
{&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;/div&gt;</summary>
		<author><name>Tisaac</name></author>
	</entry>
	<entry>
		<id>https://en.doc.boardgamearena.com/index.php?title=Gamehelpkingdombuilder&amp;diff=5706</id>
		<title>Gamehelpkingdombuilder</title>
		<link rel="alternate" type="text/html" href="https://en.doc.boardgamearena.com/index.php?title=Gamehelpkingdombuilder&amp;diff=5706"/>
		<updated>2020-09-22T19:14:25Z</updated>

		<summary type="html">&lt;p&gt;Tisaac: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Rules overview ==&lt;br /&gt;
Place three settlements per turn on the same terrain type shown on your card with the following constraint : if possible you &#039;&#039;&#039;must&#039;&#039;&#039; build adjacent to your existing settlements. Never forget this, managing adjacency is the key of this game.&lt;br /&gt;
&lt;br /&gt;
By building next to a castle, the player will earn gold at the end of the game, but the most gold will be earned by meeting the conditions of the three Kingdom Builder cards; these three cards (from a total of ten in the game) specify the conditions that must be met in order to earn the much-desired gold, such as earning gold for your settlements built next to water hexes or having the majority of settlements in a sector of the board.&lt;br /&gt;
&lt;br /&gt;
Building next to a location will grant you a corresponding tile (if there are any left, and if you did not already obtained a tile from this precise location) that you will be able to activate it from next turn on.&lt;br /&gt;
These extra actions can be activated at each turn either before or after your mandatory build of three settlements, and here is the action each location grants you :&lt;br /&gt;
 - Oracle : build one settlement on a hex of the same type as your played card, build adjacent if possible&lt;br /&gt;
 - Farm : build one settlement on grass, build adjacent if possible&lt;br /&gt;
 - Oasis : build one settlement on a desert hex, build adjacent if possible&lt;br /&gt;
 - Tower : build one settlement at the edge on the board, build ajacent if possible&lt;br /&gt;
 - Tavern : build one settlement at the end of a string of at least 3 of your own settlements. The orientation of the string does not matter. The chosen hex must be suitable for building.&lt;br /&gt;
 - Barn : move any one of your existing settlements to a hex of the same type as your played terrain card. Build ajacent if possible.&lt;br /&gt;
 - Harbor : move any one of your existing settlements to a water hex. Build ajacent if possible. This is the only way to build settlements on water hexes.&lt;br /&gt;
 - Paddock : move any one of your existing settlements two hexes in a straight line in any direction to an elligible hex. You may jump accross any terrain type hex, even moutain, water, castle, location and/or your own and other players&#039; settlement. The target must *not necessarily* be adjacent to one of your own settlements&lt;br /&gt;
&lt;br /&gt;
== Losing a tile ==&lt;br /&gt;
The player keeps a location tile as long as at least one of their settlements is adjacent to the corresponding location.&lt;br /&gt;
If they move their last settlement away from such a location by using an extra action (Barn, Harbor or Paddock), they must discard this location tile and remove it from the game.&lt;br /&gt;
Notice that after losing a tile from a location, a player cannot reobtain the tile from the same location since &#039;&#039;&#039;a player may seize only one location tile from a given location&#039;&#039;&#039;&lt;/div&gt;</summary>
		<author><name>Tisaac</name></author>
	</entry>
	<entry>
		<id>https://en.doc.boardgamearena.com/index.php?title=Gamehelpkingdombuilder&amp;diff=5705</id>
		<title>Gamehelpkingdombuilder</title>
		<link rel="alternate" type="text/html" href="https://en.doc.boardgamearena.com/index.php?title=Gamehelpkingdombuilder&amp;diff=5705"/>
		<updated>2020-09-22T19:10:09Z</updated>

		<summary type="html">&lt;p&gt;Tisaac: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Rules overview ==&lt;br /&gt;
Place three settlements per turn on the same terrain type shown on your card with the following constraint : if possible you *must* build adjacent to your existing settlements. Never forget this, managing adjacency is the key of this game.&lt;br /&gt;
&lt;br /&gt;
By building next to a castle, the player will earn gold at the end of the game, but the most gold will be earned by meeting the conditions of the three Kingdom Builder cards; these three cards (from a total of ten in the game) specify the conditions that must be met in order to earn the much-desired gold, such as earning gold for your settlements built next to water hexes or having the majority of settlements in a sector of the board.&lt;br /&gt;
&lt;br /&gt;
Building next to a location will grant you a corresponding tile (if there are any left, and if you did not already obtained a tile from this precise location) that you will be able to activate it from next turn on.&lt;br /&gt;
These extra actions can be activated at each turn either before or after your mandatory build of three settlements, and here is the action each location grants you :&lt;br /&gt;
 - Oracle : build one settlement on a hex of the same type as your played card, build adjacent if possible&lt;br /&gt;
 - Farm : build one settlement on grass, build adjacent if possible&lt;br /&gt;
 - Oasis : build one settlement on a desert hex, build adjacent if possible&lt;br /&gt;
 - Tower : build one settlement at the edge on the board, build ajacent if possible&lt;br /&gt;
 - Tavern : build one settlement at the end of a string of at least 3 of your own settlements. The orientation of the string does not matter. The chosen hex must be suitable for building.&lt;br /&gt;
 - Barn : move any one of your existing settlements to a hex of the same type as your played terrain card. Build ajacent if possible.&lt;br /&gt;
 - Harbor : move any one of your existing settlements to a water hex. Build ajacent if possible. This is the only way to build settlements on water hexes.&lt;br /&gt;
 - Paddock : move any one of your existing settlements two hexes in a straight line in any direction to an elligible hex. You may jump accross any terrain type hex, even moutain, water, castle, location and/or your own and other players&#039; settlement. The target must *not necessarily* be adjacent to one of your own settlements&lt;br /&gt;
&lt;br /&gt;
== Losing a tile ==&lt;br /&gt;
The player keeps a location tile as long as at least one of their settlements is adjacent to the corresponding location.&lt;br /&gt;
If they move their last settlement away from such a location by using an extra action (Barn, Harbor or Paddock), they must discard this location tile and remove it from the game.&lt;br /&gt;
Notice that after losing a tile from a location, a player cannot reobtain the tile from the same location since *a player may seize only one location tile from a given location*&lt;/div&gt;</summary>
		<author><name>Tisaac</name></author>
	</entry>
	<entry>
		<id>https://en.doc.boardgamearena.com/index.php?title=Gamehelpkingdombuilder&amp;diff=5704</id>
		<title>Gamehelpkingdombuilder</title>
		<link rel="alternate" type="text/html" href="https://en.doc.boardgamearena.com/index.php?title=Gamehelpkingdombuilder&amp;diff=5704"/>
		<updated>2020-09-22T19:04:00Z</updated>

		<summary type="html">&lt;p&gt;Tisaac: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Place three settlements per turn on the same terrain type shown on your card with the following constraint : if possible you *must* build adjacent to your existing settlements. Never forget this, managing adjacency is the key of this game.&lt;br /&gt;
&lt;br /&gt;
By building next to a castle, the player will earn gold at the end of the game, but the most gold will be earned by meeting the conditions of the three Kingdom Builder cards; these three cards (from a total of ten in the game) specify the conditions that must be met in order to earn the much-desired gold, such as earning gold for your settlements built next to water hexes or having the majority of settlements in a sector of the board.&lt;br /&gt;
&lt;br /&gt;
Building next to a location will grant you a corresponding tile (if there are any left, and if you did not already obtained a tile from this precise location) that you will be able to activate it from next turn on.&lt;br /&gt;
These extra actions can be activated either before or after your mandatory build of three settlements, and here is the action each location grants you :&lt;br /&gt;
 - Oracle : build one settlement on a hex of the same type as your played card, build adjacent if possible&lt;br /&gt;
 - Farm : build one settlement on grass, build adjacent if possible&lt;br /&gt;
 - Oasis : build one settlement on a desert hex, build adjacent if possible&lt;br /&gt;
 - Tower : build one settlement at the edge on the board, build ajacent if possible&lt;br /&gt;
 - Tavern : build one settlement at the end of a string of at least 3 of your own settlements. The orientation of the string does not matter. The chosen hex must be suitable for building.&lt;br /&gt;
 - Barn : move any one of your existing settlements to a hex of the same type as your played terrain card. Build ajacent if possible.&lt;br /&gt;
 - Harbor : move any one of your existing settlements to a water hex. Build ajacent if possible. This is the only way to build settlements on water hexes.&lt;br /&gt;
 - Paddock : move any one of your existing settlements two hexes in a straight line in any direction to an elligible hex. You may jump accross any terrain type hex, even moutain, water, castle, location and/or your own and other players&#039; settlement. The target must *not necessarily* be adjacent to one of your own settlements&lt;/div&gt;</summary>
		<author><name>Tisaac</name></author>
	</entry>
	<entry>
		<id>https://en.doc.boardgamearena.com/index.php?title=Fullguidesantorini&amp;diff=5524</id>
		<title>Fullguidesantorini</title>
		<link rel="alternate" type="text/html" href="https://en.doc.boardgamearena.com/index.php?title=Fullguidesantorini&amp;diff=5524"/>
		<updated>2020-09-08T11:09:45Z</updated>

		<summary type="html">&lt;p&gt;Tisaac: /* About Us */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==About Us==&lt;br /&gt;
Hi everyone. I (shcowcow) and my team is now developing a full guide of all gods in Santorini.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Image:Santorini-Apollo.jpeg]]&lt;br /&gt;
&lt;br /&gt;
==Link to Strategies==&lt;br /&gt;
Here are all the links to the strategies of each god.&lt;br /&gt;
* [[Tips santorini|Santorini Strategies]]&lt;br /&gt;
&lt;br /&gt;
===Simple Gods===&lt;br /&gt;
* [[SantoriniPowerApollo|Apollo: God of Music]]&lt;br /&gt;
* [[SantoriniPowerArtemis|Artemis: Goddess of the Hunt]]&lt;br /&gt;
* [[SantoriniPowerAthena|Athena: Goddess of Wisdom]]&lt;br /&gt;
* [[SantoriniPowerAtlas|Atlas: Titan Shouldering the Heavens]]&lt;br /&gt;
* [[SantoriniPowerDemeter|Demeter: Goddess of the Harvest]]&lt;br /&gt;
* [[SantoriniPowerHephaestus|Hephaestus: God of Blacksmiths]]&lt;br /&gt;
* [[SantoriniPowerHermes|Hermes: God of Travel]]&lt;br /&gt;
* [[SantoriniPowerMinotaur|Minotaur: Bull-headed Monster]]&lt;br /&gt;
* [[SantoriniPowerPan|Pan: God of the Wild]]&lt;br /&gt;
* [[SantoriniPowerPrometheus|Prometheus: Titan Benefactor of Mankind]]&lt;br /&gt;
&lt;br /&gt;
===Advanced Gods===&lt;br /&gt;
* [[SantoriniPowerAphrodite|Aphrodite: Goddess of Love]]&lt;br /&gt;
* [[SantoriniPowerAres|Ares: God of War]]&lt;br /&gt;
* [[SantoriniPowerBia|Bia: Goddess of Violence]]&lt;br /&gt;
* [[SantoriniPowerChaos|Chaos: Primordial Nothingness]]&lt;br /&gt;
* [[SantoriniPowerCharon|Charon: Ferryman to the Underworld]]&lt;br /&gt;
* [[SantoriniPowerChronus|Chronus: God of Time]]&lt;br /&gt;
* [[SantoriniPowerCirce|Circe: Divine Enchantress]]&lt;br /&gt;
* [[SantoriniPowerDionysus|Dionysus: God of Wine]]&lt;br /&gt;
* [[SantoriniPowerEros|Eros: God of Desire]]&lt;br /&gt;
* [[SantoriniPowerHera|Hera: Goddess of Marriage]]&lt;br /&gt;
* [[SantoriniPowerHestia|Hestia: Goddess of Hearth and Home]]&lt;br /&gt;
* [[SantoriniPowerHypnus|Hypnus: God of Sleep]]&lt;br /&gt;
* [[SantoriniPowerLimus|Limus: Goddess of Famine]]&lt;br /&gt;
* [[SantoriniPowerMedusa|Medusa: Petrifying Gorgon]]&lt;br /&gt;
* [[SantoriniPowerMorpheus|Morpheus: God of Dreams]]&lt;br /&gt;
* [[SantoriniPowerPersephone|Persephone: Goddess of Spring Growth]]&lt;br /&gt;
* [[SantoriniPowerPoseidon|Poseidon: God of the Sea]]&lt;br /&gt;
* [[SantoriniPowerSelene|Selene: Goddess of the Moon]]&lt;br /&gt;
* [[SantoriniPowerTriton|Triton: God of the Waves]]&lt;br /&gt;
* [[SantoriniPowerZeus|Zeus: God of the Sky]]&lt;br /&gt;
&lt;br /&gt;
===Golden Fleece Gods===&lt;br /&gt;
* [[SantoriniPowerClio|Clio: Muse of History]]&lt;br /&gt;
* [[SantoriniPowerEuropa|Europa &amp;amp; Talus: Queen and Guardian Automaton]]&lt;br /&gt;
* [[SantoriniPowerGaea|Gaea: Goddess of the Earth]]&lt;br /&gt;
* [[SantoriniPowerGraeae|Graeae: The Gray Hags]]&lt;br /&gt;
* [[SantoriniPowerHades|Hades: God of the Underworld]]&lt;br /&gt;
* [[SantoriniPowerHarpies|Harpies: Winged Menaces]]&lt;br /&gt;
* [[SantoriniPowerTerpsichore|Terpsichore: Muse of Dancing]]&lt;br /&gt;
* [[SantoriniPowerUrania|Urania: Muse of Astronomy]]&lt;br /&gt;
&lt;br /&gt;
===Promo Gods===&lt;br /&gt;
* [[SantoriniPowerAsteria|Asteria: Goddess of Falling Stars]]&lt;br /&gt;
* [[SantoriniPowerCastor|Castor &amp;amp; Pollux: Mortal and Divine Brothers]]&lt;br /&gt;
* [[SantoriniPowerEris|Eris: Goddess of Discord]]&lt;br /&gt;
* [[SantoriniPowerHippolyta|Hippolyta: Queen of the Amazons]]&lt;br /&gt;
* [[SantoriniPowerHydra|Hydra: Many Headed Monster]]&lt;br /&gt;
* [[SantoriniPowerIris|Iris: Goddess of Rainbow]]&lt;br /&gt;
* [[SantoriniPowerMaenads|Maenads: Raving Ones]]&lt;br /&gt;
* [[SantoriniPowerNyx|Nyx: Goddess of Night]]&lt;br /&gt;
* [[SantoriniPowerPegasus|Pegasus: Winged Horse]]&lt;br /&gt;
* [[SantoriniPowerProteus|Proteus: Shapeshifting Sea God]]&lt;br /&gt;
* [[SantoriniPowerScylla|Scylla: Menacing Sea Monster]]&lt;br /&gt;
* [[SantoriniPowerTyche|Tyche: Goddess of Fortune]]&lt;br /&gt;
&lt;br /&gt;
===Heroes===&lt;br /&gt;
* [[SantoriniPowerAchilles|Achilles: Volatile Warrior]]&lt;br /&gt;
* [[SantoriniPowerAdonis|Adonis: Devastalingly Handsome]]&lt;br /&gt;
* [[SantoriniPowerAtalanta|Atalanta: Swift Huntress]]&lt;br /&gt;
* [[SantoriniPowerBellerophon|Bellerophon: Tamer of Pegasus]]&lt;br /&gt;
* [[SantoriniPowerHeracles|Heracles: Doer of Great Deeds]]&lt;br /&gt;
* [[SantoriniPowerJason|Jason: Leader of the Argonauts]]&lt;br /&gt;
* [[SantoriniPowerMedea|Medea: Powerful Sorceress]]&lt;br /&gt;
* [[SantoriniPowerOdysseus|Odysseus: Cunning Leader]]&lt;br /&gt;
* [[SantoriniPowerPolyphemus|Polyphemus: Gigantic Cyclops]]&lt;br /&gt;
* [[SantoriniPowerTheseus|Theseus: Slayer of the Minotaur]]&lt;br /&gt;
&lt;br /&gt;
==Update Log==&lt;br /&gt;
* 5th Sept 2020 Update: Apollo&lt;br /&gt;
* 8th Sept 2020 Update: Artemis&lt;/div&gt;</summary>
		<author><name>Tisaac</name></author>
	</entry>
	<entry>
		<id>https://en.doc.boardgamearena.com/index.php?title=File:Santorini-Apollo.jpeg&amp;diff=5523</id>
		<title>File:Santorini-Apollo.jpeg</title>
		<link rel="alternate" type="text/html" href="https://en.doc.boardgamearena.com/index.php?title=File:Santorini-Apollo.jpeg&amp;diff=5523"/>
		<updated>2020-09-08T11:09:28Z</updated>

		<summary type="html">&lt;p&gt;Tisaac: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Tisaac</name></author>
	</entry>
	<entry>
		<id>https://en.doc.boardgamearena.com/index.php?title=SantoriniGuide&amp;diff=5407</id>
		<title>SantoriniGuide</title>
		<link rel="alternate" type="text/html" href="https://en.doc.boardgamearena.com/index.php?title=SantoriniGuide&amp;diff=5407"/>
		<updated>2020-09-01T09:26:38Z</updated>

		<summary type="html">&lt;p&gt;Tisaac: Guide to play Santorini&amp;#039;s power&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Hi everyone. I and my team is now developing a full guide of all gods in Santorini. We have done a few simple gods and would like to post it somewhere in BGA.&lt;br /&gt;
&lt;br /&gt;
However, BGAWiki would not be a good place since we have a full description of how to use the god and how to counter it. It would be too lengthy to happen on BGAWiki, since BGAWiki &amp;quot;strategy tips&amp;quot; gonna happen under our gameplay when we are playing.&lt;br /&gt;
&lt;br /&gt;
We would like to ask for some help about this, like can developer create a new page for us to put all the tutorial for all gods? It would be good since it is more user friendly that player can simply press on which god they would like to learn. We have thought of posting on this forum, but this is not really a good idea since it would then be hard for players to find a specific post of a god.&lt;br /&gt;
&lt;br /&gt;
I hope someone (even not developer) can give an advice in doing so! Thanks!&lt;br /&gt;
&lt;br /&gt;
Credit to ArielFriedrichGauss, YTBlueBlueberry&lt;/div&gt;</summary>
		<author><name>Tisaac</name></author>
	</entry>
</feed>