[iagno] Introduce Reverse Reversi.



commit 109e2f2363409c6355db4367127d2a9d9a2ef209
Author: Arnaud Bonatti <arnaud bonatti gmail com>
Date:   Sun Aug 11 20:57:13 2019 +0200

    Introduce Reverse Reversi.

 COPYING.images                     |   9 +
 data/iagno.css                     |  25 +-
 data/iagno.gresource.xml           |   7 +-
 data/new-game-screen.css           | 128 +++++++++
 data/org.gnome.Reversi.gschema.xml |  11 +
 data/reverse.png                   | Bin 0 -> 88475 bytes
 data/reversi.png                   | Bin 0 -> 95732 bytes
 data/schema.svg                    | 567 +++++++++++++++++++++++++++++++++++++
 data/ui/iagno-screens.ui           | 271 ------------------
 data/ui/new-game-screen.ui         | 135 +++++++++
 src/computer-reversi.vala          | 306 ++++++++++++++++++--
 src/game.vala                      |   7 +-
 src/iagno.vala                     | 178 ++++++++++--
 src/new-game-screen.vala           | 251 ++++++++--------
 src/test-iagno.vala                |   2 +-
 15 files changed, 1440 insertions(+), 457 deletions(-)
---
diff --git a/COPYING.images b/COPYING.images
new file mode 100644
index 0000000..1a1c8d1
--- /dev/null
+++ b/COPYING.images
@@ -0,0 +1,9 @@
+The files data/reverse.png, data/reversi.png, data/schema.svg are licensed
+under the Creative Commons “Attribution-Share Alike 3.0 Unported” license:
+  summary: https://creativecommons.org/licenses/by-sa/3.0/deed.en
+  license: https://creativecommons.org/licenses/by-sa/3.0/legalcode
+because they include a remix of the file Antu_games-highscores.svg seen on
+  webpage: https://commons.wikimedia.org/wiki/File:Antu_games-highscores.svg
+  creator: Fabián Alexis <fabian alexis openmailbox org>.
+
+Other images files are released under the same license as the application.
diff --git a/data/iagno.css b/data/iagno.css
index 4e8223c..f5092f8 100644
--- a/data/iagno.css
+++ b/data/iagno.css
@@ -23,16 +23,12 @@ button.unfullscreen-button {
   margin:6px;
 }
 
-.main-box {
-  padding:1.5rem;
-}
-
 .extra-thin-window.thin-window button.history-button  { padding-left:12px; padding-right:12px; transition: 
padding 0 ease; }
 .extra-thin-window.thin-window button.new-game-button { padding-left:12px; padding-right:12px; transition: 
padding 0 ease;
 /* hack: fix the double spacing around the centerwidget box, on extra-thin window */
                                                         margin-right:-12px; }
 /*\
-* * new-game screen generics
+* * board generics; TODO move in game-window.css
 \*/
 
                                .game-box                { transition:padding 0.3s; padding:1.5rem; }
