From 1ac87837f894b2846599cf240171caa97874e1fa Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Beno=C3=AEt=20Harrault?= <benoit@harrault.fr>
Date: Thu, 19 Aug 2021 16:51:08 +0200
Subject: [PATCH] Add minimal gameplay

---
 android/gradle.properties                     |   4 +-
 assets/icons/button_back.png                  | Bin 3744 -> 0 bytes
 assets/icons/button_restart.png               | Bin 0 -> 8633 bytes
 assets/icons/button_start.png                 | Bin 3969 -> 0 bytes
 assets/icons/difficulty_easy.png              | Bin 2833 -> 0 bytes
 assets/icons/difficulty_hard.png              | Bin 2649 -> 0 bytes
 assets/icons/difficulty_medium.png            | Bin 2857 -> 0 bytes
 assets/icons/empty.png                        | Bin 0 -> 170 bytes
 assets/{empty.png => skins/default_tile.png}  | Bin
 assets/skins/default_tile_black.png           | Bin 3383 -> 3387 bytes
 assets/skins/default_tile_empty.png           | Bin 0 -> 170 bytes
 assets/skins/default_tile_white.png           | Bin 3271 -> 3025 bytes
 .../metadata/android/en-US/changelogs/2.txt   |   2 +-
 .../metadata/android/en-US/changelogs/3.txt   |   1 -
 .../metadata/android/en-US/changelogs/4.txt   |   1 -
 .../metadata/android/en-US/changelogs/5.txt   |   1 -
 .../metadata/android/en-US/changelogs/6.txt   |   1 -
 .../metadata/android/fr-FR/changelogs/2.txt   |   2 +-
 .../metadata/android/fr-FR/changelogs/3.txt   |   1 -
 .../metadata/android/fr-FR/changelogs/4.txt   |   1 -
 .../metadata/android/fr-FR/changelogs/5.txt   |   1 -
 .../metadata/android/fr-FR/changelogs/6.txt   |   1 -
 .../android/fr-FR/full_description.txt        |   2 +-
 .../android/fr-FR/short_description.txt       |   2 +-
 fastlane/metadata/android/fr-FR/title.txt     |   2 +-
 icons/build_application_icons.sh              |   9 +-
 icons/button_back.svg                         |   2 -
 icons/button_restart.svg                      |   2 +
 icons/button_start.svg                        |   2 -
 icons/difficulty_easy.svg                     |   2 -
 icons/difficulty_hard.svg                     |   2 -
 icons/difficulty_medium.svg                   |   2 -
 icons/empty.svg                               |   2 +-
 icons/skins/default/tile_black.svg            |   2 +-
 icons/skins/default/tile_empty.svg            |   2 +
 icons/skins/default/tile_white.svg            |   2 +-
 lib/game_board.dart                           | 255 ++++++++++++++
 lib/game_board_scorer.dart                    |  64 ++++
 lib/game_model.dart                           |  58 +++
 lib/main.dart                                 | 332 ++++++++++++++++--
 lib/move_finder.dart                          | 116 ++++++
 lib/provider/data.dart                        |  75 ----
 lib/screens/home.dart                         |  32 --
 lib/styling.dart                              |  76 ++++
 lib/thinking_indicator.dart                   | 143 ++++++++
 pubspec.lock                                  | 132 ++++++-
 pubspec.yaml                                  |   5 +-
 47 files changed, 1171 insertions(+), 168 deletions(-)
 delete mode 100644 assets/icons/button_back.png
 create mode 100644 assets/icons/button_restart.png
 delete mode 100644 assets/icons/button_start.png
 delete mode 100644 assets/icons/difficulty_easy.png
 delete mode 100644 assets/icons/difficulty_hard.png
 delete mode 100644 assets/icons/difficulty_medium.png
 create mode 100644 assets/icons/empty.png
 rename assets/{empty.png => skins/default_tile.png} (100%)
 create mode 100644 assets/skins/default_tile_empty.png
 delete mode 100644 fastlane/metadata/android/en-US/changelogs/3.txt
 delete mode 100644 fastlane/metadata/android/en-US/changelogs/4.txt
 delete mode 100644 fastlane/metadata/android/en-US/changelogs/5.txt
 delete mode 100644 fastlane/metadata/android/en-US/changelogs/6.txt
 delete mode 100644 fastlane/metadata/android/fr-FR/changelogs/3.txt
 delete mode 100644 fastlane/metadata/android/fr-FR/changelogs/4.txt
 delete mode 100644 fastlane/metadata/android/fr-FR/changelogs/5.txt
 delete mode 100644 fastlane/metadata/android/fr-FR/changelogs/6.txt
 delete mode 100644 icons/button_back.svg
 create mode 100644 icons/button_restart.svg
 delete mode 100644 icons/button_start.svg
 delete mode 100644 icons/difficulty_easy.svg
 delete mode 100644 icons/difficulty_hard.svg
 delete mode 100644 icons/difficulty_medium.svg
 create mode 100644 icons/skins/default/tile_empty.svg
 create mode 100644 lib/game_board.dart
 create mode 100644 lib/game_board_scorer.dart
 create mode 100644 lib/game_model.dart
 create mode 100644 lib/move_finder.dart
 delete mode 100644 lib/provider/data.dart
 delete mode 100644 lib/screens/home.dart
 create mode 100644 lib/styling.dart
 create mode 100644 lib/thinking_indicator.dart

diff --git a/android/gradle.properties b/android/gradle.properties
index bc2d95e..818e87b 100644
--- a/android/gradle.properties
+++ b/android/gradle.properties
@@ -1,5 +1,5 @@
 org.gradle.jvmargs=-Xmx1536M
 android.useAndroidX=true
 android.enableJetifier=true
-app.versionName=0.0.1
-app.versionCode=1
+app.versionName=0.0.2
+app.versionCode=2
diff --git a/assets/icons/button_back.png b/assets/icons/button_back.png
deleted file mode 100644
index 2a802ff2d2bc0c90488a1c319288be9f28cdea5e..0000000000000000000000000000000000000000
GIT binary patch
literal 0
HcmV?d00001

literal 3744
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

