<?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=Professor+Tweak</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=Professor+Tweak"/>
	<link rel="alternate" type="text/html" href="https://en.doc.boardgamearena.com/Special:Contributions/Professor_Tweak"/>
	<updated>2026-09-27T12:04:08Z</updated>
	<subtitle>User contributions</subtitle>
	<generator>MediaWiki 1.39.0</generator>
	<entry>
		<id>https://en.doc.boardgamearena.com/index.php?title=BGA_Undo_policy&amp;diff=17481</id>
		<title>BGA Undo policy</title>
		<link rel="alternate" type="text/html" href="https://en.doc.boardgamearena.com/index.php?title=BGA_Undo_policy&amp;diff=17481"/>
		<updated>2023-07-16T06:43:23Z</updated>

		<summary type="html">&lt;p&gt;Professor Tweak: /* About Undo to avoid &amp;quot;misclick&amp;quot; */ fixed typo&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;br /&gt;
Introducing &amp;quot;Undo&amp;quot; features in games can lead to bugs and/or bad interface design.&lt;br /&gt;
&lt;br /&gt;
Please read the following carefully before implementing an Undo feature for your game.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
= What you must NEVER do =&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
When you are restoring a game situation A from a game situation B:&lt;br /&gt;
&lt;br /&gt;
* The Undo action must &#039;&#039;&#039;never change the active player&#039;&#039;&#039;. In other words, if player X clicks on &amp;quot;Undo&amp;quot;, it must NOT make player Y active.&lt;br /&gt;
* If several players did game actions between A and B, you must NEVER provide an undo. In other words, an &amp;quot;Undo&amp;quot; action must NEVER force another player to redo some moves.&lt;br /&gt;
* No hidden (or private) information must have been revealed between A and B.&lt;br /&gt;
* No random event with a visible effect must have been triggered between A and B. This includes cards shuffling, dice roll, elements picking, ...&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
= When to propose to Undo? =&lt;br /&gt;
&lt;br /&gt;
As a rule of thumb, on BGA we advise you to not undo moves.&lt;br /&gt;
&lt;br /&gt;
Undo are painful for opponents, in real world and online. Some players may also use Undo to &amp;quot;test&amp;quot; situations while they should just think instead.&lt;br /&gt;
&lt;br /&gt;
In many cases, proposing an &amp;quot;Undo&amp;quot; means also adding an extra step, which is not good for the game interface.&lt;br /&gt;
&lt;br /&gt;
Undo may be useful in 2 main situations:&lt;br /&gt;
* To allow players to take back a move following a &amp;quot;misclick&amp;quot; that may ruin their game.&lt;br /&gt;
* To allow players to take back a very complex series of actions.&lt;br /&gt;
&lt;br /&gt;
== About Undo to avoid &amp;quot;misclick&amp;quot; ==&lt;br /&gt;
&lt;br /&gt;
I most cases, you don&#039;t need this: players must pay attention :)&lt;br /&gt;
&lt;br /&gt;
However, if several of the following cases correspond to your situation, you may consider adding an Undo for &amp;quot;misclicks&amp;quot;:&lt;br /&gt;
&lt;br /&gt;
* If the &#039;&#039;&#039;zone to click is very small&#039;&#039;&#039;, or close to other zones, misclicks may happened frequently. Note that if this only happens on mobile, you can propose the Undo to mobile users only.&lt;br /&gt;
* If &#039;&#039;&#039;there is already another step&#039;&#039;&#039; after the step you want to undo. In this case, adding an &amp;quot;Undo&amp;quot; does not add an extra step.&lt;br /&gt;
* If you are in the middle of a real &amp;quot;game action&amp;quot;. For example, on Chess, it is normal to allow to undo the selection of a piece in order to select another one, as the move hasn&#039;t been done already.&lt;br /&gt;
* The action done by the player is obviously a mistake (in this case, please also consider adding a confirmation before the action).&lt;br /&gt;
&lt;br /&gt;
On the contrary, you must be reluctant to add an Undo if:&lt;br /&gt;
* This adds an extra step.&lt;br /&gt;
* The game action is clear and the zone to click is large.&lt;br /&gt;
&lt;br /&gt;
To conclude: we may allow a player to undo a move caused by a &amp;quot;misclick&amp;quot;, but we shouldn&#039;t allow a player to undo a bad move he plays consciously.&lt;br /&gt;
&lt;br /&gt;
Note: not all of these situations require server undo, in chess example above Undo of selection - you don&#039;t need to send piece selection to the server you can store it locally (this is &amp;quot;client side undo&amp;quot;), there is no Undo button in this case - user just selects another piece. Similary if you add prompt for clicking on critical buttons like &amp;quot;Pass&amp;quot; you can add extra prompt, but no Undo&lt;br /&gt;
&lt;br /&gt;
== About Undo to take back moves from a complex series of actions ==&lt;br /&gt;
&lt;br /&gt;
Games with a complex serie of actions are an &amp;quot;exception&amp;quot; to BGA Undo policy.&lt;br /&gt;
&lt;br /&gt;
In most games, you shouldn&#039;t provide an undo because players are not allowed to &amp;quot;explore&amp;quot; the different possibilities by playing and undoing their moves.&lt;br /&gt;
&lt;br /&gt;
However, in some games, it is commonly admitted that players are allowed to take back a move. The typical example is a complex strategy game with a long serie of actions during your turn. &amp;quot;Through the Ages&amp;quot; or &amp;quot;Tzolk&#039;in&amp;quot; are 2 good examples.&lt;br /&gt;
&lt;br /&gt;
To know if this is a good idea to propose an undo, ask yourself the question: &amp;quot;when playing in real life, will my opponents authorize me to take back this move?&amp;quot;. Depending on your answer, you should choose to provide an Undo, to not provide an Undo, or maybe to propose an Undo as an option for the game.&lt;br /&gt;
&lt;br /&gt;
Note: in this situation it is also possible to use client side undo, instead of server side, see &amp;quot;Russian Railroads&amp;quot; for example (implemented using setClientState method).&lt;br /&gt;
&lt;br /&gt;
= How to implement Undo =&lt;br /&gt;
&lt;br /&gt;
There are 2 ways to implement Undo:&lt;br /&gt;
* The framework undoSavePoint/undoRestorepoint methods, [[Main_game_logic:_yourgamename.game.php#Undo_moves | documented here]].&lt;br /&gt;
* Your own method.&lt;br /&gt;
&lt;br /&gt;
As a rule of thumb, it is way better to use your own method to provide an Undo. The reasons are:&lt;br /&gt;
* The framework method is quite heavy to use (it saves the WHOLE situation). To cancel a simple move, it is way more efficient for you to execute the opposite move.&lt;br /&gt;
* The framework method is doing a full &amp;quot;reset&amp;quot; of the game interface. It is way more smooth and clear to play the opposite move from a player point of view.&lt;br /&gt;
* The framework Undo provides only ONE save point. If you want to provide a complex Undo (i.e.: the possibility to undo all the previous steps one by one), you must implement it by yourself.&lt;br /&gt;
&lt;br /&gt;
However, the framework is very handy to use (only 2 methods), so this should be your first choice if some moves are very difficult to reverse on client side.&lt;br /&gt;
&lt;br /&gt;
== How does undoSavePoint/undoRestorepoint works? ==&lt;br /&gt;
&lt;br /&gt;
The undoSavePoint method makes a full copy of the game database state.&lt;br /&gt;
&lt;br /&gt;
The undoRestorePoint method:&lt;br /&gt;
* restores the game database&lt;br /&gt;
* removes all your game HTML + the player panels&lt;br /&gt;
* restores the game HTML + the player panels according to their state at the initial game loading&lt;br /&gt;
* calls your &amp;quot;setup&amp;quot; method&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Important&#039;&#039;&#039;: because undoRestorePoint is calling your &amp;quot;setup&amp;quot; method, you must ensure that your whole game state can be restored from there. In particular, all your member variables must be initialized inside the &amp;quot;setup&amp;quot; method (and not only in the constructor !).&lt;br /&gt;
&lt;br /&gt;
== Adding simple Undo action to your game ==&lt;br /&gt;
&lt;br /&gt;
=== Step 1: Declare in gameinfos ===&lt;br /&gt;
Add  &#039;db_undo_support&#039; =&amp;gt; true in gamesinfo.inc.php&lt;br /&gt;
&lt;br /&gt;
Note: if you have game in studio you must reload gameinfos and restart all these games&lt;br /&gt;
&lt;br /&gt;
=== Step 2: Insert savepoint ===&lt;br /&gt;
Determine where you want to save the undo state. Must be single active player state&lt;br /&gt;
* Begging of new user turn&lt;br /&gt;
* Every time new information revealed such as &lt;br /&gt;
** dice roll&lt;br /&gt;
** card is drawn&lt;br /&gt;
** anything else hidden is shown&lt;br /&gt;
&lt;br /&gt;
Insert&lt;br /&gt;
 $this-&amp;gt;undoSavepoint();&lt;br /&gt;
&lt;br /&gt;
=== Step 3: Create undo action in server ===&lt;br /&gt;
Add players undo action&lt;br /&gt;
in game.action.php:&lt;br /&gt;
    public function undo() {&lt;br /&gt;
        self::setAjaxMode();&lt;br /&gt;
        $this-&amp;gt;game-&amp;gt;action_undo();&lt;br /&gt;
        self::ajaxResponse();&lt;br /&gt;
    }&lt;br /&gt;
in game.game.php&lt;br /&gt;
    function action_undo() {&lt;br /&gt;
        $this-&amp;gt;undoRestorePoint(); // do not do checkAction - its on purpose - do not need to add undo as possible action to every state&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
=== Step 4: Create undo action in client ===&lt;br /&gt;
in game.js&lt;br /&gt;
add this to onUpdateActionButton regardless of state but inside isCurrenPlayerAction&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
			this.addActionButton(&#039;button_undo&#039;, _(&#039;Undo&#039;), &#039;onUndo&#039;, undefined, undefined, &#039;red&#039;);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
and onUndo would be like this&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    onUndo: function (event) {&lt;br /&gt;
      const action = &amp;quot;undo&amp;quot;;&lt;br /&gt;
      this.ajaxcall(&lt;br /&gt;
        &amp;quot;/&amp;quot; + this.game_name + &amp;quot;/&amp;quot; + this.game_name + &amp;quot;/&amp;quot; + action + &amp;quot;.html&amp;quot;,&lt;br /&gt;
        [],&lt;br /&gt;
        this,&lt;br /&gt;
        (result) =&amp;gt; {},&lt;br /&gt;
        (err) =&amp;gt; {&lt;br /&gt;
          if (err) return;&lt;br /&gt;
          this.setMainTitle(_(&amp;quot;Undo requested...&amp;quot;));&lt;br /&gt;
          dojo.empty(&amp;quot;generalactions&amp;quot;);&lt;br /&gt;
        },&lt;br /&gt;
        true&lt;br /&gt;
      );&lt;br /&gt;
    },&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Step 5: Make it fancy ===&lt;br /&gt;
If you want you can add extra styling to the Undo button such as it will appeat at right of all buttons&lt;br /&gt;
in game.css&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#button_undo {&lt;br /&gt;
    float: right;&lt;br /&gt;
    background-color: red;&lt;br /&gt;
    background-image: none;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Category:Studio]]&lt;/div&gt;</summary>
		<author><name>Professor Tweak</name></author>
	</entry>
</feed>