@@ -41,6 +37,10 @@ button.unfullscreen-button {
                   .flat-window .game-box                {                          padding:0.5rem; }
 .extra-flat-window.flat-window .game-box                {                          padding:0.4rem; }
 
+/*\
+* * start-game button; TODO move in game-window.css
+\*/
+
                                button.start-game-button { margin-top:1.5rem; margin-bottom:0.5rem;
                                                transition:margin-top 0 ease, margin-bottom 0 ease; }
                   .flat-window button.start-game-button { margin-top:0.5rem;                       }
@@ -48,10 +48,6 @@ button.unfullscreen-button {
 
 .extra-thin-window             button.start-game-button { margin-top:1.0rem; }
 
-/*\
-* * options buttons
-\*/
-
 .extra-flat-window button.start-game-button {
   min-height:2rem;
 }
@@ -66,10 +62,6 @@ button.unfullscreen-button {
 * * labels' tweaks
 \*/
 
-label.bold-label {
-  font-weight: bold;
-}
-
 /* "Default" theme is in italic */
 popover > stack > box:nth-child(2) > box > box > box:first-child > modelbutton:first-child > box > label {
   font-style:italic;
@@ -86,6 +78,13 @@ popover modelbutton {
              margin    0.3s ease;
 }
 
+/*\
+* * games buttons
+\*/
+
+button.radio-like-toggle#radio-one { background-image: 
url("resource://org/gnome/Reversi/images/reversi.png"); }
+button.radio-like-toggle#radio-two { background-image: 
url("resource://org/gnome/Reversi/images/reverse.png"); }
+
 /*\
 * * the end
 \*/
diff --git a/data/iagno.gresource.xml b/data/iagno.gresource.xml
index 4c4b563..246be62 100644
--- a/data/iagno.gresource.xml
+++ b/data/iagno.gresource.xml
@@ -1,5 +1,9 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <gresources>
+  <gresource prefix="/org/gnome/Reversi/images">
+    <file preprocess="to-pixdata" alias="reverse.png">../data/reverse.png</file>
+    <file preprocess="to-pixdata" alias="reversi.png">../data/reversi.png</file>
+  </gresource>
   <gresource prefix="/org/gnome/Reversi/ui">
     <file preprocess="xml-stripblanks" compressed="true" alias="adaptative-window.ui"       
ui/adaptative-window.ui</file>
     <file preprocess="xml-stripblanks" compressed="true" alias="base-headerbar.ui"          
ui/base-headerbar.ui</file>
@@ -8,7 +12,8 @@
     <file preprocess="xml-stripblanks" compressed="true" alias="base-window.ui"             
ui/base-window.ui</file>
     <file preprocess="xml-stripblanks" compressed="true" alias="game-headerbar.ui"          
ui/game-headerbar.ui</file>
     <file compressed="true">iagno.css</file>
-    <file preprocess="xml-stripblanks" compressed="true" alias="iagno-screens.ui"           
ui/iagno-screens.ui</file>
+    <file compressed="true">new-game-screen.css</file>
+    <file preprocess="xml-stripblanks" compressed="true" alias="new-game-screen.ui"         
ui/new-game-screen.ui</file>
     <file preprocess="xml-stripblanks" compressed="true" alias="notifications-revealer.ui"  
ui/notifications-revealer.ui</file>
     <file>noise.png</file>
     <file preprocess="xml-stripblanks" compressed="true" alias="overlayed-list.ui"          
ui/overlayed-list.ui</file>
diff --git a/data/new-game-screen.css b/data/new-game-screen.css
new file mode 100644
index 0000000..bc26727
--- /dev/null
+++ b/data/new-game-screen.css
@@ -0,0 +1,128 @@
+/*
+  This file is part of a GNOME game.
+
+  This application is free software: you can redistribute it and/or modify
+  it under the terms of the GNU General Public License as published by
+  the Free Software Foundation, either version 3 of the License, or
+  (at your option) any later version.
+
+  This application is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+  GNU General Public License for more details.
+
+  You should have received a copy of the GNU General Public License along
+  with this application.  If not, see <https://www.gnu.org/licenses/>.
+*/
+
+                               .new-game-screen { padding:0.5rem; }
+.extra-flat-window.flat-window .new-game-screen { padding:0.4rem; }
+
+button.radio-like-toggle,
+button.menubutton-like-combo {
+  border-radius:15px;
+  -gtk-outline-radius:13px;
+}
+
+.extra-thin-window label.section-header { margin-top:1.0rem; }  /* like start-game button */
+
+/*\
+* * games buttons
+\*/
+
+                                                       button.radio-like-toggle:backdrop { color: 
@theme_unfocused_fg_color; }
+                                                       button.radio-like-toggle          { color: 
@theme_fg_color;
+
+  background-repeat:no-repeat;
+  background-color:transparent;
+  min-width:10rem;
+
+  background-size:12rem;
+  background-position:center bottom;
+  min-height:13rem;
+  padding:0.5rem 1rem 1rem 1rem;
+}
+
+                                   .extra-thin-window  button.radio-like-toggle {
+  background-size:5rem;
+  background-position:0.4rem center;
+  min-height:3rem;
+  padding:1.8rem 0.6rem 1rem 5rem;
+}
+
+                  .flat-window:not(.extra-thin-window) button.radio-like-toggle {
+  background-size:8rem;              /*
+  background-position:center bottom; */
+  min-height:9rem;                   /*
+  padding:0.5rem 1rem 1rem 1rem;     */
+}
+
+.extra-flat-window.flat-window                         button.radio-like-toggle {
+  background-size:3rem;
+  background-position:0.3rem center;
+  min-height:2rem;
+  padding:0.6rem 0.5rem 0.5rem 4rem;
+}
+
+                                                       button.radio-like-toggle label { 
padding-bottom:10rem; }
+                                   .extra-thin-window  button.radio-like-toggle label { padding-bottom: 
1rem; }
+                  .flat-window:not(.extra-thin-window) button.radio-like-toggle label { padding-bottom: 
6rem; }
+.extra-flat-window.flat-window                         button.radio-like-toggle label { padding-bottom: 
0rem; }
+
+/* transitions */
+
+                                   .extra-thin-window  button.radio-like-toggle,
+                       .flat-window.extra-thin-window  button.radio-like-toggle,
+     .extra-flat-window.flat-window.extra-thin-window  button.radio-like-toggle,
+                 .flat-window                          button.radio-like-toggle,
+      window:not(.flat-window):not(.extra-thin-window) button.radio-like-toggle {
+  transition:background-size     0.3s,
+             min-height          0.3s,
+             padding             0.3s;
+}
+                                   .extra-thin-window  button.radio-like-toggle label,
+                       .flat-window.extra-thin-window  button.radio-like-toggle label,
+     .extra-flat-window.flat-window.extra-thin-window  button.radio-like-toggle label,
+                 .flat-window                          button.radio-like-toggle label,
+      window:not(.flat-window):not(.extra-thin-window) button.radio-like-toggle label {
+  transition:padding-bottom      0.3s ease 0.01s;
+}
+
+/* hack: 0.01s delay helps fixing the race between CSS and box orientation changes (warning if a label gets 
out of view) */
+                                                       button.radio-like-toggle {
+  transition-delay:                        0.01s;
+  transition-timing-function:         ease;
+}
+
+/*\
+* * menubuttons
+\*/
+
+/* copying start-game button */
+
+.extra-flat-window button.menubutton-like-combo {
+  min-height:2rem;
+}
+                   button.menubutton-like-combo {
+  min-height:3rem;
+  min-width:11rem;
+
+  transition:min-height          0.3s ease 0.01s;
+}
+
+/* styling */
+
+button.menubutton-like-combo:checked,
+button.menubutton-like-combo:hover {
+  color:#2e3436; /* gtk-contained.css’ theme_fg_color */
+  background:-gtk-gradient (radial, center center, 0, center center, 0.5, from(rgba (255, 255, 255, 1)), 
to(rgba (255, 255, 255, 0)));
+}
+button.menubutton-like-combo:checked:backdrop,
+button.menubutton-like-combo:hover:backdrop {
+  color:@theme_unfocused_fg_color;
+  background:-gtk-gradient (radial, center center, 0, center center, 0.5, from(rgba (255, 255, 255, 0.3)), 
to(rgba (255, 255, 255, 0)));
+}
+
+/*\
+* * the end
+\*/
diff --git a/data/org.gnome.Reversi.gschema.xml b/data/org.gnome.Reversi.gschema.xml
index d46c30d..d8c7b9b 100644
--- a/data/org.gnome.Reversi.gschema.xml
+++ b/data/org.gnome.Reversi.gschema.xml
@@ -34,6 +34,10 @@
     </key>
   </schema>
 
+  <enum id="org.gnome.Reversi.GameType">
+    <value value="0" nick="classic"/>
+    <value value="1" nick="reverse"/>
+  </enum>
   <enum id="org.gnome.Reversi.Color">
     <value value="0" nick="dark"/>
     <value value="1" nick="light"/>
@@ -83,5 +87,12 @@
       <!-- Translators: description of a settings key, see 'dconf-editor /org/gnome/iagno/sound' -->
       <description>Whether or not to play event sounds.</description>
     </key>
+    <key name="type" enum="org.gnome.Reversi.GameType">
+      <default>'classic'</default>
+      <!-- Translators: summary of a settings key, see 'dconf-editor /org/gnome/iagno/type' -->
+      <summary>Name of the game</summary>
+      <!-- Translators: description of a settings key, see 'dconf-editor /org/gnome/iagno/type' -->
+      <description>The name of the game that will be played. It could be “classic” (the usual game, where 
you try to have more pieces), or “reverse” (the opposite game, where you try to have less 
pieces).</description>
+    </key>
   </schema>
 </schemalist>
diff --git a/data/reverse.png b/data/reverse.png
new file mode 100644
index 0000000..ad7d7c6
Binary files /dev/null and b/data/reverse.png differ
diff --git a/data/reversi.png b/data/reversi.png
new file mode 100644
index 0000000..c7b5681
Binary files /dev/null and b/data/reversi.png differ
diff --git a/data/schema.svg b/data/schema.svg
new file mode 100644
index 0000000..63f88f3
--- /dev/null
+++ b/data/schema.svg
@@ -0,0 +1,567 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+   xmlns:dc="http://purl.org/dc/elements/1.1/";
+   xmlns:cc="http://creativecommons.org/ns#";
+   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#";
+   xmlns:svg="http://www.w3.org/2000/svg";
+   xmlns="http://www.w3.org/2000/svg";
+   xmlns:xlink="http://www.w3.org/1999/xlink";
+   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd";
+   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape";
+   width="1000"
+   height="1000"
+   viewBox="0 0 264.58333 264.58334"
+   version="1.1"
+   id="svg8"
+   sodipodi:docname="schema.svg"
+   inkscape:version="0.92.4 (unknown)"
+   inkscape:export-filename="/home/aton/jhbuild/checkout/iagno/data/schema.svg.png"
+   inkscape:export-xdpi="96"
+   inkscape:export-ydpi="96">
+  <defs
+     id="defs2">
+    <clipPath
+       id="clipPath6584">
+      <path
+         id="path6582"
+         d="m-7 1024.36h34v34h-34z"
+         fill-opacity=".514"
+         fill="#00f" />
+    </clipPath>
+    <clipPath
+       id="clipPath6588">
+      <path
+         id="path6586"
+         d="m-6 1028.36h32v32h-32z"
+         fill-opacity=".472"
+         fill="#aade87" />
+    </clipPath>
+  </defs>
+  <sodipodi:namedview
+     id="base"
+     pagecolor="#ffffff"
+     bordercolor="#666666"
+     borderopacity="1.0"
+     inkscape:pageopacity="0.0"
+     inkscape:pageshadow="2"
+     inkscape:zoom="0.35"
+     inkscape:cx="710"
+     inkscape:cy="331.42857"
+     inkscape:document-units="mm"
+     inkscape:current-layer="layer1"
+     showgrid="false"
+     units="px"
+     inkscape:window-width="1366"
+     inkscape:window-height="704"
+     inkscape:window-x="0"
+     inkscape:window-y="27"
+     inkscape:window-maximized="1" />
+  <metadata
+     id="metadata5">
+    <rdf:RDF>
+      <cc:Work
+         rdf:about="">
+        <dc:format>image/svg+xml</dc:format>
+        <dc:type
+           rdf:resource="http://purl.org/dc/dcmitype/StillImage"; />
+        <dc:title></dc:title>
+      </cc:Work>
+    </rdf:RDF>
+  </metadata>
+  <g
+     inkscape:label="Calque 1"
+     inkscape:groupmode="layer"
+     id="layer1"
+     transform="translate(0,-32.41665)">
+    <circle
+       id="path18"
+       cx="20"
+       cy="276.99997"
+       style="stroke-width:0.3175"
+       r="12"
+       inkscape:tile-cx="20"
+       inkscape:tile-cy="244.58332"
+       inkscape:tile-w="20"
+       inkscape:tile-h="20"
+       inkscape:tile-x0="9.9999999"
+       inkscape:tile-y0="234.58332" />
+    <use
+       x="0"
+       y="0"
+       inkscape:tiled-clone-of="#path18"
+       xlink:href="#path18"
+       transform="translate(32)"
+       id="use6294" />
+    <use
+       x="0"
+       y="0"
+       inkscape:tiled-clone-of="#path18"
+       xlink:href="#path18"
+       transform="translate(63.999999)"
+       id="use6296" />
+    <use
+       x="0"
+       y="0"
+       inkscape:tiled-clone-of="#path18"
+       xlink:href="#path18"
+       transform="translate(95.999999)"
+       id="use6298" />
+    <use
+       x="0"
+       y="0"
+       inkscape:tiled-clone-of="#path18"
+       xlink:href="#path18"
+       transform="translate(128)"
+       id="use6300" />
+    <use
+       x="0"
+       y="0"
+       inkscape:tiled-clone-of="#path18"
+       xlink:href="#path18"
+       transform="translate(160)"
+       id="use6302" />
+    <use
+       x="0"
+       y="0"
+       inkscape:tiled-clone-of="#path18"
+       xlink:href="#path18"
+       transform="translate(192)"
+       id="use6304" />
+    <use
+       x="0"
+       y="0"
+       inkscape:tiled-clone-of="#path18"
+       xlink:href="#path18"
+       transform="translate(224)"
+       id="use6306" />
+    <use
+       x="0"
+       y="0"
+       inkscape:tiled-clone-of="#path18"
+       xlink:href="#path18"
+       transform="translate(0,-32)"
+       id="use6308" />
+    <use
+       x="0"
+       y="0"
+       inkscape:tiled-clone-of="#path18"
+       xlink:href="#path18"
+       transform="translate(32,-32)"
+       id="use6310" />
+    <use
+       x="0"
+       y="0"
+       inkscape:tiled-clone-of="#path18"
+       xlink:href="#path18"
+       transform="translate(63.999999,-32)"
+       id="use6312" />
+    <use
+       x="0"
+       y="0"
+       inkscape:tiled-clone-of="#path18"
+       xlink:href="#path18"
+       transform="translate(95.999999,-32)"
+       id="use6314" />
+    <use
+       x="0"
+       y="0"
+       inkscape:tiled-clone-of="#path18"
+       xlink:href="#path18"
+       transform="translate(128,-32)"
+       id="use6316" />
+    <use
+       x="0"
+       y="0"
+       inkscape:tiled-clone-of="#path18"
+       xlink:href="#path18"
+       transform="translate(160,-32)"
+       id="use6318" />
+    <use
+       x="0"
+       y="0"
+       inkscape:tiled-clone-of="#path18"
+       xlink:href="#path18"
+       transform="translate(192,-32)"
+       id="use6320" />
+    <use
+       x="0"
+       y="0"
+       inkscape:tiled-clone-of="#path18"
+       xlink:href="#path18"
+       transform="translate(224,-32)"
+       id="use6322" />
+    <use
+       x="0"
+       y="0"
+       inkscape:tiled-clone-of="#path18"
+       xlink:href="#path18"
+       transform="translate(0,-63.999999)"
+       id="use6324" />
+    <use
+       x="0"
+       y="0"
+       inkscape:tiled-clone-of="#path18"
+       xlink:href="#path18"
+       transform="translate(32,-63.999999)"
+       id="use6326" />
+    <use
+       x="0"
+       y="0"
+       inkscape:tiled-clone-of="#path18"
+       xlink:href="#path18"
+       transform="translate(63.999999,-63.999999)"
+       id="use6328" />
+    <use
+       x="0"
+       y="0"
+       inkscape:tiled-clone-of="#path18"
+       xlink:href="#path18"
+       transform="translate(95.999999,-63.999999)"
+       id="use6330" />
+    <use
+       x="0"
+       y="0"
+       inkscape:tiled-clone-of="#path18"
+       xlink:href="#path18"
+       transform="translate(128,-63.999999)"
+       id="use6332" />
+    <use
+       x="0"
+       y="0"
+       inkscape:tiled-clone-of="#path18"
+       xlink:href="#path18"
+       transform="translate(160,-63.999999)"
+       id="use6334" />
+    <use
+       x="0"
+       y="0"
+       inkscape:tiled-clone-of="#path18"
+       xlink:href="#path18"
+       transform="translate(192,-63.999999)"
+       id="use6336" />
+    <use
+       x="0"
+       y="0"
+       inkscape:tiled-clone-of="#path18"
+       xlink:href="#path18"
+       transform="translate(224,-63.999999)"
+       id="use6338" />
+    <use
+       x="0"
+       y="0"
+       inkscape:tiled-clone-of="#path18"
+       xlink:href="#path18"
+       transform="translate(0,-95.999999)"
+       id="use6340" />
+    <use
+       x="0"
+       y="0"
+       inkscape:tiled-clone-of="#path18"
+       xlink:href="#path18"
+       transform="translate(32,-95.999999)"
+       id="use6342" />
+    <use
+       x="0"
+       y="0"
+       inkscape:tiled-clone-of="#path18"
+       xlink:href="#path18"
+       transform="translate(63.999999,-95.999999)"
+       id="use6344" />
+    <use
+       x="0"
+       y="0"
+       inkscape:tiled-clone-of="#path18"
+       xlink:href="#path18"
+       transform="translate(95.999999,-95.999999)"
+       id="use6346" />
+    <use
+       x="0"
+       y="0"
+       inkscape:tiled-clone-of="#path18"
+       xlink:href="#path18"
+       transform="translate(128,-95.999999)"
+       id="use6348" />
+    <use
+       x="0"
+       y="0"
+       inkscape:tiled-clone-of="#path18"
+       xlink:href="#path18"
+       transform="translate(160,-95.999999)"
+       id="use6350" />
+    <use
+       x="0"
+       y="0"
+       inkscape:tiled-clone-of="#path18"
+       xlink:href="#path18"
+       transform="translate(192,-95.999999)"
+       id="use6352" />
+    <use
+       x="0"
+       y="0"
+       inkscape:tiled-clone-of="#path18"
+       xlink:href="#path18"
+       transform="translate(224,-95.999999)"
+       id="use6354" />
+    <use
+       x="0"
+       y="0"
+       inkscape:tiled-clone-of="#path18"
+       xlink:href="#path18"
+       transform="translate(0,-128)"
+       id="use6356" />
+    <use
+       x="0"
+       y="0"
+       inkscape:tiled-clone-of="#path18"
+       xlink:href="#path18"
+       transform="translate(32,-128)"
+       id="use6358" />
+    <use
+       x="0"
+       y="0"
+       inkscape:tiled-clone-of="#path18"
+       xlink:href="#path18"
+       transform="translate(63.999999,-128)"
+       id="use6360" />
+    <use
+       x="0"
+       y="0"
+       inkscape:tiled-clone-of="#path18"
+       xlink:href="#path18"
+       transform="translate(95.999999,-128)"
+       id="use6362" />
+    <use
+       x="0"
+       y="0"
+       inkscape:tiled-clone-of="#path18"
+       xlink:href="#path18"
+       transform="translate(128,-128)"
+       id="use6364" />
+    <use
+       x="0"
+       y="0"
+       inkscape:tiled-clone-of="#path18"
+       xlink:href="#path18"
+       transform="translate(160,-128)"
+       id="use6366" />
+    <use
+       x="0"
+       y="0"
+       inkscape:tiled-clone-of="#path18"
+       xlink:href="#path18"
+       transform="translate(192,-128)"
+       id="use6368" />
+    <use
+       x="0"
+       y="0"
+       inkscape:tiled-clone-of="#path18"
+       xlink:href="#path18"
+       transform="translate(224,-128)"
+       id="use6370" />
+    <use
+       x="0"
+       y="0"
+       inkscape:tiled-clone-of="#path18"
+       xlink:href="#path18"
+       transform="translate(0,-160)"
+       id="use6372" />
+    <use
+       x="0"
+       y="0"
+       inkscape:tiled-clone-of="#path18"
+       xlink:href="#path18"
+       transform="translate(32,-160)"
+       id="use6374" />
+    <use
+       x="0"
+       y="0"
+       inkscape:tiled-clone-of="#path18"
+       xlink:href="#path18"
+       transform="translate(63.999999,-160)"
+       id="use6376" />
+    <use
+       x="0"
+       y="0"
+       inkscape:tiled-clone-of="#path18"
+       xlink:href="#path18"
+       transform="translate(95.999999,-160)"
+       id="use6378" />
+    <use
+       x="0"
+       y="0"
+       inkscape:tiled-clone-of="#path18"
+       xlink:href="#path18"
+       transform="translate(128,-160)"
+       id="use6380" />
+    <use
+       x="0"
+       y="0"
+       inkscape:tiled-clone-of="#path18"
+       xlink:href="#path18"
+       transform="translate(160,-160)"
+       id="use6382" />
+    <use
+       x="0"
+       y="0"
+       inkscape:tiled-clone-of="#path18"
+       xlink:href="#path18"
+       transform="translate(192,-160)"
+       id="use6384" />
+    <use
+       x="0"
+       y="0"
+       inkscape:tiled-clone-of="#path18"
+       xlink:href="#path18"
+       transform="translate(224,-160)"
+       id="use6386" />
+    <use
+       x="0"
+       y="0"
+       inkscape:tiled-clone-of="#path18"
+       xlink:href="#path18"
+       transform="translate(0,-192)"
+       id="use6388" />
+    <use
+       x="0"
+       y="0"
+       inkscape:tiled-clone-of="#path18"
+       xlink:href="#path18"
+       transform="translate(32,-192)"
+       id="use6390" />
+    <use
+       x="0"
+       y="0"
+       inkscape:tiled-clone-of="#path18"
+       xlink:href="#path18"
+       transform="translate(63.999999,-192)"
+       id="use6392" />
+    <use
+       x="0"
+       y="0"
+       inkscape:tiled-clone-of="#path18"
+       xlink:href="#path18"
+       transform="translate(95.999999,-192)"
+       id="use6394" />
+    <use
+       x="0"
+       y="0"
+       inkscape:tiled-clone-of="#path18"
+       xlink:href="#path18"
+       transform="translate(128,-192)"
+       id="use6396" />
+    <use
+       x="0"
+       y="0"
+       inkscape:tiled-clone-of="#path18"
+       xlink:href="#path18"
+       transform="translate(160,-192)"
+       id="use6398" />
+    <use
+       x="0"
+       y="0"
+       inkscape:tiled-clone-of="#path18"
+       xlink:href="#path18"
+       transform="translate(192,-192)"
+       id="use6400" />
+    <use
+       x="0"
+       y="0"
+       inkscape:tiled-clone-of="#path18"
+       xlink:href="#path18"
+       transform="translate(224,-192)"
+       id="use6402" />
+    <use
+       x="0"
+       y="0"
+       inkscape:tiled-clone-of="#path18"
+       xlink:href="#path18"
+       transform="translate(0,-224)"
+       id="use6404" />
+    <use
+       x="0"
+       y="0"
+       inkscape:tiled-clone-of="#path18"
+       xlink:href="#path18"
+       transform="translate(32,-224)"
+       id="use6406" />
+    <use
+       x="0"
+       y="0"
+       inkscape:tiled-clone-of="#path18"
+       xlink:href="#path18"
+       transform="translate(63.999999,-224)"
+       id="use6408" />
+    <use
+       x="0"
+       y="0"
+       inkscape:tiled-clone-of="#path18"
+       xlink:href="#path18"
+       transform="translate(95.999999,-224)"
+       id="use6410" />
+    <use
+       x="0"
+       y="0"
+       inkscape:tiled-clone-of="#path18"
+       xlink:href="#path18"
+       transform="translate(128,-224)"
+       id="use6412" />
+    <use
+       x="0"
+       y="0"
+       inkscape:tiled-clone-of="#path18"
+       xlink:href="#path18"
+       transform="translate(160,-224)"
+       id="use6414" />
+    <use
+       x="0"
+       y="0"
+       inkscape:tiled-clone-of="#path18"
+       xlink:href="#path18"
+       transform="translate(192,-224)"
+       id="use6416" />
+    <use
+       x="0"
+       y="0"
+       inkscape:tiled-clone-of="#path18"
+       xlink:href="#path18"
+       transform="translate(224,-224)"
+       id="use6418" />
+    <circle
+       id="path6497"
+       cx="20"
+       cy="276.99997"
+       style="fill:#ffffff;stroke-width:0.26458332"
+       r="8" />
+    <use
+       x="0"
+       y="0"
+       xlink:href="#path6497"
+       id="use6499"
+       transform="translate(32,-31.999986)"
+       width="100%"
+       height="100%" />
+    <use
+       x="0"
+       y="0"
+       xlink:href="#path6497"
+       id="use6501"
+       transform="translate(0,-31.999986)"
+       width="100%"
+       height="100%" />
+    <use
+       x="0"
+       y="0"
+       xlink:href="#path6497"
+       id="use6503"
+       transform="translate(0,-63.999986)"
+       width="100%"
+       height="100%" />
+    <path
+       id="path6592"
+       d="m 216.33789,193.3888 c 8.69016,-6.07131 15.77029,-13.83796 19.9345,-21.8704 4.82693,-9.3113 
5.30059,-18.23564 1.33253,-25.12886 -3.24425,-5.63746 -8.38814,-9.21252 -14.48291,-10.06782 -2.99906,-0.4193 
-6.1328,-0.17767 -9.24201,0.6396 v -10.43436 c 0,-2.5915 -2.10005,-4.69099 -4.69118,-4.69099 h -59.12486 c 
-2.59041,0 -4.69082,2.10077 -4.69082,4.69099 v 10.43366 c -3.10922,-0.82439 -6.24367,-1.05891 
-9.24202,-0.63961 -6.09476,0.85636 -11.23795,4.43037 -14.48254,10.06746 -3.96772,6.89393 -3.49298,15.81791 
1.33252,25.12921 4.16386,8.03208 11.24328,15.79908 19.93487,21.87041 1.85132,1.29343 2.06096,2.68282 
1.91172,3.61807 -0.17766,1.06245 -0.84925,1.91882 -1.7305,2.18532 -1.32186,0.39799 -3.85009,-0.38376 
-6.96571,-3.77583 -2.24574,-2.44472 -6.04823,-2.60462 -8.49295,-0.35888 -2.44473,2.24573 -2.60464,6.04927 
-0.35889,8.49331 5.7778,6.29128 11.29942,7.73963 15.16159,7.73963 1.76249,0 3.18029,-0.28427 4.1191,-0.58275 
2.0041,-0.60408 3.82167,-1.65233 5.3546,-3.02038 4.37
 67,6.016
 59 10.66123,10.56067 17.95989,12.73001 v 17.26166 h -14.59198 c -6.88541,0 -12.48769,5.60156 
-12.48769,12.48767 v 16.23616 c 0,3.23358 2.6224,5.85384 5.8542,5.85384 h 61.96225 c 3.23358,0 
5.85385,-2.6224 5.85385,-5.85384 v -16.23686 c 0,-6.88576 -5.60193,-12.48733 -12.48732,-12.48733 h -14.592 v 
-17.26165 c 7.29619,-2.17111 13.5807,-6.71342 17.95599,-12.73002 1.53151,1.37161 3.35085,2.41986 
5.35531,3.02038 0.93811,0.28427 2.3559,0.58631 4.11874,0.58631 3.86253,0 9.38591,-1.44979 15.16196,-7.73964 
2.24574,-2.44473 2.08584,-6.24791 -0.3589,-8.49332 -2.44473,-2.24574 -6.24828,-2.08584 -8.49331,0.3589 
-3.11632,3.38993 -5.64172,4.17276 -6.96571,3.77583 -0.88125,-0.24874 -1.55994,-1.12286 -1.7305,-2.18532 
-0.14214,-0.93811 0.0711,-2.32392 1.91172,-3.61737 m -82.68488,-27.40408 c -1.66654,-3.21227 
-4.08746,-9.25374 -1.58481,-13.59883 1.41425,-2.45539 3.29043,-3.81633 5.73338,-4.15924 2.28129,-0.3198 
4.9545,0.24874 7.57193,1.53862 v 30.3431 c -5.04013,-4.28041 -9.18906,-9.24769 -11.
 7198,-14
 .12757 m 80.22666,14.12757 v -30.34701 c 2.61529,-1.28277 5.28922,-1.85843 7.57157,-1.53862 2.44472,0.35534 
4.3202,1.70207 5.73268,4.15925 2.50158,4.34507 0.0711,10.38477 -1.58482,13.59881 -2.53001,4.87881 
-6.67753,9.84609 -11.71943,14.12757 z"
+       inkscape:connector-curvature="0"
+       
style="fill:#000000;stroke:#ffffff;stroke-width:8.64305687;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;fill-opacity:1"
 />
+  </g>
+</svg>
diff --git a/data/ui/new-game-screen.ui b/data/ui/new-game-screen.ui
new file mode 100644
index 0000000..abe1dd6
--- /dev/null
+++ b/data/ui/new-game-screen.ui
@@ -0,0 +1,135 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  This file is part of a GNOME game.
+
+  This application is free software: you can redistribute it and/or modify
+  it under the terms of the GNU General Public License as published by
+  the Free Software Foundation, either version 3 of the License, or
+  (at your option) any later version.
+
+  This application is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+  GNU General Public License for more details.
+
+  You should have received a copy of the GNU General Public License along
+  with this application.  If not, see <https://www.gnu.org/licenses/>.
+-->
+<interface>
+  <requires lib="gtk+" version="3.12"/>
+  <template class="NewGameScreen" parent="GtkBox">
+    <property name="orientation">vertical</property>
+    <property name="visible">True</property>
+    <property name="spacing">6</property>
+    <style>
+      <class name="new-game-screen"/>
+    </style>
+    <child>
+      <object class="GtkLabel" id="games_label">
+        <property name="visible">False</property>
+        <property name="halign">start</property>
+        <!-- Translators: when configuring a new game, header of the game type that appears on small screen 
-->
+        <property name="label" translatable="yes">Game</property>
+        <style>
+          <class name="bold-label"/>
+          <class name="section-header"/>
+        </style>
+      </object>
+    </child>
+    <child>
+      <object class="GtkBox" id="games_box">
+        <property name="orientation">horizontal</property>
+        <property name="visible">True</property>
+        <property name="homogeneous">True</property>
+        <property name="spacing">6</property>
+        <child>
+          <object class="GtkModelButton" id="modelbutton_one">
+            <property name="visible">True</property>
+            <property name="name">radio-one</property>
+            <style>
+              <class name="radio-like-toggle"/>
+              <class name="flat"/>
+            </style>
+            <property name="focus-on-click">False</property>
+            <property name="iconic">True</property>
+            <property name="centered">True</property>
+          </object>
+        </child>
+        <child>
+          <object class="GtkModelButton" id="modelbutton_two">
+            <property name="visible">True</property>
+            <property name="name">radio-two</property>
+            <style>
+              <class name="radio-like-toggle"/>
+              <class name="flat"/>
+            </style>
+            <property name="focus-on-click">False</property>
+            <property name="iconic">True</property>
+            <property name="centered">True</property>
+          </object>
+        </child>
+      </object>
+      <packing>
+        <property name="expand">True</property>
+        <property name="fill">True</property>
+      </packing>
+    </child>
+    <child>
+      <object class="GtkSeparator" id="options_separator">
+        <property name="visible">False</property>
+        <property name="orientation">horizontal</property>
+      </object>
+    </child>
+    <child>
+      <object class="GtkLabel" id="options_label">
+        <property name="visible">False</property>
+        <property name="halign">start</property>
+        <!-- Translators: when configuring a new game, header of the options that appears on small screen -->
+        <property name="label" translatable="yes">Options</property>
+        <style>
+          <class name="bold-label"/>
+          <class name="section-header"/>
+        </style>
+      </object>
+    </child>
+    <child>
+      <object class="GtkBox" id="options_box">
+        <property name="orientation">horizontal</property>
+        <property name="visible">True</property>
+        <property name="homogeneous">True</property>
+        <property name="spacing">6</property>
+        <child>
+          <object class="GtkMenuButton" id="menubutton_one">
+            <property name="visible">True</property>
+            <property name="use-underline">True</property>
+            <style>
+              <class name="menubutton-like-combo"/>
+              <class name="flat"/>
+            </style>
+          </object>
+          <packing>
+            <property name="expand">True</property>
+            <property name="fill">True</property>
+          </packing>
+        </child>
+        <child>
+          <object class="GtkMenuButton" id="menubutton_two">
+            <property name="visible">True</property>
+            <property name="use-underline">True</property>
+            <style>
+              <class name="menubutton-like-combo"/>
+              <class name="flat"/>
+            </style>
+          </object>
+          <packing>
+            <property name="expand">True</property>
+            <property name="fill">True</property>
+          </packing>
+        </child>
+      </object>
+      <packing>
+        <property name="fill">True</property>
+      </packing>
+    </child>
+  </template>
+</interface>
diff --git a/src/computer-reversi.vala b/src/computer-reversi.vala
index 8772a8c..c9f0741 100644
--- a/src/computer-reversi.vala
+++ b/src/computer-reversi.vala
@@ -42,6 +42,269 @@ private struct PossibleMove
     }
 }
 