diff --git a/assets/icons/button_restart.png b/assets/icons/button_restart.png
new file mode 100644
index 0000000000000000000000000000000000000000..389eabc630dcb6d973aae1b616e1783dbc414ca6
GIT binary patch
literal 8633
zcmV;qAx7SbP)<h;3K|Lk000e1NJLTq006)M006)U1^@s6Qrv6@00009a7bBm0016C
z0016B0f4_M2mk;88FWQhbW?9;ba!ELWdL_~cP?peYja~^aAhuUa%Y?FJQ@H1Ax23=
zK~#9!?OkbfR8_Xld%fQK^;SQb!4U-&XQc&2!Nvi!)qdS-Yx`acgc(FckU>;N0Rbl_
znPmte0TYHWgh0X=APiy3JO>g8Nl3^@QmG`KcfU&)9a5+6KKE87b*t*!wZ2}<)l{YK
zIeXu`&)(nuwx6H8<RvfHU5v5+RPab~4SPSkw0>k(aqX1E{My+P5_$pKfepcy6r1V-
z+cKlU|E{3C?wy1J>&Amw)|ilZOV->Y6=kD$m9c?aOWB8;OW6Ct5)%3W+kp+imgYxS
zl)<(RWYxsL){1Vhzrgm~X82W%-JO_kU9%_6k}zRUMa^3Q*V&)eOGq?5U~3a2DlB^y
z+e<98u2CG}&gOjLw~f!Q+Z1rFD)-%>61gD~ZpC|w4Q^0uF`=+7Sh3C4O=<Z5mUX@M
z%k4>)3~BfhW^{zGBujc`QT-Q9Vf-x;3+uwi>?*I4i!EVhjM-goId`@8fMT<ExWxF&
z7<=&OMQi+f@~JQ3A^4kefIgOEjVrUT&Q2MBUa9rjh;&QZ+wy=b;bDNy?p178vEe@$
zd-5yZ6O~z$`leh=2@eHqHzLiFR?1i>y)plPAG=f&C!hQho{m3nxXxm7tmhS*{=KjR
zBo@?${e6>+`6avqD5}Nh*X|NB{><X~ai53FY>$L@VZ36~*(LR3$aLqf6icdHFbQwO
zo>WVUW_mQK(7Fz<3%OVl-iQyBus*4<?iWW-|5lshs<Y%mNq93t6RWehl!?@$y2bL~
zE8*>cji(mYEwXcfsEnF3a)Bg#0f(|{&Vt)^%lONyS+AJ~Dl6sUNcaN2Iapp%Ud4Lc
za)6ZLy5;X|l;MwrZ{V+rttS^+m)vrI=!@2aa$zKV35v}hxa9ylQ!L4HQ6zi`yHYJl
zw)AJa6{l|G%SDm!C9ICE%2U&!%Ktp~RaCiEE{cRNVM=60jbi)VKzn}kv)$!#QG6J$
zuf4{e|2~;LG3^BFJRyp8`g|YjG(J-O?;by<u{YKhd)+;c3omDt7WTSdUM2fzL|B<L
z1RukzEAv^`Ip^8^V<TA00UOvIAFX$Ywu3jbCuf{wudlo2HTMsjhwc02mevg(wp}`a
zFQE6*OYEuXr`X-2cCZ#71!x*Q4;_YYVZ9b-dBs}5=3)EN0lXM*tSe?c7iO@>zCOm<
zE5@tW;CW~{AdtQAQ>t_T33H<FnnKonej<Bt!hY6zV6aP!-p&d916l87xzYh7OcKwp
z$YWh+pJg4#>|rhY1vZJ%H^$u`hpBHE=>QULi|3!5af;pZ$xe1hzxB;x^o@ZxjdTEs
zW{T&Fl-N6sb(wsGwHx}YTMXXrEub8xr2|MbVSc`db)T2OI**TJt^9+U+@L!S4`zdw
z9A@*jUSJ>ou%ES{-Ym-h-}je7=>QV0FHAi)^*C!YD7eXu{;9EB*cTg4v4in>tfsb}
z{q`HXg*E$A$<Oy(m?<4V!gWBNy~D83CNp?E)nA#qn|-$}j>TWPew)Gb@W|*8&F_2e
zyF}>#60QMq_N@kNbh**D8yLvm|1OIC5|zsGif@ocZ$o`OW1UBC*8FZzD5L{;F<x7J
zm35mNuNIS3OgXN^<?-y*6<1vPcV1qetHk-PGyYB^H?ff`j<T>*msn+Wt+3HIM98r$
z^6&IoBtszY%ebs9R*XK5-90KylQMAE$J><<Ac_5Hos)l4`TV`3cROwL&yL^5rUb>Z
zW61@qw(d7WMsKbCjYTKrvxxyGSzCW?j!?_~8`OikbO3KTe6A^C&&)c*+6@WOWq8QN
zzqazK;lJDChZJKK*?s}+^_hFvPdnpT>g7^H1`k{-v#?FknQ8_InIO@>f8VFOWg665
za_rB1bB47Uw8`+(x9yP4?4>2yhW>uX&-RED(gtm0|M=+u3pkk03d^bu8~ugsV)p&^
zIM#PYIBV5Ez|cK=>H%0fKm(w-bmxezE{VI_4i09ot<v`<0L7T1FCcR>_~#>R&zW3S
zWvMe{@HZ^AEL{2g*flZi(N9Ap6~fmYp!d>T^%d^&V$zs!U1x$`i|B*qioMB(jQ(O_
z1zWW*h5hZjC^Zx0GBTXvuz&pdk|e`<WVo}wn01|VPNnrWRj$3qkK%M;9HO<p3u#Ev
z11<jDQRM(TEjX4vKPjwfn4rqR*HcrUKJNe^kRh|v)Ya7o#_kpVO(2v}m0Hm!{?+SM
zYN*sy_k|Eok8?{0FcI+7Z_$5);myYr^^;Y{SkEta2vl1GSf5`CgnrkH3)0B=KlfUt
zuF&U5;#Jn;3)eY1-j)x4aftO<o$odF;4=;YUd@9O4jA72w`cEVk>@X~RZ*LPeY@p6
zT_6%{9fVO)-?ch2#ZW%~=kO$U?=a(hqI*8s!Me^q$NCC7vvdHng*?l0*qtM`8QT2!
z=0&noX@y+ls;mEv<j8cJpCJ4@Deezw3`WzP`6X3s#PXvwvy(@m7#gA+b}xFRZFs!{
zfTd`pB@m$wp7@kuJvV8)c2)M<3&Owk(XXRPE)S2+us<%39ZI+=<One-1+3RsI}Noz
zs?~1k0G<OBXeg<V#z3fmlp#U~ks=bRu&$yBzqlZs{C&Gl=h*#@^t>|l{{welq!NrQ
z(MshW^;CP+bI3;lYRjc`01v=3v(BoAP(2%rJh{k0v)Wq6)*VP=4~?QbvOuEK!#!#}
zP`lw}v~mFF{ibdcZiaYm6o;R%{-jE4pzZ?|WE|-AhDA?KKPer+%y{~nSbc}Qp+PM0
za0Y2GWjCyB!OjHMWps$3eom<F-ws7Kt?z`>;q1})w|%wo^zHl{<xRG5SAy!S)P12c
z4A!WgHGA~yqtXG)`sCNs9R9-O9V|@=A*d(*qFsr)Lk6T=_5OZPtf}ukoqo;kHy&2b
z0K9+u^ti2T>xqlEWv_TZf52b9-KXpRKna%)V5S`Z?DM*eA6XG_W3&uoOH8(EL`I55
zMkvBaHMZ!deQuc*a?b8|qK)xBja28W({{7t$^n=<8%*DHMqfBI<CJs&GXRxTQJFs+
zT#*~sG6tLl-kTp~u-!1gsf-E5O+pcl_nQYUK1>$VKy{|N!8R)4U^{<7iiq-^s1Zm9
zaC84`%l?7FZGqdAkU*>b4=sZ@7Z@!ZAq;coex8~cOB!+x=dd1hBtz);-9KUz3q78#
z=>%w|5iOpz=pW#*)CiAv0JJ2w8N5kY?gJa^Xwyq8YuHB%4jOMXR}8@wApr_^)Zap?
zmY3Dh!|4ZKsJzPRa6Qgt6|)CF-YoQ8t^I>kX03F9X6@X%#_k-sO*p?Fn{iDur~k}2
z<NW~lj^4$3E^?h>G9_Y*@QimKeWr)&`rX|oZr7|Gq+Tf#&w33DWqno`NC#*xJTys+
z+jIAjAa>FLodH0@c>6&HXwgb2f-Wu)*<5{ZkA8KO4CN}S><{qh?$X`VqO8yE*c^xJ
zlbl;BoF;u>+&<|5&4F(75`;DchOHI$EZvhtR&%*=^w@|d<;RFrg?A{9+xULsE?zhE
z21DqCvyY>7!uN`%fjy~O?2!)e%JR!X5`j1@Zq+#OLODUNq1-icyV^e49Eubahv^ds
zRpH0R7#Gx<yXAtz^#b3hjR3U-^b=3%6!SO-Kqr@~ge<U`P(5>%@nch;nsK^W`(Hbc
z-%nJ9H*>4P<JO*ViuXS|^qj+W!&^e+J8(9G$bfVJR~Nfb=@r<3VauW&RzGKKKC6!^
zF)GY0gCIo0JRVg$;%u(d%`aLHkMZlo91LTaqyxB8oo!{FQ0UWr;&z7>UQinJ7($oH
z(QXrc>LXAU{wCzC-917v0<tO2I)S4G98{fASr&O~zHIUdG9Kjs7~3gQ=)!@Gw{bg9
z=LjEo(Kd-Eu)FV>stUh2nO_zD`w#n_c7WCc0vz^4WagI(6${NSn&mMLfJ&ptrY(<1
zc39N8bFkP`5r<C*)S80XI+H%DTq>+I9IJ~kWs`DCxN8a(Iicnv6RSsfh6Aj-t_m=T
z^zHKEepGm&svxTDW~PcJLI~<NujEvPFBjb~)c)uwq;w>#`=P*_ro-^9rWMcf2nRr4
zEgAaw2eK3g70n?_j|ek3doRr~-Til<s>1Ukx%W-AK0*nv&A?5<%vndIK@`$xYWR8S
z07moSXe=?Bzg~YZU1)=02rrw^_;2<KA0?fiR~5zqnW8R0$F#NJ*ri{OW^vbeSwxc1
zo7Id8(x!I+G?kN2m(RB{i?!ZvW3Ck65IU$q;?FEGKew@e0nPFZ<5Y#wEU#Jp_22kU
zUDQ-E+hm(HP*7UUm0m%ZM1B4bb1p~+&<hbc6AW<RJ(>E6Fgukvx!b%rldD$KRbdRl
zXng;B&s`=D`?kLU;}m%dpr3%Z)@atJ&jMT2LZ);89g5AQ@RSng@~WXC8)D1zdqT;+
z^Mw7RTzbPZ5Rw5Oe7~Ozfg1jehbM_q!SQC{Il-U4q2=ApCaq#>2LR!WT2MUYc!e5-
zMIyW&$dY>m`A;AbfR;$KOJZgKM6{@X52{7u!5|_M@u)rUgnAD-=u5u6E)XsqKs5bF
zwK(GGZ<McsLYF5sa9|E^OMllYSwB11KJ@$Jl8Zv;0VEfAYmdp3RLF@rXwm@)JU*4?
zo1g`dM*|QU{P5&7&(pT)@}=t(pAr8%%E~-8C5Bdn7!%4(JfPi_R+EU44nXT<ZXxw?
zc$zmNDLE8oJaMSoD=V(JY=Y!dGh#KT)wCCwQOwg)LTL2lXIsdWs96eQrgQ)_xl@Y|
zWoDjOtw>v=Cu`dyY;k(5(Wo7y0YX+%q@9wNfIv-#JVz`@mk!_vk9-wPHo9aNRB*{|
zBE7qwF6Q*av>3z2k6vTZ`DG$~7rZ0{6e}pwA@*20fCID}s;#++iH5ubn255Orw(-H
z^+o6v{=H}PPL)#b$}}`oG<bXQ?z~7+a$P#Wdj8NlBg5h#_C!g7c*E1bv3v@e&?ymM
zjD1DSZzS%fNQj_JV<c1K{aCY~&cq?(Bptv`+w%;m>c%U_LkQNJ=h;%)NYBiQRrC5V
zSOCuc@Z`g++uV4k4*VkZhsC=SxdS<<FbFNC(gAc9zh0iQi~GubiC{h=tn%b}w(c7(
zRYVRBe`Dqz?w%l2rIa<K12kfOwi=+F=9~GeeG4EOLde|n*T<znH<3mWp7eO)H{O@|
z+b$5bh#<FfgG}WB(Al93IXWrdZlTxirw?o1I^(K2@Y3RJa(yu{r18FBugtzLrg8u(
z#|@DyUiHy`(IM@^*N83Bke%$vYd1u@x;}JiG`A{GsZ6`OQN~mb@W_|i`Ty6Z?dGaE
zKQKZ&M#c9^LvGsI45$%C&H?V;8&f#|G8bBl1;HntIsskzO_4_IB+%GStuwDUNofeV
zn;mK@2WT@$yXgbD<;DxV{p3YbvK&LQr4c)+QM9^%Wasj<N}(-8)hMI`tiL(Q-G~Yr
z)%Oa1yEI@|b?0r>&CkMECTd^%xN!o#X&gYL0-RrBUjX~RAGIaYADpmX8n4T`(zKgw
z1}r*cw?9SY7II&EFTErkpvRACr1Akz^M@*cJvH;RG+q}0TAxN5l&IMY*n6LM0IDe)
zEsng!r7}R>y_Ejo4p0<nj8o$65jABK${#-O0GO>sslM^@%#`|BFBgt2@^yeoOVQMM
zbsA75%sOh-G!F1M!Er~d&*Pm_@ueR6uLMoHqt-i@GrjU3KOHb_i==5Bfa05AqM_XY
zx67sEhR77C3o~_V=u91N;2!o)>obpj9W5OI)Lp&ffS~wHZHU=~m^>L+OKQE(XBXS;
z)2NllG(UsA_jw0+aH95W5*5Y93mZe^m?3#64cE26nrf{%_N4JXeNI$^ADVbjIsoMW
z6V{*9U1Wjwk2Komb$}D8h58*}(gEoJ4}YP}==^l`al3^*n^{DPFoDS^4cB!VrBn!X
zffE9Kyh8hY2fZVocL0hB%A?z2fHQdrUQ;BE*H!9tYYNHrPRlE^+oyqx4-?Hw$D{+G
zV@qq1`Y$|Ws1xkf6*3L#x-@7Wx!#yeqjz2zWL{(;Z2C#fMS5#ignc2bMi#=%RtV#%
z^--$P?xd@jhYIoSdF|l}<F^^2LOds_5H15Xw-|%Fd3*H4XQ6~hucShdQy?+nk+-;z
z>Nabc-P=IXRd|XWkWOqv2zWt&%jX?Hq#^!#MUCz$Fp>`4e01o39F;f-mQnla&SBc7
zaezLnX$66koQ9Y=q1vI-og=qN<8=|JX_a%foYP&bM5@}IO5Nsai6lmL@}xJm5_<HI
z4RmM6kvFA4DG5f16F1(URr_R1q>iR|?dc+u15ep4aK=@EruZL{r4ctnQ#_9e3J#an
zXF87AEgisyE(9TtmkI^Cj1G~qC{4aM(S|ZWfBbqU!2~@j9l(aJv(J&jSiC$lMYnA~
zG*lX~)A7G{Ds#xvBiuSoTYv2gQ1^N9(gE~H@bTD&Lehv!q%@-8eOW^93vXN!HK_Y$
zLwv4ufQDo%Y6jL1VR7748zsf<PQHn!17V603dGdlSZ#4!e<_Y@hmN0Vm(5XD=f#?R
zrfW;^wH+L+IG7~H>3%4!Emnux8Ii2-MJRS)xQDy%&vXtzNpD~ZOktV5KG1@l^dN`s
z^NrIYFgX#!CLaFcuqxqb8${7*d=z_nW-NPU`4#V^KL`xSSQ2hOAOlllD4tf=*=MB#
z7&!+7aE3HrQNkdM>(QK%H7d+dSOy9J-XK)H;el~`-CEUb3SgonH5&kH-*`WM4yVV}
znqgqJ`G(}JyRN))wTI-r|6LUKmHQz<yS>Rf5g(BX`tLoT?9erc4uk73z|I?tzvqGs
z@_yf&7inl>yje1HrkoPlW%3a+4B|a?!q3q1ikOrr@*7@Td6gX2ZB~xEt6+3Ysz`AX
zDj?DU96)3|=l9#=xKqkOn|5|s9u9ugbVLzg;D<L?e!ETB#vPQ6F;>)Pky@1wpkaV*
z25a+zFcF@&`0JJP0k!yevg1%|l=dqMq;w%B<#GByYm1aM3MKCkJRhD~U#F3qJZ55#
zDIMTui{vqK19;@Cn%a7@0Rwn^YK();zs6b*40eeFcq$F!ae+znkBkmcjorw6V08aU
z2O!XUS*}Wz)zp=r&Yu_$)+n_JE&6TX4rrr9dUd}A25e+~e<}1B<L~`*4k>-&C=&<u
z?&l|kk=e3WO!QVXtplisu+j7(>^O%SfwRC1lj-cuog=o{sYY}jA4z@=*``g=nQV6G
zIo5G_aFf;_nmhElYvgvJ*xy=fAAW|Nx<r1q)93q4b<d`D02mInp#L*xFZV4Fb>WK8
z6Z+vVZdWBkdX5t5Z8)bO<#H+OFleJ!bfr<+Og8M}WPb3_d2SNzJUtg?NC(hUgc3<b
z@-{?7kLFgx{hWU_WrLrh^>5)=jsMPw<wuF8k6_bJsTU3X1}!<vU2BlxsLvv^X14n_
zwF8Jyq}Ae<67Jv$)Ob@0N~=lL2-|tU)|lOLfOh<QFg{QBpguD``5NNI1!=5h{|)3l
z+&3(kI}sj-VUfgxyQ$9}=>UjJ(Kbgd?k`cP+$YoKqnScaHaz)}n{H2}|7L~Q_q~=^
zS;>LWkC~+K!xJMA&3bL*P@YBe{ur=lMx}1kJHXAiz*(WE69`zm4H~{IT4;mOliXpr
z_BfxH9L&LbcV48&O{)hNU*zGU75b!JDI=X9Kw-^{w&f8H02;GMVaA^`r4XpBu4UaP
zZg)vq6AVWl_kG3QWRD<!{p-npi6r<n6eYu3j+geN#viG%|EL|N4gWmC0RU=1n+=G^
zc}|d&Tf*)c8sriu;DuWk3oFRafi`WHn4dcA-!k4IK`j2#b?%xj-YvE#FD^)z4&Vxw
zD0ukPVk0k~!%-&yBF|qYDbpfA9f0@!RPEuuPs82M@1GkdROqsi4jpCKAWcv8`vRTE
zn>z*UIS!!U<)va(N_36!vO>V>$P}j?0C|5N4S+ffBHPs0O&UeuKB1XM&wZ}saD8lt
zevGXp6AJ@_*sCk^r31K>r!w_~(B`2ZmA84ociZBec7lkrxpv=sDvj39hrp~m=nZ#$
ztnUmoZ|eo_+9B@8Sxe+Qy3RgtdVBIX2f&kzlIXJ`I6Bjz6M)9xj022Ydx9$ji(%24
zAwe@%g~6%?@k})2u>ou2Xx)$o7Wod)SUh1sp~pFZt!+}IaMNyJp!!sHw3&0a7$?3x
zJ|>j=ozz4`<lJGHO|Q0{rgEM1-j|l~ga1VJ`PxDsPwA2NNC!}x=V!zUZ73?i$N)Lo
zRFv?I9*lX}ksShrFti#rrG`((F?;m0R+R&<qhca}3b;tV-_vF?c&q~;D<rznkWS1l
zsBpNsXr(lgBIR|ZRaDiIhSC&rfJkk2920K%P`^7i$Km=!C*_lbKQqky^(_ZL-|p(G
ztlf|hp^bTZ+*Wm_n4?X`gmb;cGDrOg@6FfN(QiN8byeY>3p0g!ceSX^2@dl7HhJ^A
zhKLzI$ZqbGI`=sTuyI*h3ci{jQ{r}%?j3D5(tFUj)Dt%FG>Rxma8(j;S&s7)Tc({P
zCCjw{wk)s0+c4}AeKSJI1406xW<MV905_||Nvy?3VupY$4R4lhLu`r3X7`T}<H!UZ
zu_uV35J$d|zHzQ9jL#c2eDJ0=97@+*gI|wk2^G3jDH!DeWR@m(pL75{hhkfKUn}Od
zDVyPKKxIAf6y<%s=a*Df*tjk}8ihn1o>#@r<4DRh#7{fpg|a=i7RTqmPx4s1@frtE
z8|kOS=pwaYyi&vNE*{Qg7O^*HML5oPD<Oi#TCY1_-a-kV`mEMp6-EmuHA%-2p$!=-
zt$W1*o|2ls?H&{-bmxRe=>P^qwHjl<qC?!_dyT7~+fH0m57NBvIFxYJzABu4O`t(U
ze^nT&b9(L%Y2c-Ml2o+}t$Rdkr$|d<!`WV4=bZO=d+|C4K=o0yx3ytWi`QJ=7#Pm6
za94sFLpS{VR~t`rtHKYB`jw~(N9n%5_5!qUn{3IVU5T29T$^)azJh3`=a%t%iTtD2
zIe@K3Afjo1TlI24fXW|27(h9~wK5Bvu>Rz&`M1wH7~(y8)iJVSs;4RpVwp(I1L9!3
zu&gnV7Jg^$K7IWVO6cYdPk!%q09%@H`bpif@}r-Is97M&cx<%;n;>smo_%^1!d<T9
z%A>ECO3P~H^c#wYEsID}lL7jKe*;b1*(Dvo0iON#f^ISx@Rx7*sRl0M2si`q)FRM{
z20oH@RXAGLy-?x+)Ne)AyPJXTI2^otF3R#c`|x@PuvJS%+y8DW?)YzD(>I+_4Ozqy
zcz~3<woa+IOgIkB)Z5EZRtskwXeb#;okA?jOzoV~0rb!%R$XOJ%{Xm{8QIXVFp%4b
z1Bf)>^jR&|G}23X0#o0G)NaEAE;_o<AY}C3ADVQ)<LC|20sd+D4^BKFM4J}HUlA5*
zP$_u8@Mx;2B+3qjqli!+UQ|LM(6V)<H93Pm5OR6@3^cEFfF3`j7%CPCheeyuup1Wf
zu!s_k>aK%6eE-<JO>$q2RUFWM>g~qwl@5TiJbG_kZ4{V=g|R<qqCrDARY7hThEQE%
zdZ+|FeoSdH!^cw}vk}ZL<0u_Kiy3Ml<D*4$K&2SOvHX&1LuY`{<MhzKUW+ny75a?w
z{x#J!l<)Mm0e?Q_0C;M-WUSHnZE9r~RA7oeKv4_62{}uqLGiX~EYU8~2hnEmW|tU#
zhvA_fBi}9^z)2}}M=?DPw;1b*;ci9^9?pV#z~sPF>i8yMYO+DCAkdGg0oK}z)tgkw
z$>!)!mJZMi0KHf^wKwWlm8O7!4ir~L3&rIYReTq^nfDGeHdd*-6aBMjK+)R`)^2Es
zYWUuq+VnXGz+5kIR5Ul<Kafoej#cT+q6b(<^ao6(2SvJ7f9F)@P+)TU3B2y+!Cx!<
z18o^Y!n@6j^Z6&fS2_SHy_B(q9Lq9f@E8SjSP5-#E)Y>e6VECIa%Yq|0}S?t2LEGI
zj;lik!G(el*K4ctrLlW^OC%NY=y~cRv_VTCLYw=B1-m@sf`c!9vot{I0L^j$29<#_
zdayac^?yqVZCoLst0j!(ZH!9k0B#R~==oG=`e+>597(*&z79IAraqgxx{9Yhl#)GB
zIYByr$pOV>YNjywI3Ik!U#;XKv=JF^>NNV@)XI5c>IwGh$~<Xs(gB(d;IA~fK?~9e
z?jIY$y3RSLJnf~?O9yDK!4Cviz9|9X9cBUJEYf#Pp)@S%0B)c{taS|)LNv62-acj(
z^je&y=HjI>Ne6H{dN0c*=lnVo+I0LZLY-SI<9X=-=FJE#$Y8DfH_FgP!gm{DFhE0e
ziVTmQ@c7gi8QS=o1LRe*k4A)fPfH}oUQf<ANirr|^hap3=VoZLLWVZJ2G~4o->=NV
z-u!HLx!2tw`UGD1DOHsc?=(J&b^3gtT9CqjqayqInrqS!d>G@x%UPv`_4Q+nJvSw?
zvPLe7gfC%AWJQf)``zFGZC9PHx+)h%!k6$%Y*n6O`>p(N?MSgC%SDm!CG1M6PV%!|
zM=x3r$VHLxB^<qE-G9pglCN2pzq7GKE{udv;9bSmQ;X^r-*SNRYSwe+!HNpGI1;{q
zS%)er%BtA&ehsgvjG8lYaU^^Jhq7zV_%*&#3TqeseUl7>B)l82@svXA0y_s_jJ4bx
zSDhsnNy3}4C9yhFvGvw|yeqk|Zp{bsEg<2=PyeLCy48M;F2yr`zbjSN1SGr@d(&%@
z6&t_9PwUDqsUI^TqT+^JFbQwM#J%N}Sw+^-ej-;=LEScaAeQhJydPY`67p+z`iWi$
zg<^87=l{GxE}n#E12%m8lJ%To)BokC=PIdY_eEybB)=IT7g549@uq@^bW2*Pg+1VB
z<jO0xcHNh5Nqt*7frJM>`6Dwdsf8u%89!&PG7IZ`>{3nK--6|tK*DokekFvzVED<;
zITPHGP*58_c6UXUTwn>4cY0YaT&<13Io8kBSH|`FiDAi>bon-rFdJZ#JCiMG8O8PE
z{hIPZ89AZA8WecGD(Af*=?D_;H~ftks&f(xtbw5O_%+w1{IL#+h1S&(X_oj&dn+vR
zpe)f`fUSMGucCTih9w@<2E`WJ`?>2<{`l|mZ`8e=SWvg&U{=lXkofAX`9~^Cp)@gY
zYbpER%_ZugL_$I@U^}oO*wS~=l_jBx)mewKt;dw7{f28d>fTap@8A8*b}2vVKNLJ%
zR8{xxrPBK0S;e(e67y?kOGxMiYzH<3TT*Q5A=s9myyPV>*IoY)Pf3k10p|O700000
LNkvXXu0mjf35csB

literal 0
HcmV?d00001

diff --git a/assets/icons/button_start.png b/assets/icons/button_start.png
deleted file mode 100644
index 0a3b74a3b98f45de590a7f290b810daba7120912..0000000000000000000000000000000000000000
GIT binary patch
literal 0
HcmV?d00001

literal 3969
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
R3AzAy8S9&2U+Ov${{z{_1KI!p

diff --git a/assets/icons/difficulty_easy.png b/assets/icons/difficulty_easy.png
deleted file mode 100644
index 66f1476dadfda62b03378a040f10737d9edbab1c..0000000000000000000000000000000000000000
GIT binary patch
literal 0
HcmV?d00001

literal 2833
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
U+QhC*{_~;kuyeD$XB~3vKj9&LUH||9

diff --git a/assets/icons/difficulty_hard.png b/assets/icons/difficulty_hard.png
deleted file mode 100644
index 2c1aef8bb260d6e5241a0856c11cfae129c9d24e..0000000000000000000000000000000000000000
GIT binary patch
literal 0
HcmV?d00001

literal 2649
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

diff --git a/assets/icons/difficulty_medium.png b/assets/icons/difficulty_medium.png
deleted file mode 100644
index 146d9b9ca714b9c82e9a5188e88e5cc8736b893e..0000000000000000000000000000000000000000
GIT binary patch
literal 0
HcmV?d00001

literal 2857
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

diff --git a/assets/icons/empty.png b/assets/icons/empty.png
new file mode 100644
index 0000000000000000000000000000000000000000..28f81cf18e57d73b9cce53e1ae7a0525f3bdedbc
GIT binary patch
literal 170
zcmeAS@N?(olHy`uVBq!ia0vp^2SAvS8AxUb{c{0QoCO|{#S9E`&Oq$M*sx!V11Kn2
z;u=vBoS#-wo>-L1P+nfHmzkGcoSayYs+V7sKKq@G6i^X!fKP}kkX~M8dkaW0mIV0)
zGdMiEkp|>Qd%8G=NJzdtXvhfU9a8wcJdT$?0mx)1&=ESoz}U`y@g0cg>FVdQ&MBb@
E0A__NlK=n!

literal 0
HcmV?d00001

diff --git a/assets/empty.png b/assets/skins/default_tile.png
similarity index 100%
rename from assets/empty.png
rename to assets/skins/default_tile.png
diff --git a/assets/skins/default_tile_black.png b/assets/skins/default_tile_black.png
index c9147334912e10a656a748dacd9e5ee8a51210bb..5fed42df2e38f0385dfb1bc1fe4f2c1c020d8bec 100644
GIT binary patch
literal 3387
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
H9x?VmKeBNS

delta 3334
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
QeE<Le07*qoM6N<$f^xxczW@LL

diff --git a/assets/skins/default_tile_empty.png b/assets/skins/default_tile_empty.png
new file mode 100644
index 0000000000000000000000000000000000000000..586de0573e7f77d97c16942f603b8ee6d9c7d7bc
GIT binary patch
literal 170
zcmeAS@N?(olHy`uVBq!ia0vp^2SAvS8AxUb{c{0QoCO|{#S9EG5g^QXcE<BFKtah8
z*NBqf{Irtt#G+J&^73-M%)IR4<ivthz5Jr|+3#$mfQpy{d_r7-^ztg(TR@7jB*-tA
z!Qt7BG$2RX)5S4FLh|iFLq;I)kizffalHHqKqf<hj?e)H#&-6L??60HS3j3^P6<r_
DJR2=x

literal 0
HcmV?d00001

diff --git a/assets/skins/default_tile_white.png b/assets/skins/default_tile_white.png
index 7ac8407cc621b5931503d80be48443d44fead163..afd8939dc1e839364210e534ed908e6e0bc1a6e1 100644
GIT binary patch
literal 3025
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

delta 3222
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
It^-0~g4D=6!~g&Q

diff --git a/fastlane/metadata/android/en-US/changelogs/2.txt b/fastlane/metadata/android/en-US/changelogs/2.txt
index fe56ebf..d636f6b 100644
--- a/fastlane/metadata/android/en-US/changelogs/2.txt
+++ b/fastlane/metadata/android/en-US/changelogs/2.txt
@@ -1 +1 @@
-Improve CI/CD, add jabber notification on create tag
+Add minimal gameplay
diff --git a/fastlane/metadata/android/en-US/changelogs/3.txt b/fastlane/metadata/android/en-US/changelogs/3.txt
deleted file mode 100644
index c4767c3..0000000
--- a/fastlane/metadata/android/en-US/changelogs/3.txt
+++ /dev/null
@@ -1 +0,0 @@
-Add minimal playable game.
diff --git a/fastlane/metadata/android/en-US/changelogs/4.txt b/fastlane/metadata/android/en-US/changelogs/4.txt
deleted file mode 100644
index 60ec69f..0000000
--- a/fastlane/metadata/android/en-US/changelogs/4.txt
+++ /dev/null
@@ -1 +0,0 @@
-Finalize minimal gameplay.
diff --git a/fastlane/metadata/android/en-US/changelogs/5.txt b/fastlane/metadata/android/en-US/changelogs/5.txt
deleted file mode 100644
index 8b03873..0000000
--- a/fastlane/metadata/android/en-US/changelogs/5.txt
+++ /dev/null
@@ -1 +0,0 @@
-Remove flag on cell when explored.
diff --git a/fastlane/metadata/android/en-US/changelogs/6.txt b/fastlane/metadata/android/en-US/changelogs/6.txt
deleted file mode 100644
index 9ff6c06..0000000
--- a/fastlane/metadata/android/en-US/changelogs/6.txt
+++ /dev/null
@@ -1 +0,0 @@
-Ensure first cell is not mined (postone put mines on board)
diff --git a/fastlane/metadata/android/fr-FR/changelogs/2.txt b/fastlane/metadata/android/fr-FR/changelogs/2.txt
index cdf380a..7e81cee 100644
--- a/fastlane/metadata/android/fr-FR/changelogs/2.txt
+++ b/fastlane/metadata/android/fr-FR/changelogs/2.txt
@@ -1 +1 @@
-Amélioration de la chaîne CI/CD, envoi d'un message à la création de version
+Ajout du jeu minimal
diff --git a/fastlane/metadata/android/fr-FR/changelogs/3.txt b/fastlane/metadata/android/fr-FR/changelogs/3.txt
deleted file mode 100644
index 75d5298..0000000
--- a/fastlane/metadata/android/fr-FR/changelogs/3.txt
+++ /dev/null
@@ -1 +0,0 @@
-Ajout du jeu minimal, jouable.
diff --git a/fastlane/metadata/android/fr-FR/changelogs/4.txt b/fastlane/metadata/android/fr-FR/changelogs/4.txt
deleted file mode 100644
index 6f741b5..0000000
--- a/fastlane/metadata/android/fr-FR/changelogs/4.txt
+++ /dev/null
@@ -1 +0,0 @@
-Finalisation du jeu minimal.
diff --git a/fastlane/metadata/android/fr-FR/changelogs/5.txt b/fastlane/metadata/android/fr-FR/changelogs/5.txt
deleted file mode 100644
index 0b46e4f..0000000
--- a/fastlane/metadata/android/fr-FR/changelogs/5.txt
+++ /dev/null
@@ -1 +0,0 @@
-Enlève le marquage sur les cellules parcourues.
diff --git a/fastlane/metadata/android/fr-FR/changelogs/6.txt b/fastlane/metadata/android/fr-FR/changelogs/6.txt
deleted file mode 100644
index 0c8a46b..0000000
--- a/fastlane/metadata/android/fr-FR/changelogs/6.txt
+++ /dev/null
@@ -1 +0,0 @@
-Impossibilité de tomber sur une mine au premier coup (reporte la génération de la grille)
diff --git a/fastlane/metadata/android/fr-FR/full_description.txt b/fastlane/metadata/android/fr-FR/full_description.txt
index 170a1a6..3369f59 100644
--- a/fastlane/metadata/android/fr-FR/full_description.txt
+++ b/fastlane/metadata/android/fr-FR/full_description.txt
@@ -1 +1 @@
-Jeu du démineur simple
+Jeu du reversi simple
diff --git a/fastlane/metadata/android/fr-FR/short_description.txt b/fastlane/metadata/android/fr-FR/short_description.txt
index 170a1a6..3369f59 100644
--- a/fastlane/metadata/android/fr-FR/short_description.txt
+++ b/fastlane/metadata/android/fr-FR/short_description.txt
@@ -1 +1 @@
-Jeu du démineur simple
+Jeu du reversi simple
diff --git a/fastlane/metadata/android/fr-FR/title.txt b/fastlane/metadata/android/fr-FR/title.txt
index 170a1a6..3369f59 100644
--- a/fastlane/metadata/android/fr-FR/title.txt
+++ b/fastlane/metadata/android/fr-FR/title.txt
@@ -1 +1 @@
-Jeu du démineur simple
+Jeu du reversi simple
diff --git a/icons/build_application_icons.sh b/icons/build_application_icons.sh
index 9a5488a..7909dd5 100755
--- a/icons/build_application_icons.sh
+++ b/icons/build_application_icons.sh
@@ -46,6 +46,7 @@ function build_asset_image() {
 function build_icons_for_skin() {
   SKIN_CODE="$1"
 
+  build_icon_for_skin ${SKIN_CODE} tile_empty
   build_icon_for_skin ${SKIN_CODE} tile_black
   build_icon_for_skin ${SKIN_CODE} tile_white
 }
@@ -58,13 +59,9 @@ function build_icon_for_skin() {
 }
 
 # Game icons
-build_asset_image ${CURRENT_DIR}/button_back.svg ${BASE_DIR}/assets/icons/button_back.png
-build_asset_image ${CURRENT_DIR}/button_start.svg ${BASE_DIR}/assets/icons/button_start.png
-build_asset_image ${CURRENT_DIR}/difficulty_easy.svg ${BASE_DIR}/assets/icons/difficulty_easy.png
-build_asset_image ${CURRENT_DIR}/difficulty_medium.svg ${BASE_DIR}/assets/icons/difficulty_medium.png
-build_asset_image ${CURRENT_DIR}/difficulty_hard.svg ${BASE_DIR}/assets/icons/difficulty_hard.png
+build_asset_image ${CURRENT_DIR}/button_restart.svg ${BASE_DIR}/assets/icons/button_restart.png
+build_asset_image ${CURRENT_DIR}/empty.svg ${BASE_DIR}/assets/icons/empty.png
 build_asset_image ${CURRENT_DIR}/game_win.svg ${BASE_DIR}/assets/icons/game_win.png
-build_asset_image ${CURRENT_DIR}/empty.svg ${BASE_DIR}/assets/empty.png
 
 # Skins
 build_icons_for_skin "default"
diff --git a/icons/button_back.svg b/icons/button_back.svg
deleted file mode 100644
index 2622a57..0000000
--- a/icons/button_back.svg
+++ /dev/null
@@ -1,2 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<svg enable-background="new 0 0 100 100" version="1.1" viewBox="0 0 93.665 93.676" xml:space="preserve" xmlns="http://www.w3.org/2000/svg"><rect x=".44662" y=".89101" width="92.772" height="91.894" ry="11.689" fill="#e41578" stroke="#fff" stroke-width=".238"/><path d="m59.387 71.362c1.1248 1.1302 4.0012 1.1302 4.0012 0v-45.921c0-1.1316-2.8832-1.1316-4.0121 0l-37.693 20.918c-1.1289 1.1248-1.1479 2.9551-0.02171 4.084z" fill="#fefeff" stroke="#930e4e" stroke-linecap="round" stroke-linejoin="round" stroke-width="8.257"/><path d="m57.857 68.048c0.96243 0.96706 3.4236 0.96706 3.4236 0v-39.292c0-0.96825-2.467-0.96825-3.4329 0l-32.252 17.898c-0.96594 0.96243-0.9822 2.5285-0.01858 3.4945z" fill="#fefeff" stroke="#feffff" stroke-linecap="round" stroke-linejoin="round" stroke-width="4.314"/></svg>
diff --git a/icons/button_restart.svg b/icons/button_restart.svg
new file mode 100644
index 0000000..1d18f3b
--- /dev/null
+++ b/icons/button_restart.svg
@@ -0,0 +1,2 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<svg enable-background="new 0 0 100 100" version="1.1" viewBox="0 0 93.665 93.676" xml:space="preserve" xmlns="http://www.w3.org/2000/svg"><rect x=".44662" y=".89101" width="92.772" height="91.894" ry="11.689" fill="#49a1ee" stroke="#fff" stroke-width=".238"/><switch transform="matrix(.69484 0 0 .69484 12.09 12.096)" fill="#fefeff" stroke="#105ca1" stroke-width="5.7567"><foreignObject width="1" height="1" requiredExtensions="http://ns.adobe.com/AdobeIllustrator/10.0/"/><g fill="#fefeff" stroke="#105ca1" stroke-width="5.7567"><g fill="#fefeff" stroke="#105ca1" stroke-width="5.7567"><path d="m43.3 91.8-18.3 5.5c-2.5 0.7-5.1-0.7-5.9-3.1-0.7-2.5 0.7-5.1 3.1-5.9l6.8-2c-12.4-7.3-20.8-20.8-20.8-36.3 0-17.3 10.6-32.2 25.6-38.6 3.1-1.3 6.6 1 6.6 4.3 0 1.9-1.1 3.6-2.8 4.3-11.8 5-20 16.5-20 30 0 12.2 6.8 22.9 16.8 28.4l-2.4-8.1c-0.7-2.5 0.7-5.1 3.1-5.9 2.5-0.7 5.1 0.7 5.9 3.1l5.5 18.3c0.7 2.6-0.7 5.2-3.2 6z"/><path d="m77.7 11.7-6.8 2c12.5 7.3 20.9 20.8 20.9 36.3 0 17.3-10.6 32.2-25.6 38.6-3.1 1.3-6.6-1-6.6-4.3 0-1.9 1.1-3.6 2.8-4.3 11.8-5 20-16.5 20-30 0-12.2-6.8-22.9-16.8-28.4l2.4 8.1c0.7 2.5-0.7 5.1-3.1 5.9-2.5 0.7-5.1-0.7-5.9-3.1l-5.5-18.3c-0.7-2.5 0.7-5.1 3.2-5.9l18.3-5.6c2.5-0.7 5.1 0.7 5.9 3.1 0.7 2.5-0.7 5.2-3.2 5.9z"/></g></g></switch></svg>
diff --git a/icons/button_start.svg b/icons/button_start.svg
deleted file mode 100644
index e9d49d2..0000000
--- a/icons/button_start.svg
+++ /dev/null
@@ -1,2 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<svg enable-background="new 0 0 100 100" version="1.1" viewBox="0 0 93.665 93.676" xml:space="preserve" xmlns="http://www.w3.org/2000/svg"><rect x=".44662" y=".89101" width="92.772" height="91.894" ry="11.689" fill="#49a1ee" stroke="#fff" stroke-width=".238"/><path d="m34.852 25.44c-1.1248-1.1302-4.0012-1.1302-4.0012 0v45.921c0 1.1316 2.8832 1.1316 4.0121 0l37.693-20.918c1.1289-1.1248 1.1479-2.9551 0.02171-4.084z" fill="#fefeff" stroke="#105ca1" stroke-linecap="round" stroke-linejoin="round" stroke-width="8.257"/><path d="m36.382 28.754c-0.96243-0.96706-3.4236-0.96706-3.4236 0v39.292c0 0.96825 2.467 0.96825 3.4329 0l32.252-17.898c0.96594-0.96243 0.9822-2.5285 0.01858-3.4945z" fill="#fefeff" stroke="#feffff" stroke-linecap="round" stroke-linejoin="round" stroke-width="4.314"/></svg>
diff --git a/icons/difficulty_easy.svg b/icons/difficulty_easy.svg
deleted file mode 100644
index da0e21f..0000000
--- a/icons/difficulty_easy.svg
+++ /dev/null
@@ -1,2 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<svg enable-background="new 0 0 100 100" version="1.1" viewBox="0 0 102 102" xml:space="preserve" xmlns="http://www.w3.org/2000/svg"><rect x="1" y="1" width="100" height="100" ry="0" fill="#41ff6a" stroke="#000" stroke-width="2"/><path d="m23.408 53.415 20.8 13.7c0.2 0.1 0.3 0.2 0.5 0.3 1.3 0.5 2.8-0.1 3.3-1.3 0.5-1.3-0.1-2.8-1.3-3.3l-23.2-9.6c-0.2 0-0.3 0.2-0.1 0.2zm23.7 11.6c0.1 0.8-0.5 1.4-1.3 1.5s-1.4-0.5-1.5-1.3 0.5-1.4 1.3-1.5c0.8 0 1.5 0.5 1.5 1.3z"/><path d="m41.708 36.515c0.1 0.4 0.6 0.7 1 0.7 0.9-0.1 1.9-0.1 2.8-0.1 1.5 0 2.9 0.1 4.3 0.3 0.6 0.1 1.2-0.4 1.2-1v-6.9c0-0.6-0.5-1-1-1-3.2 0.1-6.4 0.7-9.3 1.6-0.5 0.2-0.8 0.7-0.6 1.3z"/><path d="m52.508 37.815c2.1 0.5 4.2 1.3 6.2 2.2 0.5 0.3 1.2 0 1.4-0.6l2.7-8.2c0.2-0.5-0.1-1.1-0.6-1.3-3-0.9-6.1-1.5-9.3-1.6-0.6 0-1 0.4-1 1v7.5c-0.1 0.5 0.2 0.9 0.6 1z"/><path d="m81.508 46.115-8.4 6.1c-0.4 0.3-0.5 0.8-0.3 1.3 0.9 1.6 1.6 3.2 2.2 4.9 0.2 0.5 0.7 0.8 1.2 0.6l9.8-3.2c0.5-0.2 0.8-0.7 0.6-1.3-1-2.9-2.3-5.7-3.8-8.2-0.2-0.4-0.9-0.6-1.3-0.2z"/><path d="m32.908 40.015c2.3-1.1 4.7-2 7.2-2.5 0.6-0.1 1-0.7 0.8-1.3l-1.5-4.7c-0.2-0.5-0.8-0.8-1.3-0.6-2.9 1.2-5.7 2.7-8.2 4.6-0.4 0.3-0.5 0.9-0.2 1.4l2 2.8c0.2 0.4 0.8 0.5 1.2 0.3z"/><path d="m63.408 31.615-2.8 8.6c-0.1 0.4 0 0.9 0.4 1.1 1.7 1 3.4 2.2 4.9 3.6 0.4 0.4 1.1 0.3 1.5-0.1l5.7-7.9c0.3-0.4 0.2-1.1-0.2-1.4-2.5-1.9-5.3-3.4-8.2-4.6-0.5-0.2-1.1 0.1-1.3 0.7z"/><path d="m67.908 46.815c1.3 1.4 2.5 2.8 3.5 4.4 0.3 0.5 0.9 0.6 1.4 0.3l8.3-6c0.4-0.3 0.5-0.9 0.2-1.4-1.8-2.5-3.9-4.8-6.2-6.8-0.4-0.4-1.1-0.3-1.5 0.2l-5.9 8.1c-0.2 0.3-0.2 0.8 0.2 1.2z"/><path d="m24.408 46.315c1.8-2 3.9-3.7 6.2-5.1 0.5-0.3 0.6-1 0.3-1.4l-1.8-2.4c-0.3-0.5-1-0.6-1.5-0.2-2.3 2-4.4 4.3-6.2 6.8-0.3 0.4-0.2 1.1 0.2 1.4l1.4 1c0.5 0.3 1 0.3 1.4-0.1z"/><path d="m13.808 54.815 6 2c0.5 0.2 1-0.1 1.2-0.6 1.1-2.6 2.2-4.3 3.9-6.4 0.4-0.4 0.3-1.1-0.2-1.4l-5.9-4.2c-0.5-0.3-1.1-0.2-1.4 0.3-1.6 2.5-3.2 6.1-4.1 9-0.3 0.6 0 1.2 0.5 1.3z"/><path d="m75.808 60.915c0.4 1.7 0.7 3.5 0.9 5.3 0 0.5 0.5 0.9 1 0.9h10.2c0.6 0 1-0.5 1-1-0.1-3.1-0.5-6-1.3-8.9-0.1-0.6-0.7-0.9-1.3-0.7l-9.8 3.2c-0.6 0.2-0.9 0.7-0.7 1.2z"/><path d="m15.808 67.115c0.1-3.2 0.7-6.3 1.7-9.2 0.2-0.5-0.1-1.1-0.6-1.3l-0.4-0.1c-0.5-0.2-1.1 0.1-1.3 0.7-0.8 3.2-1.3 6.5-1.3 9.9z"/></svg>
diff --git a/icons/difficulty_hard.svg b/icons/difficulty_hard.svg
deleted file mode 100644
index 254346a..0000000
--- a/icons/difficulty_hard.svg
+++ /dev/null
@@ -1,2 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<svg enable-background="new 0 0 100 100" version="1.1" viewBox="0 0 102 102" xml:space="preserve" xmlns="http://www.w3.org/2000/svg"><rect x="1" y="1" width="100" height="100" ry="0" fill="#d31158" stroke="#000" stroke-width="2"/><path d="m69.154 59.254-24.4 5.1c-0.2 0-0.4 0.1-0.5 0.1-1.3 0.6-1.9 2-1.4 3.3 0.6 1.3 2 1.9 3.3 1.4l23-9.7c0.2 0 0.1-0.2 0-0.2zm-25 8.7c-0.6-0.5-0.6-1.4-0.1-2s1.4-0.6 2-0.1 0.6 1.4 0.1 2c-0.5 0.5-1.4 0.6-2 0.1z"/><path d="m41.054 38.354c0.1 0.4 0.6 0.7 1 0.7 0.9-0.1 1.9-0.1 2.8-0.1 1.5 0 2.9 0.1 4.3 0.3 0.6 0.1 1.2-0.4 1.2-1v-6.9c0-0.6-0.5-1-1-1-3.2 0.1-6.4 0.7-9.3 1.6-0.5 0.2-0.8 0.7-0.6 1.3z"/><path d="m51.854 39.754c2.1 0.5 4.2 1.3 6.2 2.2 0.5 0.3 1.2 0 1.4-0.6l2.7-8.2c0.2-0.5-0.1-1.1-0.6-1.3-3-0.9-6.1-1.5-9.3-1.6-0.6 0-1 0.4-1 1v7.5c-0.2 0.5 0.1 0.9 0.6 1z"/><path d="m82.754 46.554-12.2 8.9c-0.4 0.3-0.5 0.8-0.3 1.3 0.9 1.6 1.2 2.6 1.8 4.3 0.2 0.5 0.7 0.8 1.2 0.6l14.4-4.7c0.5-0.2 0.8-0.7 0.6-1.3-1-2.9-2.6-6.4-4.1-8.9-0.3-0.5-1-0.6-1.4-0.2z"/><path d="m32.154 41.854c2.3-1.1 4.7-2 7.2-2.5 0.6-0.1 1-0.7 0.8-1.3l-1.5-4.7c-0.2-0.5-0.8-0.8-1.3-0.6-2.9 1.2-5.7 2.7-8.2 4.6-0.4 0.3-0.5 0.9-0.2 1.4l2 2.8c0.3 0.4 0.8 0.5 1.2 0.3z"/><path d="m62.754 33.454-2.8 8.6c-0.1 0.4 0 0.9 0.4 1.1 1.7 1 3.4 2.2 4.9 3.6 0.4 0.4 1.1 0.3 1.5-0.1l5.7-7.9c0.3-0.4 0.2-1.1-0.2-1.4-2.5-1.9-5.3-3.4-8.2-4.6-0.5-0.1-1.1 0.2-1.3 0.7z"/><path d="m67.154 48.654c1.3 1.4 2.5 2.8 3.5 4.4 0.3 0.5 0.9 0.6 1.4 0.3l8.3-6c0.4-0.3 0.5-0.9 0.2-1.4-1.8-2.5-3.9-4.8-6.2-6.8-0.4-0.4-1.1-0.3-1.5 0.2l-5.9 8.1c-0.2 0.3-0.1 0.9 0.2 1.2z"/><path d="m23.654 48.154c1.8-2 3.9-3.7 6.2-5.1 0.5-0.3 0.6-1 0.3-1.4l-1.7-2.4c-0.3-0.5-1-0.6-1.5-0.2-2.3 2-4.4 4.3-6.2 6.8-0.3 0.4-0.2 1.1 0.2 1.4l1.4 1c0.4 0.4 1 0.3 1.3-0.1z"/><path d="m15.954 57.654 0.5 0.2c0.5 0.2 1-0.1 1.2-0.6 1.1-2.6 2.5-5 4.2-7.1 0.4-0.4 0.3-1.1-0.2-1.4l-1.2-0.8c-0.3-0.4-1-0.2-1.3 0.3-1.6 2.5-2.9 5.3-3.8 8.2-0.2 0.5 0.1 1.1 0.6 1.2z"/><path d="m75.054 62.754c0.4 1.7 0.7 3.5 0.9 5.3 0 0.5 0.5 0.9 1 0.9h10.2c0.6 0 1-0.5 1-1-0.1-3.1-0.5-6-1.3-8.9-0.1-0.6-0.7-0.9-1.3-0.7l-9.8 3.2c-0.5 0.2-0.8 0.7-0.7 1.2z"/><path d="m15.054 68.954c0.1-3.2 0.7-6.3 1.7-9.2 0.2-0.5-0.1-1.1-0.6-1.3l-0.3-0.1c-0.5-0.2-1.1 0.1-1.3 0.7-0.8 3.2-1.3 6.5-1.3 9.9z"/></svg>
diff --git a/icons/difficulty_medium.svg b/icons/difficulty_medium.svg
deleted file mode 100644
index a6a8c55..0000000
--- a/icons/difficulty_medium.svg
+++ /dev/null
@@ -1,2 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<svg enable-background="new 0 0 100 100" version="1.1" viewBox="0 0 102 102" xml:space="preserve" xmlns="http://www.w3.org/2000/svg"><rect x="1" y="1" width="100" height="100" ry="0" fill="#eeb517" stroke="#000" stroke-width="2"/><path d="m53.928 43.009-11 21.7c-0.1 0.2-0.1 0.3-0.2 0.5-0.4 1.4 0.4 2.7 1.7 3.2 1.4 0.4 2.7-0.4 3.2-1.7l6.6-23.7c0-0.1-0.2-0.2-0.3 0zm-8.5 24.3c-0.8 0.1-1.5-0.4-1.6-1.1-0.1-0.8 0.4-1.5 1.1-1.6 0.8-0.1 1.5 0.4 1.6 1.1 0.1 0.8-0.4 1.5-1.1 1.6z"/><path d="m41.128 37.409c0.1 0.4 0.6 0.7 1 0.7 0.9-0.1 1.9-0.1 2.8-0.1 1.5 0 2.9 0.1 4.3 0.3 0.6 0.1 1.2-0.4 1.2-1v-6.9c0-0.6-0.5-1-1-1-3.2 0.1-6.4 0.7-9.3 1.6-0.5 0.2-0.8 0.7-0.6 1.3z"/><path d="m51.928 41.209c2.1 0.5 3.5 1 5.5 2 0.5 0.3 1.2 0 1.4-0.6l4.2-12.8c0.2-0.5-0.1-1.1-0.6-1.3-3-0.9-6.9-1.5-10.1-1.7-0.6 0-1 0.4-1 1v12.4c-0.1 0.5 0.2 0.9 0.6 1z"/><path d="m80.928 47.009-8.4 6.1c-0.4 0.3-0.5 0.8-0.3 1.3 0.9 1.6 1.6 3.2 2.2 4.9 0.2 0.5 0.7 0.8 1.2 0.6l9.8-3.2c0.5-0.2 0.8-0.7 0.6-1.3-1-2.9-2.3-5.7-3.8-8.2-0.2-0.4-0.9-0.5-1.3-0.2z"/><path d="m32.328 40.909c2.3-1.1 4.7-2 7.2-2.5 0.6-0.1 1-0.7 0.8-1.3l-1.5-4.7c-0.2-0.5-0.8-0.8-1.3-0.6-2.9 1.2-5.7 2.7-8.2 4.6-0.4 0.3-0.5 0.9-0.2 1.4l2 2.8c0.2 0.4 0.8 0.5 1.2 0.3z"/><path d="m62.828 32.509-2.8 8.6c-0.1 0.4 0 0.9 0.4 1.1 1.7 1 3.4 2.2 4.9 3.6 0.4 0.4 1.1 0.3 1.5-0.1l5.7-7.9c0.3-0.4 0.2-1.1-0.2-1.4-2.5-1.9-5.3-3.4-8.2-4.6-0.5-0.1-1.1 0.2-1.3 0.7z"/><path d="m67.328 47.709c1.3 1.4 2.5 2.8 3.5 4.4 0.3 0.5 0.9 0.6 1.4 0.3l8.3-6c0.4-0.3 0.5-0.9 0.2-1.4-1.8-2.5-3.9-4.8-6.2-6.8-0.4-0.4-1.1-0.3-1.5 0.2l-5.8 8.1c-0.3 0.3-0.3 0.9 0.1 1.2z"/><path d="m23.828 47.209c1.8-2 3.9-3.7 6.2-5.1 0.5-0.3 0.6-1 0.3-1.4l-1.8-2.4c-0.3-0.5-1-0.6-1.5-0.2-2.3 2-4.4 4.3-6.2 6.8-0.3 0.4-0.2 1.1 0.2 1.4l1.4 1c0.5 0.4 1 0.3 1.4-0.1z"/><path d="m16.128 56.709 0.5 0.2c0.5 0.2 1-0.1 1.2-0.6 1.1-2.6 2.5-5 4.2-7.1 0.4-0.4 0.3-1.1-0.2-1.4l-1.2-0.8c-0.5-0.3-1.1-0.2-1.4 0.3-1.6 2.5-2.9 5.3-3.8 8.2-0.1 0.5 0.2 1.1 0.7 1.2z"/><path d="m75.228 61.809c0.4 1.7 0.7 3.5 0.9 5.3 0 0.5 0.5 0.9 1 0.9h10.2c0.6 0 1-0.5 1-1-0.1-3.1-0.5-6-1.3-8.9-0.1-0.6-0.7-0.9-1.3-0.7l-9.8 3.2c-0.6 0.2-0.8 0.7-0.7 1.2z"/><path d="m15.228 68.009c0.1-3.2 0.7-6.3 1.7-9.2 0.2-0.5-0.1-1.1-0.6-1.3l-0.3-0.1c-0.5-0.2-1.1 0.1-1.3 0.7-0.8 3.2-1.3 6.5-1.3 9.9z"/></svg>
diff --git a/icons/empty.svg b/icons/empty.svg
index 6b7cca7..d988c49 100644
--- a/icons/empty.svg
+++ b/icons/empty.svg
@@ -1,2 +1,2 @@
 <?xml version="1.0" encoding="UTF-8"?>
-<svg enable-background="new 0 0 100 100" version="1.1" viewBox="0 0 100 100" xml:space="preserve" xmlns="http://www.w3.org/2000/svg"><rect width="100" height="100" ry="2" fill="none"/></svg>
+<svg enable-background="new 0 0 100 100" version="1.1" viewBox="0 0 93.665 93.676" xml:space="preserve" xmlns="http://www.w3.org/2000/svg"/>
diff --git a/icons/skins/default/tile_black.svg b/icons/skins/default/tile_black.svg
index 76875fd..9bc8744 100644
--- a/icons/skins/default/tile_black.svg
+++ b/icons/skins/default/tile_black.svg
@@ -1,2 +1,2 @@
 <?xml version="1.0" encoding="UTF-8"?>
-<svg enable-background="new 0 0 100 100" version="1.1" viewBox="0 0 100 100" xml:space="preserve" xmlns="http://www.w3.org/2000/svg"><rect width="100" height="100" ry="2" fill="none"/><circle cx="50" cy="50" r="42.259" stroke="#919191" stroke-linecap="round" stroke-linejoin="round" stroke-width="6.37"/></svg>
+<svg enable-background="new 0 0 100 100" version="1.1" viewBox="0 0 100 100" xml:space="preserve" xmlns="http://www.w3.org/2000/svg"><rect width="100" height="100" ry="2" fill="none"/><circle cx="50" cy="50" r="42.259" stroke="#313131" stroke-linecap="round" stroke-linejoin="round" stroke-width="4"/></svg>
diff --git a/icons/skins/default/tile_empty.svg b/icons/skins/default/tile_empty.svg
new file mode 100644
index 0000000..6b7cca7
--- /dev/null
+++ b/icons/skins/default/tile_empty.svg
@@ -0,0 +1,2 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<svg enable-background="new 0 0 100 100" version="1.1" viewBox="0 0 100 100" xml:space="preserve" xmlns="http://www.w3.org/2000/svg"><rect width="100" height="100" ry="2" fill="none"/></svg>
diff --git a/icons/skins/default/tile_white.svg b/icons/skins/default/tile_white.svg
index a41d136..e26fc61 100644
--- a/icons/skins/default/tile_white.svg
+++ b/icons/skins/default/tile_white.svg
@@ -1,2 +1,2 @@
 <?xml version="1.0" encoding="UTF-8"?>
-<svg enable-background="new 0 0 100 100" version="1.1" viewBox="0 0 100 100" xml:space="preserve" xmlns="http://www.w3.org/2000/svg"><rect width="100" height="100" ry="2" fill="none"/><circle cx="50" cy="50" r="42.259" fill="#fff" stroke="#919191" stroke-linecap="round" stroke-linejoin="round" stroke-width="6.37"/></svg>
+<svg enable-background="new 0 0 100 100" version="1.1" viewBox="0 0 100 100" xml:space="preserve" xmlns="http://www.w3.org/2000/svg"><rect width="100" height="100" ry="2" fill="none"/><circle cx="50" cy="50" r="42.259" fill="#fff" stroke="#ececec" stroke-linecap="round" stroke-linejoin="round" stroke-width="4"/></svg>
diff --git a/lib/game_board.dart b/lib/game_board.dart
new file mode 100644
index 0000000..1591fba
--- /dev/null
+++ b/lib/game_board.dart
@@ -0,0 +1,255 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+enum PieceType {
+  empty,
+  black,
+  white,
+}
+
+/// This method flips a black piece to a white one, and vice versa. I'm still
+/// unsure about having it as a global function, but don't know where else to
+/// put it.
+PieceType getOpponent(PieceType player) =>
+    (player == PieceType.black) ? PieceType.white : PieceType.black;
+
+/// A position on the reversi board. Just an [x] and [y] coordinate pair.
+class Position {
+  final int x;
+  final int y;
+
+  const Position(this.x, this.y);
+}
+
+/// An immutable representation of a reversi game's board.
+class GameBoard {
+  static final int height = 8;
+  static final int width = 8;
+  final List<List<PieceType>> rows;
+
+  // Because calculating out all the available moves for a player can be
+  // expensive, they're cached here.
+  final _availableMoveCache = <PieceType, List<Position>>{};
+
+  /// Default constructor, which creates a board with pieces in starting
+  /// position.
+  GameBoard() : rows = _emptyBoard;
+
+  /// Copy constructor.
+  GameBoard.fromGameBoard(GameBoard other)
+      : rows = List.generate(height, (i) => List.from(other.rows[i]));
+
+  /// Retrieves the type of piece at a location on the game board.
+  PieceType getPieceAtLocation(int x, int y) {
+    assert(x >= 0 && x < width);
+    assert(y >= 0 && y < height);
+    return rows[y][x];
+  }
+
+  /// Gets the total number of pieces of a particular type.
+  int getPieceCount(PieceType pieceType) {
+    return rows.fold(
+      0,
+      (s, e) => s + e.where((e) => e == pieceType).length,
+    );
+  }
+
+  /// Calculates the list of available moves on this board for a player. These
+  /// moves are calculated for the first call and cached for any subsequent
+  /// ones.
+  List<Position> getMovesForPlayer(PieceType player) {
+    if (player == PieceType.empty) {
+      return [];
+    }
+
+    if (_availableMoveCache.containsKey(player)) {
+      return _availableMoveCache[player]!;
+    }
+
+    final legalMoves = <Position>[];
+    for (var x = 0; x < width; x++) {
+      for (var y = 0; y < width; y++) {
+        if (isLegalMove(x, y, player)) {
+          legalMoves.add(Position(x, y));
+        }
+      }
+    }
+
+    _availableMoveCache[player] = legalMoves;
+    return legalMoves;
+  }
+
+  /// Returns a new GameBoard instance representing the state this one would
+  /// have after [player] puts a piece at [x],[y]. This method does not check if
+  /// the move was legal, and will blindly trust its input.
+  GameBoard updateForMove(int x, int y, PieceType player) {
+    assert(player != PieceType.empty);
+    final newBoard = GameBoard.fromGameBoard(this);
+
+    if (!isLegalMove(x, y, player)) {
+      return newBoard;
+    }
+
+    newBoard.rows[y][x] = player;
+
+    for (var dx = -1; dx <= 1; dx++) {
+      for (var dy = -1; dy <= 1; dy++) {
+        if (dx == 0 && dy == 0) continue;
+        newBoard._traversePath(x, y, dx, dy, player, true);
+      }
+    }
+
+    return newBoard;
+  }
+
+  /// Returns true if it would be a legal move for [player] to put a piece down
+  /// at [x],[y].
+  bool isLegalMove(int x, int y, PieceType player) {
+    assert(player != PieceType.empty);
+    assert(x >= 0 && x < width);
+    assert(y >= 0 && y < height);
+
+    // It's occupied, yo. No can do.
+    if (rows[y][x] != PieceType.empty) return false;
+
+    // Try each of the eight cardinal directions, looking for a row of opposing
+    // pieces to flip.
+    for (var dx = -1; dx <= 1; dx++) {
+      for (var dy = -1; dy <= 1; dy++) {
+        if (dx == 0 && dy == 0) continue;
+        if (_traversePath(x, y, dx, dy, player, false)) return true;
+      }
+    }
+
+    // No flippable opponent pieces were found in any directions. This is not a
+    // legal move.
+    return false;
+  }
+
+  // This method walks the board in one of eight cardinal directions (determined
+  // by the [dx] and [dy] parameters) beginning at [x],[y], and attempts to
+  // determine if a move at [x],[y] by [player] would result in pieces getting
+  // flipped. If so, the method returns true, otherwise false. If [flip] is set
+  // to true, the pieces are flipped in place to their new colors before the
+  // method returns.
+  bool _traversePath(
+      int x, int y, int dx, int dy, PieceType player, bool flip) {
+    var foundOpponent = false;
+    var curX = x + dx;
+    var curY = y + dy;
+
+    while (curX >= 0 && curX < width && curY >= 0 && curY < height) {
+      if (rows[curY][curX] == PieceType.empty) {
+        // This path led to an empty spot rather than a legal move.
+        return false;
+      } else if (rows[curY][curX] == getOpponent(player)) {
+        // Update flag and keep going, hoping to hit one of player's pieces.
+        foundOpponent = true;
+      } else if (foundOpponent) {
+        // Found opposing pieces and then one of player's afterward. This is
+        // a legal move.
+        if (flip) {
+          // Backtrack, flipping pieces to player's color.
+          while (curX != x || curY != y) {
+            curX -= dx;
+            curY -= dy;
+            rows[curY][curX] = player;
+          }
+        }
+        return true;
+      } else {
+        // Found one of player's pieces, but no opposing pieces.
+        return false;
+      }
+
+      curX += dx;
+      curY += dy;
+    }
+
+    return false;
+  }
+}
+
+const _emptyBoard = [
+  [
+    PieceType.empty,
+    PieceType.empty,
+    PieceType.empty,
+    PieceType.empty,
+    PieceType.empty,
+    PieceType.empty,
+    PieceType.empty,
+    PieceType.empty,
+  ],
+  [
+    PieceType.empty,
+    PieceType.empty,
+    PieceType.empty,
+    PieceType.empty,
+    PieceType.empty,
+    PieceType.empty,
+    PieceType.empty,
+    PieceType.empty,
+  ],
+  [
+    PieceType.empty,
+    PieceType.empty,
+    PieceType.empty,
+    PieceType.empty,
+    PieceType.empty,
+    PieceType.empty,
+    PieceType.empty,
+    PieceType.empty,
+  ],
+  [
+    PieceType.empty,
+    PieceType.empty,
+    PieceType.empty,
+    PieceType.black,
+    PieceType.white,
+    PieceType.empty,
+    PieceType.empty,
+    PieceType.empty,
+  ],
+  [
+    PieceType.empty,
+    PieceType.empty,
+    PieceType.empty,
+    PieceType.white,
+    PieceType.black,
+    PieceType.empty,
+    PieceType.empty,
+    PieceType.empty,
+  ],
+  [
+    PieceType.empty,
+    PieceType.empty,
+    PieceType.empty,
+    PieceType.empty,
+    PieceType.empty,
+    PieceType.empty,
+    PieceType.empty,
+    PieceType.empty,
+  ],
+  [
+    PieceType.empty,
+    PieceType.empty,
+    PieceType.empty,
+    PieceType.empty,
+    PieceType.empty,
+    PieceType.empty,
+    PieceType.empty,
+    PieceType.empty,
+  ],
+  [
+    PieceType.empty,
+    PieceType.empty,
+    PieceType.empty,
+    PieceType.empty,
+    PieceType.empty,
+    PieceType.empty,
+    PieceType.empty,
+    PieceType.empty,
+  ],
+];
diff --git a/lib/game_board_scorer.dart b/lib/game_board_scorer.dart
new file mode 100644
index 0000000..ac314aa
--- /dev/null
+++ b/lib/game_board_scorer.dart
@@ -0,0 +1,64 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+import 'game_board.dart';
+
+class GameBoardScorer {
+  // Values for each position on the board.
+  static const _positionValues = [
+    [10000, -1000, 100, 100, 100, 100, -1000, 10000],
+    [-1000, -1000, 1, 1, 1, 1, -1000, -1000],
+    [100, 1, 50, 50, 50, 50, 1, 100],
+    [100, 1, 50, 1, 1, 50, 1, 100],
+    [100, 1, 50, 1, 1, 50, 1, 100],
+    [100, 1, 50, 50, 50, 50, 1, 100],
+    [-1000, -1000, 1, 1, 1, 1, -1000, -1000],
+    [10000, -1000, 100, 100, 100, 100, -1000, 10000],
+  ];
+
+  /// Maximum and minimum values for scores, which are used in the minimax
+  /// algorithm in [MoveFinder].
+  static const maxScore = 1000 * 1000 * 1000;
+  static const minScore = -1 * maxScore;
+
+  final GameBoard board;
+
+  GameBoardScorer(this.board);
+
+  /// Returns the score of the board, as determined by what pieces are in place,
+  /// and how valuable their locations are. This is a very simple scoring
+  /// heuristic, but it's surprisingly effective.
+  int getScore(PieceType player) {
+    assert(player != PieceType.empty);
+    var opponent = getOpponent(player);
+    var score = 0;
+
+    if (board.getMovesForPlayer(PieceType.black).isEmpty &&
+        board.getMovesForPlayer(PieceType.white).isEmpty) {
+      // Game is over.
+      var playerCount = board.getPieceCount(player);
+      var opponentCount = board.getPieceCount(getOpponent(player));
+
+      if (playerCount > opponentCount) {
+        return maxScore;
+      } else if (playerCount < opponentCount) {
+        return minScore;
+      } else {
+        return 0;
+      }
+    }
+
+    for (var y = 0; y < GameBoard.height; y++) {
+      for (var x = 0; x < GameBoard.width; x++) {
+        if (board.getPieceAtLocation(x, y) == player) {
+          score += _positionValues[y][x];
+        } else if (board.getPieceAtLocation(x, y) == opponent) {
+          score -= _positionValues[y][x];
+        }
+      }
+    }
+
+    return score;
+  }
+}
diff --git a/lib/game_model.dart b/lib/game_model.dart
new file mode 100644
index 0000000..bb95262
--- /dev/null
+++ b/lib/game_model.dart
@@ -0,0 +1,58 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+import 'game_board.dart';
+
+/// A model representing the state of a game of reversi. It's a board and the
+/// player who's next to go, essentially.
+class GameModel {
+  late final GameBoard board;
+  final PieceType player;
+  final String _skin = 'default';
+
+  GameModel({
+    required this.board,
+    this.player = PieceType.black,
+  });
+
+  String get skin => _skin;
+
+  int get blackScore => board.getPieceCount(PieceType.black);
+
+  int get whiteScore => board.getPieceCount(PieceType.white);
+
+  bool get gameIsOver => (board.getMovesForPlayer(player).isEmpty);
+
+  String get gameResultString {
+    if (blackScore > whiteScore) {
+      return 'Black wins.';
+    } else if (whiteScore > blackScore) {
+      return 'White wins.';
+    } else {
+      return 'Tie.';
+    }
+  }
+
+  /// Attempts to create a new instance of GameModel using the coordinates
+  /// provided as the current player's move. If successful, a new GameModel is
+  /// returned. If unsuccessful, null is returned.
+  GameModel updateForMove(int x, int y) {
+    if (!board.isLegalMove(x, y, player)) {
+      return null!;
+    }
+
+    final newBoard = board.updateForMove(x, y, player);
+    PieceType nextPlayer;
+
+    if (newBoard.getMovesForPlayer(getOpponent(player)).isNotEmpty) {
+      nextPlayer = getOpponent(player);
+    } else if (newBoard.getMovesForPlayer(player).isNotEmpty) {
+      nextPlayer = player;
+    } else {
+      nextPlayer = PieceType.empty;
+    }
+
+    return GameModel(board: newBoard, player: nextPlayer);
+  }
+}
diff --git a/lib/main.dart b/lib/main.dart
index dd1afff..75b66de 100644
--- a/lib/main.dart
+++ b/lib/main.dart
@@ -1,34 +1,324 @@
-import 'package:flutter/material.dart';
-import 'package:flutter/services.dart';
-import 'package:provider/provider.dart';
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
 
-import 'provider/data.dart';
-import 'screens/home.dart';
+import 'dart:async';
 
+import 'package:async/async.dart';
+import 'package:flutter/services.dart' show SystemChrome, DeviceOrientation;
+import 'package:flutter/widgets.dart';
+
+import 'game_board.dart';
+import 'game_model.dart';
+import 'move_finder.dart';
+import 'styling.dart';
+import 'thinking_indicator.dart';
+
+/// Main function for the app. Turns off the system overlays and locks portrait
+/// orientation for a more game-like UI, and then runs the [Widget] tree.
 void main() {
   WidgetsFlutterBinding.ensureInitialized();
-  SystemChrome.setPreferredOrientations([DeviceOrientation.portraitUp])
-      .then((value) => runApp(MyApp()));
+
+  SystemChrome.setEnabledSystemUIOverlays([]);
+  SystemChrome.setPreferredOrientations([
+    DeviceOrientation.portraitUp,
+    DeviceOrientation.portraitDown,
+  ]);
+
+  runApp(FlutterFlipApp());
 }
 
-class MyApp extends StatelessWidget {
+/// The App class. Unlike many Flutter apps, this one does not use Material
+/// widgets, so there's no [MaterialApp] or [Theme] objects.
+class FlutterFlipApp extends StatelessWidget {
+  @override
+  Widget build(BuildContext context) {
+    return WidgetsApp(
+      color: Color(0xffffffff), // Mandatory background color.
+      onGenerateRoute: (settings) {
+        return PageRouteBuilder<dynamic>(
+          settings: settings,
+          pageBuilder: (context, animation, secondaryAnimation) => GameScreen(),
+        );
+      },
+    );
+  }
+}
+
+/// The [GameScreen] Widget represents the entire game
+/// display, from scores to board state and everything in between.
+class GameScreen extends StatefulWidget {
+  @override
+  State createState() => _GameScreenState();
+}
+
+/// State class for [GameScreen].
+///
+/// The game is modeled as a [Stream] of immutable instances of [GameModel].
+/// Each move by the player or CPU results in a new [GameModel], which is
+/// sent downstream. [GameScreen] uses a [StreamBuilder] wired up to that stream
+/// of models to build out its [Widget] tree.
+class _GameScreenState extends State<GameScreen> {
+  final StreamController<GameModel> _userMovesController =
+      StreamController<GameModel>();
+  final StreamController<GameModel> _restartController =
+      StreamController<GameModel>();
+  Stream<GameModel>? _modelStream;
+
+  _GameScreenState() {
+    // Below is the combination of streams that controls the flow of the game.
+    // There are two streams of models produced by player interaction (either by
+    // restarting the game, which produces a brand new game model and sends it
+    // downstream, or tapping on one of the board locations to play a piece, and
+    // which creates a new board model with the result of the move and sends it
+    // downstream. The StreamGroup combines these into a single stream, then
+    // does a little trick with asyncExpand.
+    //
+    // The function used in asyncExpand checks to see if it's the CPU's turn
+    // (white), and if so creates a [MoveFinder] to look for the best move. It
+    // awaits the calculation, and then creates a new [GameModel] with the
+    // result of that move and sends it downstream by yielding it. If it's still
+    // the CPU's turn after making that move (which can happen in reversi), this
+    // is repeated.
+    //
+    // The final stream of models that exits the asyncExpand call is a
+    // combination of "new game" models, models with the results of player
+    // moves, and models with the results of CPU moves. These are fed into the
+    // StreamBuilder in [build], and used to create the widgets that comprise
+    // the game's display.
+    _modelStream = StreamGroup.merge([
+      _userMovesController.stream,
+      _restartController.stream,
+    ]).asyncExpand((model) async* {
+      yield model;
+
+      var newModel = model;
+
+      while (newModel.player == PieceType.white) {
+        final finder = MoveFinder(newModel.board);
+        final move = await finder.findNextMove(newModel.player, 5);
+        if (move != null) {
+          newModel = newModel.updateForMove(move.x, move.y);
+          yield newModel;
+        }
+      }
+    });
+  }
+
+  // Thou shalt tidy up thy stream controllers.
+  @override
+  void dispose() {
+    _userMovesController.close();
+    _restartController.close();
+    super.dispose();
+  }
+
+  /// The build method mostly just sets up the StreamBuilder and leaves the
+  /// details to _buildWidgets.
   @override
   Widget build(BuildContext context) {
-    return ChangeNotifierProvider(
-      create: (BuildContext context) => Data(),
-      child: Consumer<Data>(builder: (context, data, child) {
-        return MaterialApp(
-          debugShowCheckedModeBanner: false,
-          theme: ThemeData(
-            primaryColor: Colors.blue,
-            visualDensity: VisualDensity.adaptivePlatformDensity,
+    return StreamBuilder<GameModel>(
+      stream: _modelStream,
+      builder: (context, snapshot) {
+        return _buildWidgets(
+          context,
+          snapshot.hasData ? snapshot.data! : GameModel(board: GameBoard()),
+        );
+      },
+    );
+  }
+
+  // Called when the user taps on the game's board display. If it's the player's
+  // turn, this method will attempt to make the move, creating a new GameModel
+  // in the process.
+  void _attemptUserMove(GameModel model, int x, int y) {
+    if (model.player == PieceType.black &&
+        model.board.isLegalMove(x, y, model.player)) {
+      _userMovesController.add(model.updateForMove(x, y));
+    }
+  }
+
+  Widget _buildScoreBox(PieceType player, GameModel model) {
+    var assetImageCode = player == PieceType.black ? 'black' : 'white';
+    String assetImageName = 'assets/skins/' + model.skin + '_tile_' + assetImageCode + '.png';
+
+    var scoreText = player == PieceType.black
+        ? '${model.blackScore}'
+        : '${model.whiteScore}';
+
+    return Container(
+      padding: const EdgeInsets.symmetric(
+        vertical: 3.0,
+        horizontal: 30.0,
+      ),
+      decoration: (model.player == player)
+          ? Styling.activePlayerIndicator
+          : Styling.inactivePlayerIndicator,
+      child: Row(
+        children: <Widget>[
+          SizedBox(
+            width: 30.0,
+            height: 30.0,
+            child: Image(
+              image: AssetImage(assetImageName),
+              fit: BoxFit.fill,
+            ),
           ),
-          home: Home(),
-          routes: {
-            Home.id: (context) => Home(),
-          },
+          SizedBox(
+            width: 10.0,
+          ),
+          Text(
+            scoreText,
+            textAlign: TextAlign.center,
+            style: TextStyle(
+              fontSize: 50.0,
+              color: Color(0xff000000),
+            ),
+          ),
+        ],
+      ),
+    );
+  }
+
+  Widget _buildScoreBoxes(GameModel model) {
+    return Row(
+      mainAxisAlignment: MainAxisAlignment.center,
+      children: [
+        Spacer(flex: 1),
+        _buildScoreBox(PieceType.black, model),
+        Spacer(flex: 4),
+        _buildScoreBox(PieceType.white, model),
+        Spacer(flex: 1),
+      ],
+    );
+  }
+
+  Table _buildGameBoardDisplay(BuildContext context, GameModel model) {
+    final rows = <TableRow>[];
+
+    for (var y = 0; y < GameBoard.height; y++) {
+      final cells = <Column>[];
+
+      for (var x = 0; x < GameBoard.width; x++) {
+        PieceType pieceType = model.board.getPieceAtLocation(x, y);
+        String? assetImageCode = Styling.assetImageCodes[pieceType];
+        String assetImageName = 'assets/skins/' + model.skin + '_tile_' + (assetImageCode != null ? assetImageCode : 'empty') + '.png';
+
+        Column cell = Column(
+          children: [
+            Container(
+              decoration: Styling.boardCellDecoration,
+              child: SizedBox(
+                child: GestureDetector(
+                  child: AnimatedSwitcher(
+                    duration: const Duration(milliseconds: 500),
+                    transitionBuilder: (Widget child, Animation<double> animation) {
+                      return ScaleTransition(child: child, scale: animation);
+                    },
+                    child: Image(
+                      image: AssetImage(assetImageName),
+                      fit: BoxFit.fill,
+                      key: ValueKey<int>(pieceType == PieceType.empty ? 0 : (pieceType == PieceType.black ? 1 : 2)),
+                    ),
+                  ),
+                  onTap: () {
+                    _attemptUserMove(model, x, y);
+                  },
+                ),
+              ),
+            )
+          ]
         );
-      }),
+
+        cells.add(cell);
+      }
+
+      rows.add(TableRow(children: cells));
+    }
+
+    return Table(
+      defaultColumnWidth: IntrinsicColumnWidth(),
+      children: rows
+    );
+  }
+
+  Widget _buildThinkingIndicator(GameModel model) {
+    return ThinkingIndicator(
+      color: Styling.thinkingColor,
+      height: Styling.thinkingSize,
+      visible: model.player == PieceType.white,
+    );
+  }
+
+  Widget _buildRestartGameWidget() {
+    return Container(
+      padding: const EdgeInsets.symmetric(
+        vertical: 5.0,
+        horizontal: 15.0,
+      ),
+      child: Image(
+        image: AssetImage('assets/icons/button_restart.png'),
+        fit: BoxFit.fill,
+      ),
+    );
+  }
+
+  Widget _buildEndGameWidget(GameModel model) {
+    Image decorationImage = Image(
+      image: AssetImage(
+        model.gameResultString == 'black'
+          ? 'assets/icons/game_win.png'
+          : 'assets/icons/empty.png'
+      ),
+      fit: BoxFit.fill,
+    );
+
+    return Container(
+      margin: EdgeInsets.all(2),
+      padding: EdgeInsets.all(2),
+
+      child: Table(
+        defaultColumnWidth: IntrinsicColumnWidth(),
+        children: [
+          TableRow(
+            children: [
+              Column(children: [ decorationImage ]),
+              Column(children: [
+                GestureDetector(
+                  onTap: () {
+                    _restartController.add(
+                      GameModel(board: GameBoard()),
+                    );
+                  },
+                  child: _buildRestartGameWidget(),
+                )
+              ]),
+              Column(children: [ decorationImage ]),
+            ],
+          ),
+        ]
+      )
+    );
+  }
+
+  // Builds out the Widget tree using the most recent GameModel from the stream.
+  Widget _buildWidgets(BuildContext context, GameModel model) {
+    return Container(
+      padding: EdgeInsets.only(top: 30.0, left: 15.0, right: 15.0),
+      decoration: Styling.mainWidgetDecoration,
+      child: SafeArea(
+        child: Column(
+          children: [
+            _buildScoreBoxes(model),
+            SizedBox(height: 10),
+            _buildGameBoardDisplay(context, model),
+            SizedBox(height: 10),
+            _buildThinkingIndicator(model),
+            SizedBox(height: 30),
+            if (model.gameIsOver) _buildEndGameWidget(model),
+          ],
+        ),
+      ),
     );
   }
 }
diff --git a/lib/move_finder.dart b/lib/move_finder.dart
new file mode 100644
index 0000000..32a37f9
--- /dev/null
+++ b/lib/move_finder.dart
@@ -0,0 +1,116 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+import 'dart:async';
+
+import 'package:flutter/foundation.dart';
+
+import 'game_board.dart';
+import 'game_board_scorer.dart';
+
+class MoveSearchArgs {
+  MoveSearchArgs(
+      {required this.board, required this.player, required this.numPlies});
+
+  final GameBoard board;
+  final PieceType player;
+  final int numPlies;
+}
+
+/// A move and its score. Used by the minimax algorithm.
+class ScoredMove {
+  final int score;
+  final Position move;
+
+  const ScoredMove(this.score, this.move);
+}
+
+// The [compute] function requires a top-level method as its first argument.
+// This is that method for [MoveFinder].
+Position? _findNextMove(MoveSearchArgs args) {
+  final bestMove = _performSearchPly(
+      args.board, args.player, args.player, args.numPlies - 1);
+  return bestMove?.move;
+}
+
+// This is a recursive implementation of minimax, an algorithm so old it has
+// its own Wikipedia page: https://wikipedia.org/wiki/Minimax.
+ScoredMove? _performSearchPly(
+  GameBoard board,
+  PieceType scoringPlayer,
+  PieceType player,
+  int pliesRemaining,
+) {
+  final availableMoves = board.getMovesForPlayer(player);
+
+  if (availableMoves.isEmpty) {
+    return null;
+  }
+
+  var score = (scoringPlayer == player)
+      ? GameBoardScorer.minScore
+      : GameBoardScorer.maxScore;
+  ScoredMove? bestMove;
+
+  for (var i = 0; i < availableMoves.length; i++) {
+    final newBoard =
+        board.updateForMove(availableMoves[i].x, availableMoves[i].y, player);
+    if (pliesRemaining > 0 &&
+        newBoard.getMovesForPlayer(getOpponent(player)).isNotEmpty) {
+      // Opponent has next turn.
+      score = _performSearchPly(
+            newBoard,
+            scoringPlayer,
+            getOpponent(player),
+            pliesRemaining - 1,
+          )?.score ??
+          0;
+    } else if (pliesRemaining > 0 &&
+        newBoard.getMovesForPlayer(player).isNotEmpty) {
+      // Opponent has no moves; player gets another turn.
+      score = _performSearchPly(
+            newBoard,
+            scoringPlayer,
+            player,
+            pliesRemaining - 1,
+          )?.score ??
+          0;
+    } else {
+      // Game is over or the search has reached maximum depth.
+      score = GameBoardScorer(newBoard).getScore(scoringPlayer);
+    }
+
+    if (bestMove == null ||
+        (score > bestMove.score && scoringPlayer == player) ||
+        (score < bestMove.score && scoringPlayer != player)) {
+      bestMove =
+          ScoredMove(score, Position(availableMoves[i].x, availableMoves[i].y));
+    }
+  }
+
+  return bestMove;
+}
+
+/// The [MoveFinder] class exists to provide its [findNextMove] method, which
+/// uses the minimax algorithm to look for the best available move on
+/// [initialBoard] a [GameBoardScorer] to provide the heuristic.
+class MoveFinder {
+  final GameBoard initialBoard;
+
+  MoveFinder(this.initialBoard);
+
+  /// Searches the tree of possible moves on [initialBoard] to a depth of
+  /// [numPlies], looking for the best possible move for [player]. Because the
+  /// actual work is done in an isolate, a [Future] is used as the return value.
+  Future<Position?> findNextMove(PieceType player, int numPlies) {
+    return compute(
+      _findNextMove,
+      MoveSearchArgs(
+        board: initialBoard,
+        player: player,
+        numPlies: numPlies,
+      ),
+    );
+  }
+}
diff --git a/lib/provider/data.dart b/lib/provider/data.dart
deleted file mode 100644
index ee24df3..0000000
--- a/lib/provider/data.dart
+++ /dev/null
@@ -1,75 +0,0 @@
-import 'package:flutter/foundation.dart';
-
-class Data extends ChangeNotifier {
-
-  // Configuration available values
-  List _availableDifficultyLevels = ['easy', 'medium', 'hard'];
-
-  List get availableDifficultyLevels => _availableDifficultyLevels;
-
-  // Application default configuration
-  String _level = 'medium';
-  String _size = '8x8';
-  String _skin = 'default';
-
-  // Game data
-  bool _gameRunning = false;
-  int _sizeVertical = null;
-  int _sizeHorizontal = null;
-  List _cells = [];
-
-  String get level => _level;
-  void updateLevel(String level) {
-    _level = level;
-    notifyListeners();
-  }
-
-  String get size => _size;
-  int get sizeVertical => _sizeVertical;
-  int get sizeHorizontal => _sizeHorizontal;
-  void updateSize(String size) {
-    _size = size;
-    _sizeHorizontal = int.parse(_size.split('x')[0]);
-    _sizeVertical = int.parse(_size.split('x')[1]);
-    notifyListeners();
-  }
-
-  String get skin => _skin;
-  void updateSkin(String skin) {
-    _skin = skin;
-    notifyListeners();
-  }
-
-  getParameterValue(String parameterCode) {
-    switch(parameterCode) {
-      case 'difficulty': { return _level; }
-      break;
-    }
-  }
-
-  List getParameterAvailableValues(String parameterCode) {
-    switch(parameterCode) {
-      case 'difficulty': { return _availableDifficultyLevels; }
-      break;
-    }
-  }
-
-  setParameterValue(String parameterCode, String parameterValue) {
-    switch(parameterCode) {
-      case 'difficulty': { updateLevel(parameterValue); }
-      break;
-    }
-  }
-
-  List get cells => _cells;
-  void updateCells(List cells) {
-    _cells = cells;
-    notifyListeners();
-  }
-
-  bool get gameRunning => _gameRunning;
-  void updateGameRunning(bool gameRunning) {
-    _gameRunning = gameRunning;
-    notifyListeners();
-  }
-}
diff --git a/lib/screens/home.dart b/lib/screens/home.dart
deleted file mode 100644
index ba85d37..0000000
--- a/lib/screens/home.dart
+++ /dev/null
@@ -1,32 +0,0 @@
-import 'package:flutter/material.dart';
-import 'package:provider/provider.dart';
-
-import '../provider/data.dart';
-
-class Home extends StatelessWidget {
-  static const String id = 'home';
-
-  @override
-  Widget build(BuildContext context) {
-    Data myProvider = Provider.of<Data>(context);
-
-    return Scaffold(
-      appBar: AppBar(
-        title: new Text('Reversi'),
-
-        actions: [
-        ],
-        
-        leading: IconButton(
-          icon: Image.asset('assets/icons/application.png'),
-          onPressed: () { },
-        ),
-      ),
-      body: SafeArea(
-        child: Center(
-          child: Text('🎮')
-        ),
-      )
-    );
-  }
-}
diff --git a/lib/styling.dart b/lib/styling.dart
new file mode 100644
index 0000000..1ece8b8
--- /dev/null
+++ b/lib/styling.dart
@@ -0,0 +1,76 @@
+import 'package:flutter/widgets.dart';
+
+import 'game_board.dart';
+
+abstract class Styling {
+  // **** GRADIENTS AND COLORS ****
+
+  static const Map<PieceType, String> assetImageCodes = {
+    PieceType.black: 'black',
+    PieceType.white: 'white',
+    PieceType.empty: 'empty',
+  };
+
+  static const BorderSide boardCellBorderSide = BorderSide(
+    color: Color(0xff108010),
+    width: 1.0,
+  );
+
+  static const BoxDecoration boardCellDecoration = BoxDecoration(
+    color: Color(0xff50bb50),
+    border: Border(
+      bottom: boardCellBorderSide,
+      top: boardCellBorderSide,
+      left: boardCellBorderSide,
+      right: boardCellBorderSide,
+    ),
+  );
+
+  static const BoxDecoration mainWidgetDecoration = BoxDecoration(
+    color: Color(0xffffffff)
+  );
+
+  static const thinkingColor = Color(0xff2196f3);
+
+  // **** ANIMATIONS ****
+
+  static const Duration thinkingFadeDuration = Duration(milliseconds: 500);
+
+  static const pieceFlipDuration = Duration(milliseconds: 300);
+
+  // **** SIZES ****
+
+  static const thinkingSize = 10.0;
+
+  // **** BOXES ****
+
+  static const BorderSide activePlayerIndicatorBorder = BorderSide(
+    color: Color(0xff2196f3),
+    width: 10.0,
+  );
+
+  static const BorderSide inactivePlayerIndicatorBorder = BorderSide(
+    color: Color(0x00000000),
+    width: 10.0,
+  );
+
+  static const activePlayerIndicator = BoxDecoration(
+    borderRadius: const BorderRadius.all(const Radius.circular(10.0)),
+    border: Border(
+      bottom: activePlayerIndicatorBorder,
+      top: activePlayerIndicatorBorder,
+      left: activePlayerIndicatorBorder,
+      right: activePlayerIndicatorBorder,
+    ),
+  );
+
+  static const inactivePlayerIndicator = BoxDecoration(
+    borderRadius: const BorderRadius.all(const Radius.circular(10.0)),
+    border: Border(
+      bottom: inactivePlayerIndicatorBorder,
+      top: inactivePlayerIndicatorBorder,
+      left: inactivePlayerIndicatorBorder,
+      right: inactivePlayerIndicatorBorder,
+    ),
+  );
+}
diff --git a/lib/thinking_indicator.dart b/lib/thinking_indicator.dart
new file mode 100644
index 0000000..ad34780
--- /dev/null
+++ b/lib/thinking_indicator.dart
@@ -0,0 +1,143 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+import 'package:flutter/widgets.dart';
+import 'styling.dart';
+
+/// This is a self-animated progress spinner, only instead of spinning it
+/// moves five little circles in a horizontal arrangement.
+class ThinkingIndicator extends ImplicitlyAnimatedWidget {
+  final Color color;
+  final double height;
+  final bool visible;
+
+  ThinkingIndicator({
+    this.color = const Color(0xffffffff),
+    this.height = 10.0,
+    this.visible = true,
+    Key? key,
+  }) : super(
+          duration: Styling.thinkingFadeDuration,
+          key: key,
+        );
+
+  @override
+  ImplicitlyAnimatedWidgetState createState() => _ThinkingIndicatorState();
+}
+
+class _ThinkingIndicatorState
+    extends AnimatedWidgetBaseState<ThinkingIndicator> {
+  Tween<double>? _opacityTween;
+
+  @override
+  void dispose() {
+    super.dispose();
+  }
+
+  @override
+  Widget build(BuildContext context) {
+    return Center(
+      child: SizedBox(
+        height: widget.height,
+        child: Opacity(
+          opacity: _opacityTween!.evaluate(animation!),
+          child: _opacityTween!.evaluate(animation!) != 0
+              ? _AnimatedCircles(
+                  color: widget.color,
+                  height: widget.height,
+                )
+              : null,
+        ),
+      ),
+    );
+  }
+
+  @override
+  void forEachTween(visitor) {
+    _opacityTween = visitor(
+      _opacityTween,
+      widget.visible ? 1.0 : 0.0,
+      (dynamic value) => Tween<double>(begin: value as double),
+    ) as Tween<double>?;
+  }
+}
+
+class _AnimatedCircles extends StatefulWidget {
+  final Color color;
+  final double height;
+
+  const _AnimatedCircles({
+    required this.color,
+    required this.height,
+    Key? key,
+  }) : super(key: key);
+
+  @override
+  _AnimatedCirclesState createState() => _AnimatedCirclesState();
+}
+
+class _AnimatedCirclesState extends State<_AnimatedCircles>
+    with SingleTickerProviderStateMixin {
+  late Animation<double> _thinkingAnimation;
+  late AnimationController _thinkingController;
+
+  @override
+  void initState() {
+    super.initState();
+    _thinkingController = AnimationController(
+        duration: const Duration(milliseconds: 500), vsync: this)
+      ..addStatusListener((status) {
+        // This bit ensures that the animation reverses course rather than
+        // stopping.
+        if (status == AnimationStatus.completed) _thinkingController.reverse();
+        if (status == AnimationStatus.dismissed) _thinkingController.forward();
+      });
+    _thinkingAnimation = Tween(begin: 0.0, end: widget.height).animate(
+        CurvedAnimation(parent: _thinkingController, curve: Curves.easeOut));
+    _thinkingController.forward();
+  }
+
+  @override
+  void dispose() {
+    _thinkingController.dispose();
+    super.dispose();
+  }
+
+  Widget _buildCircle() {
+    return Container(
+      width: widget.height,
+      height: widget.height,
+      decoration: BoxDecoration(
+        border: Border.all(
+          color: widget.color,
+          width: 2.0,
+        ),
+        borderRadius: BorderRadius.all(const Radius.circular(5.0)),
+      ),
+    );
+  }
+
+  @override
+  Widget build(BuildContext context) {
+    return AnimatedBuilder(
+      animation: _thinkingAnimation,
+      builder: (context, child) {
+        return Row(
+          mainAxisSize: MainAxisSize.min,
+          children: [
+            _buildCircle(),
+            SizedBox(width: _thinkingAnimation.value),
+            _buildCircle(),
+            SizedBox(width: _thinkingAnimation.value),
+            _buildCircle(),
+            SizedBox(width: _thinkingAnimation.value),
+            _buildCircle(),
+            SizedBox(width: _thinkingAnimation.value),
+            _buildCircle(),
+          ],
+        );
+      },
+    );
+  }
+}
diff --git a/pubspec.lock b/pubspec.lock
index b6eca0d..9bed096 100644
--- a/pubspec.lock
+++ b/pubspec.lock
@@ -7,7 +7,7 @@ packages:
       name: async
       url: "https://pub.dartlang.org"
     source: hosted
-    version: "2.7.0"
+    version: "2.8.1"
   boolean_selector:
     dependency: transitive
     description:
@@ -50,6 +50,20 @@ packages:
       url: "https://pub.dartlang.org"
     source: hosted
     version: "1.2.0"
+  ffi:
+    dependency: transitive
+    description:
+      name: ffi
+      url: "https://pub.dartlang.org"
+    source: hosted
+    version: "1.1.2"
+  file:
+    dependency: transitive
+    description:
+      name: file
+      url: "https://pub.dartlang.org"
+    source: hosted
+    version: "6.1.2"
   flutter:
     dependency: "direct main"
     description: flutter
@@ -60,6 +74,18 @@ packages:
     description: flutter
     source: sdk
     version: "0.0.0"
+  flutter_web_plugins:
+    dependency: transitive
+    description: flutter
+    source: sdk
+    version: "0.0.0"
+  js:
+    dependency: transitive
+    description:
+      name: js
+      url: "https://pub.dartlang.org"
+    source: hosted
+    version: "0.6.3"
   matcher:
     dependency: transitive
     description:
@@ -88,6 +114,48 @@ packages:
       url: "https://pub.dartlang.org"
     source: hosted
     version: "1.8.0"
+  path_provider_linux:
+    dependency: transitive
+    description:
+      name: path_provider_linux
+      url: "https://pub.dartlang.org"
+    source: hosted
+    version: "2.0.2"
+  path_provider_platform_interface:
+    dependency: transitive
+    description:
+      name: path_provider_platform_interface
+      url: "https://pub.dartlang.org"
+    source: hosted
+    version: "2.0.1"
+  path_provider_windows:
+    dependency: transitive
+    description:
+      name: path_provider_windows
+      url: "https://pub.dartlang.org"
+    source: hosted
+    version: "2.0.3"
+  platform:
+    dependency: transitive
+    description:
+      name: platform
+      url: "https://pub.dartlang.org"
+    source: hosted
+    version: "3.0.2"
+  plugin_platform_interface:
+    dependency: transitive
+    description:
+      name: plugin_platform_interface
+      url: "https://pub.dartlang.org"
+    source: hosted
+    version: "2.0.1"
+  process:
+    dependency: transitive
+    description:
+      name: process
+      url: "https://pub.dartlang.org"
+    source: hosted
+    version: "4.2.3"
   provider:
     dependency: "direct main"
     description:
@@ -95,6 +163,48 @@ packages:
       url: "https://pub.dartlang.org"
     source: hosted
     version: "5.0.0"
+  shared_preferences:
+    dependency: "direct main"
+    description:
+      name: shared_preferences
+      url: "https://pub.dartlang.org"
+    source: hosted
+    version: "2.0.6"
+  shared_preferences_linux:
+    dependency: transitive
+    description:
+      name: shared_preferences_linux
+      url: "https://pub.dartlang.org"
+    source: hosted
+    version: "2.0.2"
+  shared_preferences_macos:
+    dependency: transitive
+    description:
+      name: shared_preferences_macos
+      url: "https://pub.dartlang.org"
+    source: hosted
+    version: "2.0.2"
+  shared_preferences_platform_interface:
+    dependency: transitive
+    description:
+      name: shared_preferences_platform_interface
+      url: "https://pub.dartlang.org"
+    source: hosted
+    version: "2.0.0"
+  shared_preferences_web:
+    dependency: transitive
+    description:
+      name: shared_preferences_web
+      url: "https://pub.dartlang.org"
+    source: hosted
+    version: "2.0.1"
+  shared_preferences_windows:
+    dependency: transitive
+    description:
+      name: shared_preferences_windows
+      url: "https://pub.dartlang.org"
+    source: hosted
+    version: "2.0.2"
   sky_engine:
     dependency: transitive
     description: flutter
@@ -141,7 +251,7 @@ packages:
       name: test_api
       url: "https://pub.dartlang.org"
     source: hosted
-    version: "0.4.1"
+    version: "0.4.2"
   typed_data:
     dependency: transitive
     description:
@@ -156,6 +266,20 @@ packages:
       url: "https://pub.dartlang.org"
     source: hosted
     version: "2.1.0"
+  win32:
+    dependency: transitive
+    description:
+      name: win32
+      url: "https://pub.dartlang.org"
+    source: hosted
+    version: "2.2.5"
+  xdg_directories:
+    dependency: transitive
+    description:
+      name: xdg_directories
+      url: "https://pub.dartlang.org"
+    source: hosted
+    version: "0.2.0"
 sdks:
-  dart: ">=2.12.0 <3.0.0"
-  flutter: ">=1.16.0"
+  dart: ">=2.13.0 <3.0.0"
+  flutter: ">=2.0.0"
diff --git a/pubspec.yaml b/pubspec.yaml
index 1bc5838..51faa3b 100644
--- a/pubspec.yaml
+++ b/pubspec.yaml
@@ -1,15 +1,16 @@
-name: reversi
+name: simpler_reversi
 description: A reversi game application.
 publish_to: 'none'
 version: 1.0.0+1
 
 environment:
-  sdk: ">=2.7.0 <3.0.0"
+  sdk: ">=2.12.0 <3.0.0"
 
 dependencies:
   flutter:
     sdk: flutter
   provider: ^5.0.0
+  shared_preferences: ^2.0.6
 
 dev_dependencies:
   flutter_test:
-- 
GitLab