Add Ice Age Chess
authorBenjamin Auder <benjamin.auder@somewhere>
Tue, 26 Jan 2021 22:11:44 +0000 (23:11 +0100)
committerBenjamin Auder <benjamin.auder@somewhere>
Tue, 26 Jan 2021 22:11:44 +0000 (23:11 +0100)
15 files changed:
client/public/images/pieces/Iceage/SOURCE [new file with mode: 0644]
client/public/images/pieces/Iceage/icecube.svg [new file with mode: 0644]
client/src/base_rules.js
client/src/translations/en.js
client/src/translations/es.js
client/src/translations/fr.js
client/src/translations/rules/Iceage/en.pug [new file with mode: 0644]
client/src/translations/rules/Iceage/es.pug [new file with mode: 0644]
client/src/translations/rules/Iceage/fr.pug [new file with mode: 0644]
client/src/translations/variants/en.pug
client/src/translations/variants/es.pug
client/src/translations/variants/fr.pug
client/src/variants/Iceage.js [new file with mode: 0644]
client/src/views/Game.vue
server/db/populate.sql

diff --git a/client/public/images/pieces/Iceage/SOURCE b/client/public/images/pieces/Iceage/SOURCE
new file mode 100644 (file)
index 0000000..764be1f
--- /dev/null
@@ -0,0 +1 @@
+https://all-free-download.com/free-vector/download/ice-cube-clip-art_23220.html
diff --git a/client/public/images/pieces/Iceage/icecube.svg b/client/public/images/pieces/Iceage/icecube.svg
new file mode 100644 (file)
index 0000000..b3de8f9
--- /dev/null
@@ -0,0 +1,163 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<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:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+   version="1.1"
+   width="223.17236"
+   height="207.59424"
+   viewBox="0 0 223.17236 207.59424"
+   overflow="visible"
+   enable-background="new 0 0 223.17236 207.59424"
+   xml:space="preserve"
+   id="svg56"
+   sodipodi:docname="cc.svg"
+   inkscape:version="1.0.1 (3bc2e813f5, 2020-09-07, custom)"><metadata
+   id="metadata62"><rdf:RDF><cc:Work
+       rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type
+         rdf:resource="http://purl.org/dc/dcmitype/StillImage" /></cc:Work></rdf:RDF></metadata><defs
+   id="defs60" /><sodipodi:namedview
+   pagecolor="#ffffff"
+   bordercolor="#666666"
+   borderopacity="1"
+   objecttolerance="10"
+   gridtolerance="10"
+   guidetolerance="10"
+   inkscape:pageopacity="0"
+   inkscape:pageshadow="2"
+   inkscape:window-width="1920"
+   inkscape:window-height="1060"
+   id="namedview58"
+   showgrid="false"
+   inkscape:zoom="4.2534899"
+   inkscape:cx="111.58618"
+   inkscape:cy="101.79589"
+   inkscape:window-x="0"
+   inkscape:window-y="20"
+   inkscape:window-maximized="0"
+   inkscape:current-layer="svg56" />
+<g
+   id="Layer_1"
+   transform="matrix(0.9,0,0,0.84995245,14.967333,14.540503)">
+       <path
+   fill="#30eefb"
+   d="m 120.11377,0 87.46777,26.18115 c 0,0 4.06348,110.19531 -0.49707,153.98242 -35.53613,-10.84863 -97.05371,-35.83008 -97.05371,-35.83008 0,0 -94.21338,46.62989 -102.16846,39.79102 C -0.09327,177.28564 2.61669,17.83301 2.61669,17.83301 Z"
+   id="path2" />
+       <!--<path
+   fill="#65f3fa"
+   d="m 221.03662,115.26514 c 3.91504,1.72265 1.54102,1.95019 0,0 z"
+   id="path4" />-->
+       <path
+   fill="#65f3fa"
+   d="m 205.83838,178.84717 c 0,-0.0176 -0.005,-0.0147 0,0"
+   id="path6" />
+       <line
+   fill="none"
+   stroke="#65f3fa"
+   x1="140.16553"
+   y1="207.09131"
+   x2="140.16943"
+   y2="207.09424"
+   id="line8" />
+       <g
+   id="g16">
+               <g
+   id="g14">
+                       <path
+   fill="none"
+   d="m 123.84619,35.54297 c -1.50098,45.99951 -2.88574,67.85693 -5.45508,111.79639"
+   id="path10" />
+                       <path
+   fill="#3ec3f7"
+   d="m 118.84619,35.54297 c -1.22461,37.30029 -3.27539,74.5415 -5.45508,111.79639 -0.16504,2.82422 0.94238,10 5,10 4.28125,0 4.83398,-7.16797 5,-10 2.17969,-37.25488 4.23047,-74.49609 5.45508,-111.79639 0.0928,-2.8291 -0.89355,-10 -5,-10 -4.23242,0 -4.90723,7.1665 -5,10 z"
+   id="path12" />
+               </g>
+       </g>
+       <path
+   opacity="0.65"
+   fill="#d8fcfd"
+   d="m 120.71924,0.18164 c 14.71191,5.04053 88.9834,20.00781 88.59668,25.95947 -0.27246,4.16016 -83.74316,19.19531 -89.45312,17.38184 C 84.81055,32.39062 37.31348,19.71533 0,19.74121 Z"
+   id="path18" />
+       <path
+   fill="#3ec3f7"
+   d="m 112.18701,142.84814 c 0,0 94.89746,30.63086 94.89746,37.31543 0,6.68457 -88.15137,26.5459 -88.15137,26.5459 0,0 -86.87158,-14.04883 -109.6289,-23.95508 -22.75684,-9.90625 102.88281,-39.90625 102.88281,-39.90625 z"
+   id="path20" />
+       <g
+   opacity="0.4"
+   id="g24">
+               <path
+   fill-rule="evenodd"
+   clip-rule="evenodd"
+   fill="#d8fcfd"
+   d="m 205.64111,28.13721 c -9.2627,2.87549 -81.55078,13.56494 -81.83887,18.68457 -1.55371,27.63086 -2.58984,55.31738 -2.74609,82.99121 -0.0889,15.78906 -0.11523,31.72559 1.58105,47.44824 0.10645,0.98145 3.99609,23.65723 8.45996,15.81152 6.12598,-10.76953 -1.87012,-33.44336 -3.71191,-44.72363 -2.37598,-14.57422 2.01367,-27.80859 7.21777,-41.61133 8.33203,-22.09717 27.69141,-8.30957 26.77832,11.21777 -0.65039,13.9043 -9.77051,31.88672 -12.56543,46.04199 -1.85156,9.38379 -4.27734,25.07422 2.73926,33.36426 6.22559,7.35645 35.44727,-10.54102 41.3584,-13.68555 26.00391,-13.83105 18.03613,-39.94141 17.88574,-66.20508 -0.10449,-18.41895 -0.3877,-36.8457 -1.20508,-55.24805 -0.32323,-7.30565 1.87306,-28.19774 -3.95312,-34.08592"
+   id="path22" />
+       </g>
+       <g
+   opacity="0.4"
+   id="g36">
+               <path
+   fill-rule="evenodd"
+   clip-rule="evenodd"
+   fill="#cafcfc"
+   d="m 87.51367,13.68896 c 28.32568,8.12988 47.3833,33.41992 77.75146,19.35693 C 152.87939,22.24854 111.51123,10.19678 87.51367,13.68896 Z"
+   id="path26" />
+               <g
+   id="g34">
+                       <path
+   fill="none"
+   d="m 87.51367,13.68896 c 28.32568,8.12988 47.3833,33.41992 77.75146,19.35693 C 152.87939,22.24854 111.51123,10.19678 87.51367,13.68896 Z"
+   id="path28" />
+                       <g
+   id="g32">
+                               <path
+   fill="#d6eef4"
+   d="m 146.69775,47.47705 c 0.0146,-0.4043 -0.26465,-0.80566 0.18359,-0.99561 1.38477,-0.41699 2.56348,0.98096 3.9707,0.45312 l 0.0537,-0.65869 c 1.10254,0.19775 2.27734,0.46289 3.47559,0.5708 2.125,-0.38281 4.17871,-0.99805 6.11816,-1.76709 -0.11621,-0.21484 -0.19727,-0.41895 -0.0244,-0.55957 0.7666,-0.41113 1.98828,-0.4834 3.13965,-0.85107 l 0.46582,-0.28613 c 0.082,-0.17871 0.0381,-0.40674 0.0107,-0.54639 0.51758,-0.16162 0.99316,-0.2666 1.44043,-0.354 l 1.82129,-1.30225 0.89648,-0.66113 0.22266,-0.16602 0.11133,-0.08301 0.0137,-0.01025 0.003,-0.0024 c 0.84082,-5.8877 -1.875,13.1748 1.88477,-13.2002 l -0.009,-0.0044 -0.0342,-0.01709 -0.0693,-0.03418 -0.55371,-0.27051 c -1.4707,-0.67188 -2.9668,-1.49658 -4.39355,-1.8916 -2.88379,-1.02539 -5.74023,-1.6792 -8.65723,-2.28369 -1.36328,0.03223 -2.70312,0.07812 -3.8584,-0.15186 -1.65332,-0.45166 -3.49805,-1.62695 -5.00488,-2.33057 -0.60742,2.21777 -4.69824,1.95264 -4.74219,4.4126 -0.97461,-0.40186 -2.43945,-1.021 -2.72852,-0.41895 -0.85938,1.77832 -2.35059,3.6709 -5.26855,3.97412 -1.07617,-0.07617 -2.41113,-1.30225 -2.88477,-1.02148 -0.7373,0.44434 0.93066,1.69531 0.18945,2.13818 7.20117,2.84912 14.57031,4.70117 20.86914,8.10107 0.71582,0.04102 1.98633,0.58984 3.61816,1.39648 0.45117,0.19824 0.70215,0.4248 1.09277,0.65186 l 0.55762,0.35107 0.28809,0.17969 0.14648,0.09082 0.0732,0.0459 0.0371,0.02295 0.0186,0.01123 0.01,0.0059 0.005,0.0029 c -0.47363,3.34229 4.14746,-29.0957 2.1875,-15.36328 -0.99316,0.46582 -2.03906,1.06836 -3.12305,1.45752 -4.31445,1.88232 -8.96094,2.23828 -10.83398,1.97266 l -0.34082,0.03662 c -2.05078,-0.14404 -4.53516,-0.29053 -6.55078,0.16846 -0.95117,0.3501 -1.98535,0.79004 -3.05078,1.13477 l 0.85254,1.41602 c -0.91992,-0.31299 -1.83105,-0.60254 -2.3125,-0.32227 -2.29297,0.2876 -1.56348,1.73975 -1.19336,3.5127 0.39941,0.84375 -0.7373,1.61133 0.0332,2.55713 -0.69922,-0.22021 -1.03125,-0.37598 -1.71973,-0.62842 -0.2832,0.60693 2.24316,0.36816 1.4541,1.23145 -0.61523,-0.4292 -1.48145,-0.31592 -2.18066,-0.57178 -0.0391,0.9248 2.34863,1.11572 2.00391,1.89307 -0.47559,0.10303 -1.65918,-1.76855 -2.13672,-0.77539 -0.0967,0.19824 0.61328,0.46436 0.96875,0.59863 -2.30859,-0.3877 -3.91699,0.104 -2.23828,1.95801 -0.73047,-0.26367 -1.56055,-1.09131 -2.36719,-1.22314 l -9.8e-4,0.01855 c 0.36133,0.17285 0.93066,0.625 1.27441,0.76758 l -1.26367,-0.53076 0.0635,0.50781 c 0.27441,0.24463 0.56152,0.46533 0.89258,0.60596 l -0.84692,-0.356 c 0.0898,0.41162 0.2207,0.82373 0.38574,1.22754 0.77832,1.05615 1.52832,2.34668 2.1084,2.57227 4.61721,2.04687 9.96194,3.41552 15.44631,3.59374 z"
+   id="path30" />
+                       </g>
+               </g>
+       </g>
+       <path
+   opacity="0.5"
+   fill-rule="evenodd"
+   clip-rule="evenodd"
+   fill="#d8fcfd"
+   d="M 14.76758,170.56689 C 12.07715,138.42822 11.77588,100.68212 13.86133,57.33642 34.48779,13.45947 34.79004,51.20557 14.76758,170.56689 Z"
+   id="path38" />
+       <g
+   opacity="0.65"
+   id="g42">
+               <path
+   fill-rule="evenodd"
+   clip-rule="evenodd"
+   fill="#d8fcfd"
+   d="M 122.45752,46.8501 C 117.43604,31.20655 30.69678,21.91016 14.34473,21.16114 c -8.69824,-0.39746 -7.396,97.7876 -7.37256,106.81494 0.04297,16.79492 -0.22363,33.86133 1.70752,50.58398 1.88818,16.35547 29.48389,14.19727 43.17676,16.3457 6.24951,0.98242 50.11523,12.59375 42.5752,-2.03711 -8.08252,-15.68555 -16.54004,-12.35156 -31.92773,-11.30664 -3.78174,0.25586 -28.06787,-8.11328 -27.92871,-10.96484 0.04395,-0.91406 15.56152,-7.55664 17.03711,-8.76172 8.35059,-6.82422 8.72998,-15.99414 7.68213,-25.54688 -2.17285,-19.81445 2.98828,-56.21484 8.08203,-71.2085 4.21387,-12.4043 18.42041,32.79883 18.42041,32.79883 0,0 -10.23633,28.68701 -4.43555,47.73975 1.93018,6.33789 6.40674,34.34961 17.83154,32.28711 14.87695,-2.68555 16.0752,-17.03711 17.04297,-27.7832 1.72754,-19.19922 3.30762,-38.41406 4.66016,-57.63916 0.93358,-13.26319 5.74706,-32.59375 1.56151,-45.6333"
+   id="path40" />
+       </g>
+       <g
+   opacity="0.45"
+   id="g52">
+               <g
+   id="g50">
+                       <path
+   fill="none"
+   d="m 100.76514,47.06055 c 6.03027,21.68359 12.05957,81.31787 -2.0083,113.06787"
+   id="path44" />
+                       <g
+   id="g48">
+                               <path
+   fill="#ddfcfd"
+   d="m 95.31689,75.17334 c 0.40283,-0.03271 0.76172,-0.44336 1.0127,0.10254 0.60693,1.74414 -0.60889,3.32227 -0.06934,5.07373 l 0.66113,0.06787 c -0.15039,1.41504 -0.37988,2.89014 -0.55127,4.38623 0.26123,2.70996 0.61523,5.40332 0.979,8.08887 0.23535,-0.08203 0.45264,-0.12695 0.55029,0.13867 0.21631,1.11523 0.04541,2.68262 0.0376,4.29688 l 0.14014,0.70703 c 0.14746,0.17871 0.37891,0.21973 0.52051,0.24512 0.0019,0.73047 -0.02539,1.38281 -0.0874,1.98438 1.42725,7.89307 2.78613,15.99268 3.53613,24.88916 0.4082,1.89844 0.81543,3.82227 0.90283,5.65234 -0.0698,2.68359 -1.06006,5.97656 -1.52051,8.51953 2.35986,-0.0156 2.11719,6.5293 4.65723,5.79883 -0.36475,1.76562 -1.17627,4.36328 -0.6084,4.66797 1.70996,0.92188 3.69043,2.88281 3.10547,8.19531 -0.47607,2.03125 -2.37939,4.66211 -2.27832,5.48633 0.15332,1.31055 2.24219,-1.94336 2.40283,-0.64258 6.57715,-14.46094 7.47461,-28.69531 8.39062,-43.01172 -0.13867,-5.05664 -1.32812,-37.54736 -2.40625,-45.85742 l -0.11719,-0.75244 c -0.37305,-4.55225 -1.3125,-10.05371 -2.84473,-13.74854 -0.8584,-1.67285 -1.75977,-3.33057 -2.77197,-4.98486 -0.19287,0.89941 -0.42236,1.729 -0.68604,2.45264 -0.25195,-1.79639 -0.62549,-3.60645 -1.16016,-4.20605 -1.75439,-3.59717 -2.42578,-1.16113 -3.66699,0.5874 -0.46045,1.16602 -1.77686,0.0063 -2.1333,1.73682 -0.20508,-1.14844 -0.30762,-1.72461 -0.51123,-2.87988 -0.6665,0.0093 1.05664,3.45654 -0.15479,2.87988 0.01,-1.14502 -0.6123,-2.2998 -0.84668,-3.42969 -0.75049,0.57812 0.49756,4.00293 -0.38379,3.99951 -0.32373,-0.56006 0.50293,-3.43066 -0.60596,-3.41064 -0.21826,0.0039 -0.01904,1.14062 0.08154,1.70752 -1.06006,-3.41504 -2.60449,-4.90576 -2.97168,-1.61865 -0.23047,-1.05078 -0.15576,-2.65186 -0.57715,-3.72656 l -0.01465,0.01318 c 0.10352,0.56494 0.12354,1.57764 0.23682,2.09082 l -0.41406,-1.90234 -0.35596,0.44922 c -0.0127,0.50293 0,0.99854 0.10596,1.48926 l -0.27295,-1.25391 -0.72021,1.31299 c -0.30908,1.63574 -0.96582,3.23486 -0.8418,4.07178 0.89505,6.62107 1.57571,13.50534 2.25198,20.33347 z"
+   id="path46" />
+                       </g>
+               </g>
+       </g>
+</g>
+<g
+   id="Layer_2"
+   transform="matrix(0.9,0,0,0.84995245,11.158592,15.562068)">
+</g>
+</svg>
index aff4710..df15026 100644 (file)
@@ -135,6 +135,10 @@ export const ChessRules = class ChessRules {
   static get LoseOnRepetition() {
     return false;
   }
+  // And in some others (Iceage), repetitions should be ignored:
+  static get IgnoreRepetition() {
+    return false;
+  }
 
   // At some stages, some games could wait clicks only:
   onlyClick() {
index 7bf8e72..cd10d03 100644 (file)
@@ -222,14 +222,15 @@ export const translations = {
   "Friendly pieces": "Friendly pieces",
   "Fusion pieces (v1)": "Fusion pieces (v1)",
   "Fusion pieces (v2)": "Fusion pieces (v2)",
-  "In the shadow": "In the shadow",
-  "Interweaved colorbound teams": "Interweaved colorbound teams",
   "General's Chess": "General's Chess",
   "Geometric Chess": "Geometric Chess",
   "Get strong at self-mate": "Get strong at self-mate",
   "Give three checks": "Give three checks",
   "Harassed kings": "Harassed kings",
   "Hawaiian Checkers": "Hawaiian Checkers",
+  "Ice Age is coming!": "Ice Age is coming!",
+  "In the shadow": "In the shadow",
+  "Interweaved colorbound teams": "Interweaved colorbound teams",
   "Japanese Chess": "Japanese Chess",
   "Jump the borders": "Jump the borders",
   "Keep antiking in check (v1)": "Keep antiking in check (v1)",
index 3154983..11d64a4 100644 (file)
@@ -222,14 +222,15 @@ export const translations = {
   "Friendly pieces": "Piezas amistosas",
   "Fusion pieces (v1)": "Fusionar piezas (v1)",
   "Fusion pieces (v2)": "Fusionar piezas (v2)",
-  "In the shadow": "En la sombra",
-  "Interweaved colorbound teams": "Equipos unicolores entrelazados",
   "General's Chess": "Ajedrez de los Generales",
   "Geometric Chess": "Ajedrez geométrico",
   "Get strong at self-mate": "Progreso en mates asistidos",
   "Give three checks": "Dar tres jaques",
   "Harassed kings": "Reyes acosados",
   "Hawaiian Checkers": "Damas hawaianas",
+  "Ice Age is coming!": "¡Se acerca la Edad de Hielo!",
+  "In the shadow": "En la sombra",
+  "Interweaved colorbound teams": "Equipos unicolores entrelazados",
   "Japanese Chess": "Ajedrez japonés",
   "Jump the borders": "Saltar las fronteras",
   "Keep antiking in check (v1)": "Mantener el antirey en jaque (v1)",
index a0518ee..4d134fc 100644 (file)
@@ -222,14 +222,15 @@ export const translations = {
   "Friendly pieces": "Pièces amies",
   "Fusion pieces (v1)": "Fusionner les pièces (v1)",
   "Fusion pieces (v2)": "Fusionner les pièces (v2)",
-  "In the shadow": "Dans l'ombre",
-  "Interweaved colorbound teams": "Équipes unicolores entremêlées",
   "General's Chess": "Échecs des Généraux",
   "Geometric Chess": "Échecs géométriques",
   "Get strong at self-mate": "Progressez en mats aidés",
   "Give three checks": "Donnez trois échecs",
   "Harassed kings": "Rois harcelés",
   "Hawaiian Checkers": "Dames hawaïennes",
+  "Ice Age is coming!": "L'Âge de Glace arrive !",
+  "In the shadow": "Dans l'ombre",
+  "Interweaved colorbound teams": "Équipes unicolores entremêlées",
   "Japanese Chess": "Échecs japonais",
   "Jump the borders": "Sauter les frontières",
   "Keep antiking in check (v1)": "Gardez l'antiroi en échec (v1)",
diff --git a/client/src/translations/rules/Iceage/en.pug b/client/src/translations/rules/Iceage/en.pug
new file mode 100644 (file)
index 0000000..fbcac3c
--- /dev/null
@@ -0,0 +1,43 @@
+p.boxed
+  | Every 20 moves, most empty squares freeze and isolated pieces vanish.
+
+p
+  | Ice Age is a 
+  a(href="https://www.chessvariants.com/boardrules.dir/iceage.html")
+    | chess variant
+  | &nbsp;invented by Köksal Karakus in 2000.
+  | It can also be played on 
+  a(href="https://brainking.com/en/GameRules?tp=100") brainking.com
+  | .
+
+figure.diagram-container
+  .diagram
+    | fen:rnbqkbnr/pppppppp/cccccccc/cccccccc/cccccccc/cccccccc/PPPPPPPP/RNBQKBNR:
+  figcaption Deterministic initial position
+
+p.
+  If the board is filled with ice cubes, you can only move by capturing them.
+  Ice cubes behave as normal pieces, which cannot move.
+
+p.
+  Just after the 20th black move (and before the 21st white one),
+  "ice age is coming":
+ul
+  li all empty squares freeze, except those orthogonally surrounded by pieces.
+  li all pieces which are not adjacent to any other piece (black or white) vanish.
+p.
+  If only one king remains, the other side loses.
+  But if both disappeared, then the result is a draw.
+
+figure.diagram-container
+  .diagram.diag12
+    | fen:2rq1rk1/3bpp2/1c1p1bP1/1p2n3/4P2P/1NN2P1c/PPPQ4/1K1R3R:
+  .diagram.diag22
+    | fen:cccq1rkc/cccbppcc/cccp1bPc/ccccnccc/ccccPccc/cNrccPcc/PPPQcccc/1K1Rcccc:
+  figcaption Before and after 20...Rxc3
+
+p.
+  Then, every 20 moves ice age comes again: after move 40, 60, and so on.
+  This condition excepted, the game follows FIDE chess rules, without draws
+  on repetition: indeed, as the author notices, sometimes a win is possible
+  by "waiting until the enemy king freezes".
diff --git a/client/src/translations/rules/Iceage/es.pug b/client/src/translations/rules/Iceage/es.pug
new file mode 100644 (file)
index 0000000..0332843
--- /dev/null
@@ -0,0 +1,48 @@
+p.boxed
+  | Cada 20 movimientos, la mayoría de las casillas vacías se congelan
+  | y las piezas aisladas desaparecen.
+
+p
+  | Ice Age es 
+  a(href="https://www.chessvariants.com/boardrules.dir/iceage.html")
+    | una variante
+  | &nbsp;inventado por Köksal Karakus en 2000.
+  | También puedes jugarlo en 
+  a(href="https://brainking.com/en/GameRules?tp=100") brainking.com
+  | .
+
+figure.diagram-container
+  .diagram
+    | fen:rnbqkbnr/pppppppp/cccccccc/cccccccc/cccccccc/cccccccc/PPPPPPPP/RNBQKBNR:
+  figcaption Posición inicial determinista
+
+p.
+  Si el tablero está lleno de bloques de hielo, solo puedes mover
+  capturarlos. Se comportan como piezas estacionarias normales.
+
+p.
+  Inmediatamente después del 20mo movimiento negro (y antes del 20mo
+  movimiento blanco), "la edad de hielo se acerca":
+ul
+  li.
+    todas las casillas vacías se congelan,
+    excepto aquellas rodeadas ortogonalmente por piezas.
+  li.
+    todas las piezas que no están adyacentes a otra habitación
+    (amigo o enemigo) desaparece.
+p.
+  Si solo queda un rey, el otro lado pierde.
+  Pero si ambos se van, entonces el juego es un empate.
+
+figure.diagram-container
+  .diagram.diag12
+    | fen:2rq1rk1/3bpp2/1c1p1bP1/1p2n3/4P2P/1NN2P1c/PPPQ4/1K1R3R:
+  .diagram.diag22
+    | fen:cccq1rkc/cccbppcc/cccp1bPc/ccccnccc/ccccPccc/cNrccPcc/PPPQcccc/1K1Rcccc:
+  figcaption Antes y después de 20...Rxc3
+
+p.
+  Luego, cada 20 jugadas regresa la edad de hielo: después del 40, 60,
+  etc. Salvo esta condición, el juego sigue las reglas de ajedrez de la FIDE,
+  sin los empates por repetición: de hecho, como señala el autor,
+  a veces puedes ganar "esperando que el rey contrario se congele".
diff --git a/client/src/translations/rules/Iceage/fr.pug b/client/src/translations/rules/Iceage/fr.pug
new file mode 100644 (file)
index 0000000..8f285b7
--- /dev/null
@@ -0,0 +1,48 @@
+p.boxed
+  | Tous les 20 coups, la plupart des cases vides gèlent
+  | et les pièces isolées disparaissent.
+
+p
+  | Ice Age est 
+  a(href="https://www.chessvariants.com/boardrules.dir/iceage.html")
+    | une variante
+  | &nbsp;inventée par Köksal Karakus en 2000.
+  | On peut aussi y jouer sur 
+  a(href="https://brainking.com/en/GameRules?tp=100") brainking.com
+  | .
+
+figure.diagram-container
+  .diagram
+    | fen:rnbqkbnr/pppppppp/cccccccc/cccccccc/cccccccc/cccccccc/PPPPPPPP/RNBQKBNR:
+  figcaption Position initiale déterministe
+
+p.
+  Si l'échiquier est rempli de blocs de glace, vous ne pouvez bougez qu'en
+  les capturant. Ceux-ci se comportent comme des pièces normales, immobiles.
+
+p.
+  Immédiatement après le 20eme coup noir (et avant le 21 coup blanc),
+  "l'âge de glace arrive" :
+ul
+  li.
+    toutes les cases vides gèlent,
+    sauf celles orthogonalement entourées de pièces.
+  li.
+    toutes les pièces qui ne sont pas adjacentes à une autre pièce
+    (amie ou ennemie) disparaissent.
+p.
+  Si un seul roi subsiste, l'autre camp perd.
+  Mais si les deux ont disparu, alors la partie est nulle.
+
+figure.diagram-container
+  .diagram.diag12
+    | fen:2rq1rk1/3bpp2/1c1p1bP1/1p2n3/4P2P/1NN2P1c/PPPQ4/1K1R3R:
+  .diagram.diag22
+    | fen:cccq1rkc/cccbppcc/cccp1bPc/ccccnccc/ccccPccc/cNrccPcc/PPPQcccc/1K1Rcccc:
+  figcaption Avant et après 20...Rxc3
+
+p.
+  Ensuite, tous les 20 coups l'âge de glace revient : après le 40eme, 60eme,
+  etc. Cette condition exceptée, la partie suit les règles FIDE des échecs,
+  sans les nulles par répétition : en effet, comme l'auteur le fait remarquer,
+  on peut parfois gagner en "attendant que le roi adverse gèle".
index 2c14ba6..a895843 100644 (file)
@@ -467,6 +467,7 @@ p.
     "Fusion",
     "Gridolina",
     "Hamilton",
+    "Iceage",
     "Kingsmaker",
     "Magnetic",
     "Refusal",
index 69756b1..609ac03 100644 (file)
@@ -477,6 +477,7 @@ p.
     "Fusion",
     "Gridolina",
     "Hamilton",
+    "Iceage",
     "Kingsmaker",
     "Magnetic",
     "Refusal",
index 91585e9..6c84697 100644 (file)
@@ -475,6 +475,7 @@ p.
     "Fusion",
     "Gridolina",
     "Hamilton",
+    "Iceage",
     "Kingsmaker",
     "Magnetic",
     "Refusal",
diff --git a/client/src/variants/Iceage.js b/client/src/variants/Iceage.js
new file mode 100644 (file)
index 0000000..01f82d8
--- /dev/null
@@ -0,0 +1,143 @@
+import { ChessRules } from "@/base_rules";
+
+export class IceageRules extends ChessRules {
+
+  static get IgnoreRepetition() {
+    return true;
+  }
+
+  static get ICECUBE() {
+    return "cc";
+  }
+
+  static board2fen(b) {
+    if (b[0] == 'c') return 'c';
+    return ChessRules.board2fen(b);
+  }
+
+  static fen2board(f) {
+    if (f == 'c') return V.ICECUBE;
+    return ChessRules.fen2board(f);
+  }
+
+  getPpath(b) {
+    if (b[0] == 'c') return "Iceage/icecube";
+    return b;
+  }
+
+  static IsGoodPosition(position) {
+    if (position.length == 0) return false;
+    const rows = position.split("/");
+    if (rows.length != V.size.x) return false;
+    let kings = { "k": 0, "K": 0 };
+    for (let row of rows) {
+      let sumElts = 0;
+      for (let i = 0; i < row.length; i++) {
+        if (['K','k'].includes(row[i])) kings[row[i]]++;
+        if (['c'].concat(V.PIECES).includes(row[i].toLowerCase())) sumElts++;
+        else {
+          const num = parseInt(row[i], 10);
+          if (isNaN(num)) return false;
+          sumElts += num;
+        }
+      }
+      if (sumElts != V.size.y) return false;
+    }
+    if (Object.values(kings).some(v => v != 1)) return false;
+    return true;
+  }
+
+  static GenRandInitFen(randomness) {
+    return ChessRules.GenRandInitFen(randomness).replace(/8/g, "cccccccc");
+  }
+
+  play(move) {
+    const iceAgeAfterMove = (this.movesCount % 40 == 39);
+    if (iceAgeAfterMove)
+      // Next ice age after this move:
+      move.state = JSON.stringify(this.board);
+    super.play(move);
+    if (iceAgeAfterMove) {
+      for (let i=0; i<8; i++) {
+        for (let j=0; j<8; j++) {
+          if (this.board[i][j] == V.EMPTY) {
+            const surrounded = V.steps[V.ROOK].every(s => {
+              const [ii, jj] = [i + s[0], j + s[1]];
+              return (
+                !V.OnBoard(ii, jj) ||
+                ![V.EMPTY, V.ICECUBE].includes(this.board[ii][jj])
+              );
+            });
+            if (!surrounded) this.board[i][j] = V.ICECUBE;
+          }
+          else if (this.board[i][j] != V.ICECUBE) {
+            const steps = V.steps[V.ROOK].concat(V.steps[V.BISHOP]);
+            const connected = steps.some(s => {
+              const [ii, jj] = [i + s[0], j + s[1]];
+              return (
+                V.OnBoard(ii, jj) &&
+                ![V.EMPTY, V.ICECUBE].includes(this.board[ii][jj])
+              );
+            });
+            if (!connected) this.board[i][j] = V.ICECUBE;
+          }
+        }
+      }
+      // Update king position (no need to update flags: game over)
+      const kp = this.kingPos;
+      if (this.getPiece(kp['w'][0], kp['w'][1]) != V.KING)
+        this.kingPos['w'] = [-1, -1];
+      if (this.getPiece(kp['b'][0], kp['b'][1]) != V.KING)
+        this.kingPos['b'] = [-1, -1];
+    }
+  }
+
+  undo(move) {
+    super.undo(move);
+    if (!!move.state) {
+      this.board = JSON.parse(move.state);
+      if (this.kingPos['w'][0] < 0 || this.kingPos['b'][0] < 0) {
+        for (let i=0; i<8; i++) {
+          for (let j=0; j<8; j++) {
+            if (this.board[i][j] != V.EMPTY && this.getPiece(i, j) == V.KING)
+              this.kingPos[this.getColor(i, j)] = [i, j];
+          }
+        }
+      }
+    }
+  }
+
+  getCheckSquares() {
+    if (this.kingPos[this.turn][0] < 0) return [];
+    return super.getCheckSquares();
+  }
+
+  getCurrentScore() {
+    const kingDisappear = {
+      w: this.kingPos['w'][0] < 0,
+      b: this.kingPos['b'][0] < 0
+    };
+    if (kingDisappear['w'] && kingDisappear['b']) return "1/2";
+    if (kingDisappear['w']) return "0-1";
+    if (kingDisappear['b']) return "1-0";
+    return super.getCurrentScore();
+  }
+
+  static get SEARCH_DEPTH() {
+    return 2;
+  }
+
+  evalPosition() {
+    let evaluation = 0;
+    for (let i = 0; i < V.size.x; i++) {
+      for (let j = 0; j < V.size.y; j++) {
+        if (![V.EMPTY,V.ICECUBE].includes(this.board[i][j])) {
+          const sign = this.getColor(i, j) == "w" ? 1 : -1;
+          evaluation += sign * V.VALUES[this.getPiece(i, j)];
+        }
+      }
+    }
+    return evaluation;
+  }
+
+};
index 6aea261..65d4646 100644 (file)
@@ -1406,18 +1406,20 @@ export default {
           // In corr games, just reset clock to mainTime:
           this.game.clocks[colorIdx] = extractTime(this.game.cadence).mainTime;
         }
-        // If repetition detected, consider that a draw offer was received:
-        const fenObj = this.vr.getFenForRepeat();
-        this.repeat[fenObj] =
-          !!this.repeat[fenObj]
-            ? this.repeat[fenObj] + 1
-            : 1;
-        if (this.repeat[fenObj] >= 3) {
-          if (V.LoseOnRepetition)
-            this.gameOver(moveCol == "w" ? "0-1" : "1-0", "Repetition");
-          else this.drawOffer = "threerep";
+        if (!V.IgnoreRepetition) {
+          // If repetition detected, consider that a draw offer was received:
+          const fenObj = this.vr.getFenForRepeat();
+          this.repeat[fenObj] =
+            !!this.repeat[fenObj]
+              ? this.repeat[fenObj] + 1
+              : 1;
+          if (this.repeat[fenObj] >= 3) {
+            if (V.LoseOnRepetition)
+              this.gameOver(moveCol == "w" ? "0-1" : "1-0", "Repetition");
+            else this.drawOffer = "threerep";
+          }
+          else if (this.drawOffer == "threerep") this.drawOffer = "";
         }
-        else if (this.drawOffer == "threerep") this.drawOffer = "";
         if (!!this.game.mycolor && !data.receiveMyMove) {
           // NOTE: 'var' to see that variable outside this block
           var filtered_move = getFilteredMove(move);
index 5648379..9b7842b 100644 (file)
@@ -80,6 +80,7 @@ insert or ignore into Variants (name, description) values
   ('Hoppelpoppel', 'Knibis and Bisknis'),
   ('Horde', 'A pawns cloud'),
   ('Hypnotic', 'Mind control (v1)'),
+  ('Iceage', 'Ice Age is coming!'),
   ('Interweave', 'Interweaved colorbound teams'),
   ('Isardam', 'No paralyzed pieces'),
   ('Janggi', 'Korean Chess'),