+// used in ComputerRevers{i,e}Hard
+private const int16 [,] heuristic_8 =
+{
+    { 410,  23,  13,   8,   8,  13,  23, 410 },
+    {  23, -75, -22, -51, -51, -22, -75,  23 },
+    {  13, -22,  41,   3,   3,  41, -22,  13 },
+    {   8, -51,   3, -87, -87,   3, -51,   8 },
+    {   8, -51,   3, -87, -87,   3, -51,   8 },
+    {  13, -22,  41,   3,   3,  41, -22,  13 },
+    {  23, -75, -22, -51, -51, -22, -75,  23 },
+    { 410,  23,  13,   8,   8,  13,  23, 410 }
+};
+
+private class ComputerReverseEasy : ComputerReversi
+{
+    internal ComputerReverseEasy (Game game)
+    {
+        Object (game: game, initial_depth: 2);
+    }
+
+    /*\
+    * * minimax / negamax / alpha-beta pruning
+    \*/
+
+    protected override void sort_moves (ref SList<PossibleMove?> moves)
+    {
+        moves.sort (compare_move);
+    }
+
+    private static inline int compare_move (PossibleMove? a, PossibleMove? b)
+     // requires (a != null)
+     // requires (b != null)
+    {
+        return ((!) a).n_tiles <= ((!) b).n_tiles ? -1 : 1;
+    }
+
+    /*\
+    * * AI
+    \*/
+
+    protected override int16 end_of_game (GameStateStruct g)
+    {
+        return g.n_current_tiles < g.n_opponent_tiles ? POSITIVE_INFINITY - (int16) g.n_current_tiles
+                                                      : NEGATIVE_INFINITY + (int16) g.n_opponent_tiles;
+    }
+
+    protected override int16 calculate_heuristic (GameStateStruct g)
+    {
+        /* Try to lose */
+        return (int16) g.n_current_tiles - (int16) g.n_opponent_tiles;
+    }
+}
+
+private class ComputerReverseHard : ComputerReversi
+{
+    public bool even_depth { private get; protected construct; }
+
+    construct
+    {
+        init_heuristic (size, out heuristic);
+    }
+
+    internal ComputerReverseHard (Game game, uint8 initial_depth)
+    {
+        Object (game            : game,
+                even_depth      : initial_depth % 2 == 0,
+                initial_depth   : initial_depth);
+    }
+
+    /*\
+    * * minimax / negamax / alpha-beta pruning
+    \*/
+
+    protected override void sort_moves (ref SList<PossibleMove?> moves)
+    {
+        moves.sort_with_data (compare_move);
+    }
+
+    private inline int compare_move (PossibleMove? a, PossibleMove? b)
+     // requires (a != null)
+     // requires (b != null)
+    {
+        return calculate_move_heuristic ((!) b) - calculate_move_heuristic ((!) a);
+    }
+
+    private inline int calculate_move_heuristic (PossibleMove move)
+    {
+        int comparator = 0;
+        calculate_dir_heuristic (ref comparator, move.x, move.y,  0, -1, move.n_tiles_n );
+        calculate_dir_heuristic (ref comparator, move.x, move.y,  1, -1, move.n_tiles_ne);
+        calculate_dir_heuristic (ref comparator, move.x, move.y,  1,  0, move.n_tiles_e );
+        calculate_dir_heuristic (ref comparator, move.x, move.y,  1,  1, move.n_tiles_se);
+        calculate_dir_heuristic (ref comparator, move.x, move.y,  0,  1, move.n_tiles_s );
+        calculate_dir_heuristic (ref comparator, move.x, move.y, -1,  1, move.n_tiles_so);
+        calculate_dir_heuristic (ref comparator, move.x, move.y, -1,  0, move.n_tiles_o );
+        calculate_dir_heuristic (ref comparator, move.x, move.y, -1, -1, move.n_tiles_no);
+        return 2 * comparator + (int) heuristic [move.x, move.y] + 8 * (int) neighbor_tiles [move.x, move.y];
+    }
+
+    private inline void calculate_dir_heuristic (ref int comparator, uint8 x, uint8 y, int8 x_step, int8 
y_step, uint8 count)
+    {
+        for (; count > 0; count--)
+            comparator += (int) heuristic [(int8) x + ((int8) count * x_step),
+                                           (int8) y + ((int8) count * y_step)];
+    }
+
+    /*\
+    * * AI
+    \*/
+
+    protected override int16 end_of_game (GameStateStruct g)
+    {
+        return g.n_current_tiles < g.n_opponent_tiles ? POSITIVE_INFINITY - (int16) g.n_current_tiles
+                                                      : NEGATIVE_INFINITY + (int16) g.n_opponent_tiles;
+    }
+
+    protected override int16 calculate_heuristic (GameStateStruct g)
+    {
+        return eval_heuristic (g, ref heuristic, even_depth);
+    }
+
+    private static inline int16 eval_heuristic (GameStateStruct g, ref int16 [,] heuristic, bool even_depth)
+    {
+        uint8 size = g.size;
+        int16 count = 0;
+
+        for (uint8 x = 0; x < size; x++)
+            for (uint8 y = 0; y < size; y++)
+            {
+                int16 a = (int16) g.get_empty_neighbors (x, y);
+                if (a == 0) // completely surrounded
+                    a = 6;
+
+                int16 tile_heuristic = heuristic [x, y] + 8 * a;
+                if (g.is_empty_tile (x, y))
+                {
+                    if (even_depth)
+                        count -= tile_heuristic / 2;
+                    else
+                        count += tile_heuristic / 2;
+                }
+                else if (g.is_current_color (x, y))
+                    count += tile_heuristic;
+                else
+                    count -= tile_heuristic;
+            }
+
+        mainline_penalty (g, border_penalty, ref count, MainLine.TOP);
+        mainline_penalty (g, border_penalty, ref count, MainLine.LEFT);
+        mainline_penalty (g, border_penalty, ref count, MainLine.RIGHT);
+        mainline_penalty (g, border_penalty, ref count, MainLine.BOTTOM);
+        mainline_penalty (g, corner_penalty, ref count, MainLine.TOPLEFT);
+        mainline_penalty (g, corner_penalty, ref count, MainLine.TOPRIGHT);
+
+        return count;
+    }
+
+    private const int16 border_penalty = 86;
+    private const int16 corner_penalty = 86;
+    private static void mainline_penalty (GameStateStruct g, int16 penalty, ref int16 count, MainLine 
mainline_id)
+    {
+        Player [] mainline = g.get_mainline (mainline_id);
+        if (mainline [1] == g.current_color
+         && mainline [0] == Player.NONE)
+        {
+            uint8 i = 1;
+            do { i++; if (i == g.size - 2) break; }
+            while (mainline [i] == g.current_color);
+            if (i != g.size - 2)
+            {
+                count += penalty;
+                if (mainline [i + 1] == g.current_color)
+                    count += penalty;
+            }
+        }
+        if (mainline [g.size - 2] == g.current_color
+         && mainline [g.size - 1] == Player.NONE)
+        {
+            uint8 i = 1;
+            do { i++; if (i == g.size - 2) break; }
+            while (mainline [g.size - 1 - i] == g.current_color);
+            if (i != g.size - 2)
+            {
+                count += penalty;
+                if (mainline [g.size - 2 - i] == g.current_color)
+                    count += penalty;
+            }
+        }
+    }
+
+    /*\
+    * * heuristic table
+    \*/
+
+    private int16 [,] heuristic;
+
+    private static void init_heuristic (uint8 size, out int16 [,] heuristic)
+        requires (size >= 4)
+    {
+        int16 [,] _heuristic;
+
+        if (size == 8)
+            _heuristic = heuristic_8;
+        else
+            create_heuristic (size, out _heuristic);
+
+        heuristic = new int16 [size, size];
+        for (uint8 i = 0; i < size; i++)
+            for (uint8 j = 0; j < size; j++)
+                heuristic [i, j] = (int16) (-1.7 * (_heuristic [i, j] + 112));
+
+        /* that part is fun */
+        for (uint8 i = 0; i < 5; i++)
+        {
+            heuristic [Random.int_range (0, (int32) size),
+                       Random.int_range (0, (int32) size)]
+                    += Random.boolean () ? -1 : 1;
+
+            uint8 x = (uint8) Random.int_range (0, (int32) size);
+            uint8 y = (uint8) Random.int_range (0, (int32) size);
+            bool minus = Random.boolean ();
+            heuristic [x, y]                       += minus ? -1 : 1;
+            heuristic [size - 1 - x, size - 1 - y] += minus ? -1 : 1;
+        }
+    }
+
+    private static void create_heuristic (uint8 size, out int16 [,] heuristic)
+        requires (size >= 4)
+    {
+        heuristic = new int16 [size, size];
+        for (uint8 x = 0; x < size; x++)
+            for (uint8 y = 0; y < size; y++)
+                heuristic [x, y] = 0;
+
+        // corners
+        uint8 tmp1 = size - 1;
+        heuristic [0   , 0   ] = 110;
+        heuristic [0   , tmp1] = 110;
+        heuristic [tmp1, tmp1] = 110;
+        heuristic [tmp1, 0   ] = 110;
+
+        if (size >= 6)
+        {
+            // corners neighbors
+            uint8 tmp2 = size - 2;
+            heuristic [0   , 1   ] = 35;
+            heuristic [0   , tmp2] = 35;
+            heuristic [tmp1, 1   ] = 35;
+            heuristic [tmp1, tmp2] = 35;
+            heuristic [1   , 0   ] = 35;
+            heuristic [1   , tmp1] = 35;
+            heuristic [tmp2, 0   ] = 35;
+            heuristic [tmp2, tmp1] = 35;
+
+            // corners diagonal neighbors
+            heuristic [1   , 1   ] = 15;
+            heuristic [1   , tmp2] = 15;
+            heuristic [tmp2, tmp2] = 15;
+            heuristic [tmp2, 1   ] = 15;
+        }
+    }
+}
+
 private class ComputerReversiEasy : ComputerReversi
 {
     internal ComputerReversiEasy (Game game)
@@ -62,16 +325,19 @@ private class ComputerReversiEasy : ComputerReversi
      // requires (a != null)
      // requires (b != null)
     {
-        if (((!) a).n_tiles >= ((!) b).n_tiles)
-            return -1;
-        else
-            return 1;
+        return ((!) a).n_tiles >= ((!) b).n_tiles ? -1 : 1;
     }
 
     /*\
     * * AI
     \*/
 
+    protected override int16 end_of_game (GameStateStruct g)
+    {
+        return g.n_current_tiles > g.n_opponent_tiles ? POSITIVE_INFINITY - (int16) g.n_opponent_tiles
+                                                      : NEGATIVE_INFINITY + (int16) g.n_current_tiles;
+    }
+
     protected override int16 calculate_heuristic (GameStateStruct g)
     {
         /* Try to lose */
@@ -136,6 +402,12 @@ private class ComputerReversiHard : ComputerReversi
     * * AI
     \*/
 
+    protected override int16 end_of_game (GameStateStruct g)
+    {
+        return g.n_current_tiles > g.n_opponent_tiles ? POSITIVE_INFINITY - (int16) g.n_opponent_tiles
+                                                      : NEGATIVE_INFINITY + (int16) g.n_current_tiles;
+    }
+
     protected override int16 calculate_heuristic (GameStateStruct g)
     {
         return eval_heuristic (g, ref heuristic, even_depth);
@@ -242,18 +514,6 @@ private class ComputerReversiHard : ComputerReversi
 
     private int16 [,] heuristic;
 
-    private const int16 [,] heuristic_8 =
-    {
-        { 410,  23,  13,   8,   8,  13,  23, 410 },
-        {  23, -75, -22, -51, -51, -22, -75,  23 },
-        {  13, -22,  41,   3,   3,  41, -22,  13 },
-        {   8, -51,   3, -87, -87,   3, -51,   8 },
-        {   8, -51,   3, -87, -87,   3, -51,   8 },
-        {  13, -22,  41,   3,   3,  41, -22,  13 },
-        {  23, -75, -22, -51, -51, -22, -75,  23 },
-        { 410,  23,  13,   8,   8,  13,  23, 410 }
-    };
-
     private static inline void init_heuristic (uint8 size, out int16 [,] heuristic)
         requires (size >= 4)
     {
@@ -323,9 +583,9 @@ private abstract class ComputerReversi : ComputerPlayer
     public uint8 move_randomly  { protected get; private   construct; } // TODO getter should be private, 
but...
 
     /* do not forget int16.MIN ≠ - int16.MAX */
-    private const int16 POSITIVE_INFINITY           =  32000;
-    private const int16 NEGATIVE_INFINITY           = -32000;
-    private const int16 LESS_THAN_NEGATIVE_INFINITY = -32001;
+    protected const int16 POSITIVE_INFINITY           =  32000;
+    protected const int16 NEGATIVE_INFINITY           = -32000;
+    private   const int16 LESS_THAN_NEGATIVE_INFINITY = -32001;
 
     protected uint8 [,] neighbor_tiles;
 
@@ -391,7 +651,7 @@ private abstract class ComputerReversi : ComputerPlayer
         /* For the first/first two moves play randomly so the game is not always the same */
         if (g.n_tiles < move_randomly)
         {
-            if (size != 8)
+            if (size != 8 || game.reverse)
                 random_select (g, out best_move);
             else
             {
@@ -439,10 +699,9 @@ private abstract class ComputerReversi : ComputerPlayer
     private int16 search (GameStateStruct g, uint8 depth, int16 a, int16 b)
      // requires (a <= b)
     {
-        /* End of the game, return a near-infinite evaluation */
+        /* End of the game, return (usually) a near-infinite evaluation */
         if (g.is_complete)
-            return g.n_current_tiles > g.n_opponent_tiles ? POSITIVE_INFINITY - (int16) g.n_opponent_tiles
-                                                          : NEGATIVE_INFINITY + (int16) g.n_current_tiles;
+            return end_of_game (g);
 
         /* End of the search, calculate how good a result this is. */
         if (depth == 0)
@@ -484,5 +743,6 @@ private abstract class ComputerReversi : ComputerPlayer
     }
 
     protected abstract int16 calculate_heuristic (GameStateStruct g);
+    protected abstract int16 end_of_game (GameStateStruct g);
     protected abstract void sort_moves (ref SList<PossibleMove?> moves);
 }
diff --git a/src/game.vala b/src/game.vala
index deaffbc..55945b5 100644
--- a/src/game.vala
+++ b/src/game.vala
@@ -555,6 +555,7 @@ private class Game : Object
     \*/
 
     [CCode (notify = false)] public uint8           size                    { internal get; protected 
construct;     }
+    [CCode (notify = false)] public bool            reverse                 { internal get; protected 
construct;     }
     [CCode (notify = false)] public GameStateObject current_state           { internal get; protected 
construct set; }
     [CCode (notify = false)] public bool            alternative_start       { internal get; protected 
construct;     }
     [CCode (notify = false)] public uint8           initial_number_of_tiles { internal get; protected 
construct;     }
@@ -565,7 +566,7 @@ private class Game : Object
         update_possible_moves ();
     }
 
-    internal Game (bool _alternative_start = false, uint8 _size = 8)
+    internal Game (bool _reverse, bool _alternative_start = false, uint8 _size = 8)
         requires (_size >= 4)
         requires (_size <= 16)
     {
@@ -607,13 +608,14 @@ private class Game : Object
         GameStateObject _current_state = new GameStateObject.from_grid (_size, tiles, /* Dark always starts 
*/ Player.DARK, _neighbor_tiles);
 
         Object (size                    : _size,
+                reverse                 : _reverse,
                 current_state           : _current_state,
                 alternative_start       : _alternative_start,
                 initial_number_of_tiles : _initial_number_of_tiles);
         neighbor_tiles = (owned) _neighbor_tiles;
     }
 
-    internal Game.from_strings (string [] setup, Player to_move, uint8 _size = 8)
+    internal Game.from_strings (string [] setup, Player to_move, bool _reverse = false, uint8 _size = 8)
         requires (_size >= 4)
         requires (_size <= 16)
         requires (to_move != Player.NONE)
@@ -634,6 +636,7 @@ private class Game : Object
         GameStateObject _current_state = new GameStateObject.from_grid (_size, tiles, to_move, 
_neighbor_tiles);
 
         Object (size                    : _size,
+                reverse                 : _reverse,
                 current_state           : _current_state,
                 alternative_start       : /* garbage */ false,
                 initial_number_of_tiles : (_size % 2 == 0) ? 4 : 7);
diff --git a/src/iagno.vala b/src/iagno.vala
index 386cfac..c7ead0c 100644
--- a/src/iagno.vala
+++ b/src/iagno.vala
@@ -93,9 +93,10 @@ private class Iagno : Gtk.Application, BaseApplication
 
     private const GLib.ActionEntry app_actions [] =
     {
-        { "game-type", null, "s", "'dark'", change_game_type },
-        { "set-use-night-mode", set_use_night_mode, "b" },
+        { "game-type", change_game_type, "s" },
+        { "change-level", change_level_cb, "s" },
 
+        { "set-use-night-mode", set_use_night_mode, "b" },
         { "quit", quit }
     };
 
@@ -210,7 +211,42 @@ private class Iagno : Gtk.Application, BaseApplication
         view.move.connect (player_move_cb);
         view.clear_impossible_to_move_here_warning.connect (clear_impossible_to_move_here_warning);
 
-        new_game_screen = new NewGameScreen ();
+        GLib.Menu size_menu = new GLib.Menu ();
+        /* Translators: when configuring a new game, in the first menubutton's menu, label of the entry to 
choose to play first/Dark (with a mnemonic that appears pressing Alt) */
+        size_menu.append (_("Play _first (Dark)"),  "app.game-type('dark')");
+
+
+        /* Translators: when configuring a new game, in the first menubutton's menu, label of the entry to 
choose to play second/Light (with a mnemonic that appears pressing Alt) */
+        size_menu.append (_("Play _second (Light)"), "app.game-type('light')");
+
+
+        /* Translators: when configuring a new game, in the first menubutton's menu, label of the entry to 
choose a two-players game (with a mnemonic that appears pressing Alt) */
+        size_menu.append (_("_Two players"), "app.game-type('two')");
+        size_menu.freeze ();
+
+        GLib.Menu theme_menu = new GLib.Menu ();
+        /* Translators: when configuring a new game, in the second menubutton's menu, label of the entry to 
choose an easy-level computer adversary (with a mnemonic that appears pressing Alt) */
+        theme_menu.append (_("_Easy"),   "app.change-level('1')");
+
+
+        /* Translators: when configuring a new game, in the second menubutton's menu, label of the entry to 
choose a medium-level computer adversary (with a mnemonic that appears pressing Alt) */
+        theme_menu.append (_("_Medium"), "app.change-level('2')");
+
+
+        /* Translators: when configuring a new game, in the second menubutton's menu, label of the entry to 
choose an hard-level computer adversary (with a mnemonic that appears pressing Alt) */
+        theme_menu.append (_("_Hard"),   "app.change-level('3')");
+        theme_menu.freeze ();
+
+        /* Translators: when configuring a new game, label of the first big button; name of the usual 
reversi game, where you try to have more pieces */
+        new_game_screen = new NewGameScreen (_("Classic Reversi"),
+                                             "app.type('classic')",
+
+        /* Translators: when configuring a new game, label of the second big button; name of the opposite 
game, where you try to have less pieces */
+                                             _("Reverse Reversi"),
+                                             "app.type('reverse')",
+
+                                             size_menu,
+                                             theme_menu);
 
         if (settings.get_boolean ("sound"))
             init_sound ();
@@ -316,45 +352,61 @@ private class Iagno : Gtk.Application, BaseApplication
      // set_accels_for_action ("app.help",              {                 "F1"      });
      // set_accels_for_action ("base.about",            {          "<Shift>F1"      });
         add_action (settings.create_action ("sound"));
-        add_action (settings.create_action ("color"));
-        add_action (settings.create_action ("num-players"));
-        add_action (settings.create_action ("computer-level"));
+        add_action (settings.create_action ("type"));        // TODO window action?
         add_action (settings.create_action ("highlight-turnable-tiles"));
         add_action (settings.create_action ("theme"));
 
         settings.bind ("highlight-turnable-tiles", view, "show-turnable-tiles", SettingsBindFlags.GET);
         settings.bind ("theme",                    view, "theme",               SettingsBindFlags.GET);
 
-        game_type_action = (SimpleAction) lookup_action ("game-type");
+        /* New-game screen signals */
+        settings.changed ["computer-level"].connect (() => {
+            if (!level_changed)
+                update_level_button_label (settings.get_int ("computer-level") /* 1 <= level <= 3 */);
+            level_changed = false;
+        });
+        update_level_button_label (settings.get_int ("computer-level") /* 1 <= level <= 3 */);
 
         settings.changed ["color"].connect (() => {
+                if (game_type_changed_1)
+                {
+                    game_type_changed_1 = false;
+                    return;
+                }
+
                 if (settings.get_int ("num-players") == 2)
                     return;
                 if (settings.get_string ("color") == "dark")
-                    game_type_action.set_state (new Variant.string ("dark"));
+                    update_game_type_button_label ("dark");
                 else
-                    game_type_action.set_state (new Variant.string ("light"));
+                    update_game_type_button_label ("light");
             });
 
         settings.changed ["num-players"].connect (() => {
+                if (game_type_changed_2)
+                {
+                    game_type_changed_2 = false;
+                    return;
+                }
+
                 bool solo = settings.get_int ("num-players") == 1;
                 new_game_screen.update_sensitivity (solo);
                 if (!solo)
-                    game_type_action.set_state (new Variant.string ("two"));
+                    update_game_type_button_label ("two");
                 else if (settings.get_string ("color") == "dark")
-                    game_type_action.set_state (new Variant.string ("dark"));
+                    update_game_type_button_label ("dark");
                 else
-                    game_type_action.set_state (new Variant.string ("light"));
+                    update_game_type_button_label ("light");
             });
         bool solo = settings.get_int ("num-players") == 1;
         new_game_screen.update_sensitivity (solo);
 
         if (settings.get_int ("num-players") == 2)
-            game_type_action.set_state (new Variant.string ("two"));
+            update_game_type_button_label ("two");
         else if (settings.get_string ("color") == "dark")
-            game_type_action.set_state (new Variant.string ("dark"));
+            update_game_type_button_label ("dark");
         else
-            game_type_action.set_state (new Variant.string ("light"));
+            update_game_type_button_label ("light");
 
         if (start_now)
             start_game ();
@@ -395,23 +447,75 @@ private class Iagno : Gtk.Application, BaseApplication
     * * Internal calls
     \*/
 
-    private SimpleAction game_type_action;
+    private bool game_type_changed_1 = false;
+    private bool game_type_changed_2 = false;
     private void change_game_type (SimpleAction action, Variant? gvariant)
         requires (gvariant != null)
     {
         string type = ((!) gvariant).get_string ();
-//        game_type_action.set_state ((!) gvariant);
+        update_game_type_button_label (type);
+        game_type_changed_1 = true;
+        game_type_changed_2 = true;
         switch (type)
         {
-            case "dark":  settings.set_int    ("num-players", 1); new_game_screen.update_sensitivity (true);
-                          settings.set_string ("color",  "dark");                                            
 return;
-            case "light": settings.set_int    ("num-players", 1); new_game_screen.update_sensitivity (true);
-                          settings.set_string ("color", "light");                                            
 return;
             case "two":   settings.set_int    ("num-players", 2); new_game_screen.update_sensitivity 
(false); return;
+            case "dark":  settings.delay ();
+                          settings.set_int    ("num-players", 1); new_game_screen.update_sensitivity (true);
+                          settings.set_string ("color",  "dark"); settings.apply ();                         
 return;
+            case "light": settings.delay ();
+                          settings.set_int    ("num-players", 1); new_game_screen.update_sensitivity (true);
+                          settings.set_string ("color", "light"); settings.apply ();                         
 return;
+            default: assert_not_reached ();
+        }
+    }
+    private void update_game_type_button_label (string type)
+    {
+        switch (type)
+        {
+            case "two":
+                new_game_screen.update_menubutton_label (NewGameScreen.MenuButton.ONE,
+                /* Translators: when configuring a new game, button label if a two-players game is chosen */
+                                                         _("Two players"));     return;
+            case "dark":
+                new_game_screen.update_menubutton_label (NewGameScreen.MenuButton.ONE,
+                /* Translators: when configuring a new game, button label if the player choose to start */
+                                                         _("Color: Dark"));     return;
+            case "light":
+                new_game_screen.update_menubutton_label (NewGameScreen.MenuButton.ONE,
+                /* Translators: when configuring a new game, button label if the player choose let computer 
start */
+                                                         _("Color: Light"));    return;
             default: assert_not_reached ();
         }
     }
 
+    private bool level_changed = false;
+    private void change_level_cb (SimpleAction action, Variant? gvariant)
+        requires (gvariant != null)
+    {
+        level_changed = true;
+        int level = int.parse (((!) gvariant).get_string ());
+        update_level_button_label (level /* 1 <= level <= 3 */);
+        settings.set_int ("computer-level", level);
+    }
+    private void update_level_button_label (int level)
+    {
+        switch (level)
+        {
+            case 1:
+                new_game_screen.update_menubutton_label (NewGameScreen.MenuButton.TWO,
+                /* Translators: when configuring a new game, button label for the AI level, if easy */
+                                                         _("Difficulty: Easy"));                return;
+            case 2:
+                new_game_screen.update_menubutton_label (NewGameScreen.MenuButton.TWO,
+                /* Translators: when configuring a new game, button label for the AI level, if medium */
+                                                         _("Difficulty: Medium"));              return;
+            case 3:
+                new_game_screen.update_menubutton_label (NewGameScreen.MenuButton.TWO,
+                /* Translators: when configuring a new game, button label for the AI level, if hard */
+                                                         _("Difficulty: Hard"));                return;
+        }
+    }
+
     private void back_cb ()
         requires (game_is_set)
     {
@@ -435,7 +539,8 @@ private class Iagno : Gtk.Application, BaseApplication
         if (computer != null)
             ((!) computer).cancel_move ();
 
-        game = new Game (alternative_start, (uint8) size /* 4 <= size <= 16 */);
+        bool reverse = settings.get_string ("type") == "reverse";
+        game = new Game (reverse, alternative_start, (uint8) size /* 4 <= size <= 16 */);
         game_is_set = true;
         game.turn_ended.connect (turn_ended_cb);
         view.game = game;
@@ -445,13 +550,22 @@ private class Iagno : Gtk.Application, BaseApplication
         else
         {
             uint8 computer_level = (uint8) settings.get_int ("computer-level");
-            switch (computer_level)
-            {
-                case 1 : computer = new ComputerReversiEasy (game);                break;
-                case 2 : computer = new ComputerReversiHard (game, /* depth */ 0); break;
-                case 3 : computer = new ComputerReversiHard (game, /* depth */ 1); break;
-                default: assert_not_reached ();
-            }
+            if (reverse)
+                switch (computer_level)
+                {
+                    case 1 : computer = new ComputerReverseEasy (game);                break;
+                    case 2 : computer = new ComputerReverseHard (game, /* depth */ 1); break;
+                    case 3 : computer = new ComputerReverseHard (game, /* depth */ 2); break;
+                    default: assert_not_reached ();
+                }
+            else
+                switch (computer_level)
+                {
+                    case 1 : computer = new ComputerReversiEasy (game);                break;
+                    case 2 : computer = new ComputerReversiHard (game, /* depth */ 0); break;
+                    case 3 : computer = new ComputerReversiHard (game, /* depth */ 1); break;
+                    default: assert_not_reached ();
+                }
         }
 
         if (settings.get_enum ("color") == 1)
@@ -562,11 +676,13 @@ private class Iagno : Gtk.Application, BaseApplication
     {
         window.finish_game ();
 
-        if (game.n_light_tiles > game.n_dark_tiles)
+        if ((!game.reverse && game.n_light_tiles > game.n_dark_tiles)
+         || ( game.reverse && game.n_light_tiles < game.n_dark_tiles))
             /* Translators: during a game, notification to display when Light has won the game; the %u are 
replaced with the Light and Dark number of tiles */
             window.show_notification (_("Light wins! (%u-%u)").printf (game.n_light_tiles, 
game.n_dark_tiles));
 
-        else if (game.n_dark_tiles > game.n_light_tiles)
+        else if ((!game.reverse && game.n_light_tiles < game.n_dark_tiles)
+              || ( game.reverse && game.n_light_tiles > game.n_dark_tiles))
             /* Translators: during a game, notification to display when Dark has won the game; the %u are 
replaced with the Dark and Light number of tiles */
             window.show_notification (_("Dark wins! (%u-%u)").printf (game.n_dark_tiles, 
game.n_light_tiles));
 
diff --git a/src/new-game-screen.vala b/src/new-game-screen.vala
index 32f6345..5b9beb5 100644
--- a/src/new-game-screen.vala
+++ b/src/new-game-screen.vala
@@ -1,148 +1,169 @@
-/* -*- Mode: vala; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
-/*
-   This file is part of GNOME Reversi, also known as Iagno.
+/* -*- Mode: vala; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ *
+ * Copyright (C) 2015-2016 Arnaud Bonatti <arnaud bonatti gmail com>
+ *
+ * This file is part of a GNOME game.
+ *
+ * This application is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This application is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this application. If not, see <http://www.gnu.org/licenses/>.
+ */
 
-   Copyright 2010-2013 Robert Ancell
-   Copyright 2013-2014 Michael Catanzaro
-   Copyright 2014-2019 Arnaud Bonatti
+using Gtk;
 
-   GNOME Reversi is free software: you can redistribute it and/or modify
-   it under the terms of the GNU General Public License as published by
-   the Free Software Foundation, either version 3 of the License, or
-   (at your option) any later version.
+[GtkTemplate (ui = "/org/gnome/Reversi/ui/new-game-screen.ui")]
+private class NewGameScreen : Box, AdaptativeWidget
+{
+    [GtkChild] private ModelButton modelbutton_one;
+    [GtkChild] private ModelButton modelbutton_two;
 
-   GNOME Reversi is distributed in the hope that it will be useful,
-   but WITHOUT ANY WARRANTY; without even the implied warranty of
-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-   GNU General Public License for more details.
+    [GtkChild] private Gtk.MenuButton menubutton_one;
+    [GtkChild] private Gtk.MenuButton menubutton_two;
 
-   You should have received a copy of the GNU General Public License
-   along with GNOME Reversi.  If not, see <https://www.gnu.org/licenses/>.
-*/
+    construct
+    {
+        CssProvider css_provider = new CssProvider ();
+        css_provider.load_from_resource ("/org/gnome/Reversi/ui/new-game-screen.css");
+        Gdk.Screen? gdk_screen = Gdk.Screen.get_default ();
+        if (gdk_screen != null) // else..?
+            StyleContext.add_provider_for_screen ((!) gdk_screen, css_provider, 
STYLE_PROVIDER_PRIORITY_APPLICATION);
 
-using Gtk;
+        fix_race ();
+    }
 
-[GtkTemplate (ui = "/org/gnome/Reversi/ui/iagno-screens.ui")]
-private class NewGameScreen : Box, AdaptativeWidget
-{
-    [GtkChild] private Box infos_section;
-    [GtkChild] private Box users_section;
-    [GtkChild] private Box color_section;
+    internal NewGameScreen (string      modelbutton_one_label,
+                            string      modelbutton_one_action,
+                            string      modelbutton_two_label,
+                            string      modelbutton_two_action,
+                            GLib.Menu   menu_one,
+                            GLib.Menu   menu_two)
+    {
+        modelbutton_one.text = modelbutton_one_label;
+        modelbutton_two.text = modelbutton_two_label;
 
-    [GtkChild] private Box users_box;
-    [GtkChild] private Box level_box;
-    [GtkChild] private Box color_box;
+        modelbutton_one.set_detailed_action_name (modelbutton_one_action);
+        modelbutton_two.set_detailed_action_name (modelbutton_two_action);
+
+        menubutton_one.set_menu_model (menu_one);
+        menubutton_two.set_menu_model (menu_two);
+    }
 
     internal void update_sensitivity (bool new_sensitivity)
     {
-        level_box.sensitive = new_sensitivity;
-        color_box.sensitive = new_sensitivity;
+        menubutton_two.sensitive = new_sensitivity;
+    }
+
+    /*\
+    * * options buttons
+    \*/
+
+    public enum MenuButton {
+        ONE,
+        TWO;
+    }
+
+    internal void update_menubutton_label (MenuButton button, string label)
+    {
+        switch (button)
+        {
+            case MenuButton.ONE: menubutton_one.set_label (label); return;
+            case MenuButton.TWO: menubutton_two.set_label (label); return;
+        }
+    }
+
+    // that is a quite usual menubutton label, so put it here
+    internal static inline string get_size_button_label (int size)
+    {
+        /* Translators: when configuring a new game, button label for the size of the game ("3 × 3", or 4, 
or 5) */
+        return _("Size: %d × %d ▾").printf (size, size);
+     // return _("Size: %hhu × %hhu ▾").printf (size, size));   // TODO uint8
+    }
+
+    /*\
+    * * adaptative stuff
+    \*/
+
+    private void fix_race ()   // FIXME things are a bit racy between the CSS and the box orientation 
changes, so delay games_box redraw
+    {
+        size_allocate.connect_after (() => games_box.show ());
+        map.connect (() => games_box.show ());
     }
 
-    private bool quite_thin = false;
-    private bool extra_thin = true;     // extra_thin && !quite_thin is impossible, so it will not return in 
next method the first time
+    [GtkChild] private Box          games_box;
+    [GtkChild] private Box          options_box;
+
+    [GtkChild] private Label        games_label;
+    [GtkChild] private Label        options_label;
+    [GtkChild] private Separator    options_separator;
+
+    private bool phone_size = false;
+    private bool extra_thin = false;
     private bool extra_flat = false;
     private void set_window_size (AdaptativeWidget.WindowSize new_size)
     {
-        bool _quite_thin = WindowSize.is_quite_thin (new_size);
-        bool _extra_thin = WindowSize.is_extra_thin (new_size);
-        bool _extra_flat = WindowSize.is_extra_flat (new_size);
+        bool _extra_flat = AdaptativeWidget.WindowSize.is_extra_flat (new_size);
+        bool _extra_thin = (new_size == AdaptativeWidget.WindowSize.EXTRA_THIN);
+        bool _phone_size = (new_size == AdaptativeWidget.WindowSize.PHONE_BOTH)
+                        || (new_size == AdaptativeWidget.WindowSize.PHONE_VERT);
 
-        if ((_quite_thin == quite_thin)
-         && (_extra_thin == extra_thin)
+        if ((_extra_thin == extra_thin)
+         && (_phone_size == phone_size)
          && (_extra_flat == extra_flat))
             return;
-        quite_thin = _quite_thin;
         extra_thin = _extra_thin;
+        phone_size = _phone_size;
         extra_flat = _extra_flat;
 
-        if (extra_thin)
-        {
-            set_orientation (Orientation.VERTICAL);
-            spacing = 18;
-            homogeneous = false;
-            height_request = 360;
-            width_request = 250;
-            margin_bottom = 22;
-
-            users_section.hide ();
-            color_section.hide ();
-            infos_section.show ();
-
-            level_box.set_orientation (Orientation.VERTICAL);
-
-            users_box.set_spacing (0);
-            level_box.set_spacing (0);
-            color_box.set_spacing (0);
-
-            users_box.get_style_context ().add_class ("linked");
-            level_box.get_style_context ().add_class ("linked");
-            color_box.get_style_context ().add_class ("linked");
-        }
-        else if (extra_flat)
+        if (!_extra_thin && !_phone_size)
         {
-            set_orientation (Orientation.HORIZONTAL);
-            homogeneous = true;
-            height_request = 113;
-            margin_bottom = 6;
-            if (quite_thin)
+            if (extra_flat)
             {
-                spacing = 21;
-                width_request = 420;
+                games_label.hide ();
+                options_label.hide ();
+                this.set_orientation (Orientation.HORIZONTAL);
+                games_box.set_orientation (Orientation.VERTICAL);
+                options_box.set_orientation (Orientation.VERTICAL);
+                options_separator.set_orientation (Orientation.VERTICAL);
+                options_separator.show ();
             }
             else
             {
-                spacing = 24;
-                width_request = 450;
+                games_label.hide ();
+                options_label.hide ();
+                options_separator.hide ();
+                this.set_orientation (Orientation.VERTICAL);
+                games_box.set_orientation (Orientation.HORIZONTAL);
+                options_box.set_orientation (Orientation.HORIZONTAL);
+                games_box.hide ();
             }
-
-            users_section.hide ();
-            color_section.hide ();
-            infos_section.show ();
-
-            level_box.set_orientation (Orientation.VERTICAL);
-
-            users_box.set_spacing (0);
-            level_box.set_spacing (0);
-            color_box.set_spacing (0);
-
-            users_box.get_style_context ().add_class ("linked");
-            level_box.get_style_context ().add_class ("linked");
-            color_box.get_style_context ().add_class ("linked");
+        }
+        else if (_phone_size)
+        {
+            games_label.hide ();
+            options_label.hide ();
+            this.set_orientation (Orientation.VERTICAL);
+            games_box.set_orientation (Orientation.VERTICAL);
+            options_box.set_orientation (Orientation.VERTICAL);
+            options_separator.set_orientation (Orientation.HORIZONTAL);
+            options_separator.show ();
         }
         else
         {
-            set_orientation (Orientation.VERTICAL);
-            spacing = 18;
-            height_request = 263;
-            int boxes_spacing;
-            if (quite_thin)
-            {
-                boxes_spacing = 10;
-                width_request = 380;
-            }
-            else
-            {
-                boxes_spacing = 12;
-                width_request = 400;
-            }
-            margin_bottom = 22;
-
-            infos_section.hide ();
-            users_section.show ();
-            color_section.show ();
-
-            level_box.set_orientation (Orientation.HORIZONTAL);
-
-            users_box.get_style_context ().remove_class ("linked");
-            level_box.get_style_context ().remove_class ("linked");
-            color_box.get_style_context ().remove_class ("linked");
-
-            users_box.set_spacing (boxes_spacing);
-            level_box.set_spacing (boxes_spacing);
-            color_box.set_spacing (boxes_spacing);
-
-            homogeneous = true;
+            options_separator.hide ();
+            this.set_orientation (Orientation.VERTICAL);
+            games_box.set_orientation (Orientation.VERTICAL);
+            options_box.set_orientation (Orientation.VERTICAL);
+            games_label.show ();
+            options_label.show ();
         }
         queue_allocate ();
     }
diff --git a/src/test-iagno.vala b/src/test-iagno.vala
index 6cb8cf2..432d5fd 100644
--- a/src/test-iagno.vala
+++ b/src/test-iagno.vala
@@ -127,7 +127,7 @@ private class TestIagno : Object
 
     private static void test_undo_at_start ()
     {
-        Game game = new Game ();
+        Game game = new Game (/* reverse */ false);
         assert_true (game.number_of_moves == 0);
         assert_true (game.place_tile (2, 3));
         assert_true (game.number_of_moves == 1);


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]