Add Forward + Doubleorda variants
authorBenjamin Auder <benjamin.auder@somewhere>
Mon, 18 May 2020 16:29:24 +0000 (18:29 +0200)
committerBenjamin Auder <benjamin.auder@somewhere>
Mon, 18 May 2020 16:29:24 +0000 (18:29 +0200)
42 files changed:
TODO
client/public/images/pieces/Forward/bc.svg [new symlink]
client/public/images/pieces/Forward/bl.svg [new symlink]
client/public/images/pieces/Forward/bo.svg [new symlink]
client/public/images/pieces/Forward/bs.svg [new symlink]
client/public/images/pieces/Forward/bt.svg [new symlink]
client/public/images/pieces/Forward/bu.svg [new symlink]
client/public/images/pieces/Forward/wc.svg [new symlink]
client/public/images/pieces/Forward/wl.svg [new symlink]
client/public/images/pieces/Forward/wo.svg [new symlink]
client/public/images/pieces/Forward/ws.svg [new symlink]
client/public/images/pieces/Forward/wt.svg [new symlink]
client/public/images/pieces/Forward/wu.svg [new symlink]
client/public/images/pieces/Orda/bf.svg [new file with mode: 0644]
client/public/images/pieces/Orda/wa.svg [new file with mode: 0644]
client/public/images/pieces/Orda/wf.svg [new symlink]
client/public/images/pieces/Orda/wk.svg [new file with mode: 0644]
client/public/images/pieces/Orda/wl.svg [new file with mode: 0644]
client/public/images/pieces/Orda/wp.svg [new symlink]
client/src/base_rules.js
client/src/translations/en.js
client/src/translations/es.js
client/src/translations/fr.js
client/src/translations/rules/Clorange/en.pug [new file with mode: 0644]
client/src/translations/rules/Clorange/es.pug [new file with mode: 0644]
client/src/translations/rules/Clorange/fr.pug [new file with mode: 0644]
client/src/translations/rules/Doubleorda/en.pug [new file with mode: 0644]
client/src/translations/rules/Doubleorda/es.pug [new file with mode: 0644]
client/src/translations/rules/Doubleorda/fr.pug [new file with mode: 0644]
client/src/translations/rules/Forward/en.pug [new file with mode: 0644]
client/src/translations/rules/Forward/es.pug [new file with mode: 0644]
client/src/translations/rules/Forward/fr.pug [new file with mode: 0644]
client/src/translations/rules/Rampage/en.pug
client/src/translations/rules/Rampage/es.pug
client/src/translations/rules/Rampage/fr.pug
client/src/variants/Clorange.js [new file with mode: 0644]
client/src/variants/Doubleorda.js [new file with mode: 0644]
client/src/variants/Forward.js [new file with mode: 0644]
client/src/variants/Orda.js
client/src/variants/Rampage.js
client/src/variants/Switching.js
server/db/populate.sql

diff --git a/TODO b/TODO
index d0cca4a..0698ddf 100644 (file)
--- a/TODO
+++ b/TODO
@@ -3,9 +3,6 @@ Also: if new live game starts in background, "new game" notify OK but not first
 On smartphone for Teleport, Chakart, Weiqi and some others: option "confirm moves on touch screen"
 (=> comme pour corr) + option "confirm moves in corr games"?
 
-https://www.chessvariants.com/diffmove.dir/checkers.html --> "Forward"
-in 1974 by Hans Multhopp
-
 Clorange:
 Clockwork Orange Chess (Fergus Duniho,
 1999). https://www.chessvariants.com/other.dir/clockworkorange.html
diff --git a/client/public/images/pieces/Forward/bc.svg b/client/public/images/pieces/Forward/bc.svg
new file mode 120000 (symlink)
index 0000000..b30a26a
--- /dev/null
@@ -0,0 +1 @@
+../Alice/bc.svg
\ No newline at end of file
diff --git a/client/public/images/pieces/Forward/bl.svg b/client/public/images/pieces/Forward/bl.svg
new file mode 120000 (symlink)
index 0000000..a10d9e0
--- /dev/null
@@ -0,0 +1 @@
+../Alice/bl.svg
\ No newline at end of file
diff --git a/client/public/images/pieces/Forward/bo.svg b/client/public/images/pieces/Forward/bo.svg
new file mode 120000 (symlink)
index 0000000..1200186
--- /dev/null
@@ -0,0 +1 @@
+../Alice/bo.svg
\ No newline at end of file
diff --git a/client/public/images/pieces/Forward/bs.svg b/client/public/images/pieces/Forward/bs.svg
new file mode 120000 (symlink)
index 0000000..e8cf23a
--- /dev/null
@@ -0,0 +1 @@
+../Alice/bs.svg
\ No newline at end of file
diff --git a/client/public/images/pieces/Forward/bt.svg b/client/public/images/pieces/Forward/bt.svg
new file mode 120000 (symlink)
index 0000000..c517549
--- /dev/null
@@ -0,0 +1 @@
+../Alice/bt.svg
\ No newline at end of file
diff --git a/client/public/images/pieces/Forward/bu.svg b/client/public/images/pieces/Forward/bu.svg
new file mode 120000 (symlink)
index 0000000..09e6ea3
--- /dev/null
@@ -0,0 +1 @@
+../Alice/bu.svg
\ No newline at end of file
diff --git a/client/public/images/pieces/Forward/wc.svg b/client/public/images/pieces/Forward/wc.svg
new file mode 120000 (symlink)
index 0000000..d23af91
--- /dev/null
@@ -0,0 +1 @@
+../Alice/wc.svg
\ No newline at end of file
diff --git a/client/public/images/pieces/Forward/wl.svg b/client/public/images/pieces/Forward/wl.svg
new file mode 120000 (symlink)
index 0000000..51c1893
--- /dev/null
@@ -0,0 +1 @@
+../Alice/wl.svg
\ No newline at end of file
diff --git a/client/public/images/pieces/Forward/wo.svg b/client/public/images/pieces/Forward/wo.svg
new file mode 120000 (symlink)
index 0000000..4a85712
--- /dev/null
@@ -0,0 +1 @@
+../Alice/wo.svg
\ No newline at end of file
diff --git a/client/public/images/pieces/Forward/ws.svg b/client/public/images/pieces/Forward/ws.svg
new file mode 120000 (symlink)
index 0000000..659b2de
--- /dev/null
@@ -0,0 +1 @@
+../Alice/ws.svg
\ No newline at end of file
diff --git a/client/public/images/pieces/Forward/wt.svg b/client/public/images/pieces/Forward/wt.svg
new file mode 120000 (symlink)
index 0000000..447fc4f
--- /dev/null
@@ -0,0 +1 @@
+../Alice/wt.svg
\ No newline at end of file
diff --git a/client/public/images/pieces/Forward/wu.svg b/client/public/images/pieces/Forward/wu.svg
new file mode 120000 (symlink)
index 0000000..c1403b3
--- /dev/null
@@ -0,0 +1 @@
+../Alice/wu.svg
\ No newline at end of file
diff --git a/client/public/images/pieces/Orda/bf.svg b/client/public/images/pieces/Orda/bf.svg
new file mode 100644 (file)
index 0000000..01aa1fe
--- /dev/null
@@ -0,0 +1,188 @@
+<?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:xlink="http://www.w3.org/1999/xlink"
+   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+   inkscape:version="1.0 (4035a4fb49, 2020-05-01)"
+   sodipodi:docname="bFalcon.svg"
+   id="svg12863"
+   version="1.1"
+   viewBox="0 0 50 50"
+   clip-rule="evenodd"
+   fill-rule="evenodd"
+   image-rendering="optimizeQuality"
+   shape-rendering="geometricPrecision"
+   height="177.17"
+   width="177.17">
+  <metadata
+     id="metadata12867">
+    <rdf:RDF>
+      <cc:Work
+         rdf:about="">
+        <dc:format>image/svg+xml</dc:format>
+        <dc:type
+           rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+        <dc:title></dc:title>
+      </cc:Work>
+    </rdf:RDF>
+  </metadata>
+  <sodipodi:namedview
+     inkscape:document-rotation="0"
+     inkscape:current-layer="svg12863"
+     inkscape:window-maximized="1"
+     inkscape:window-y="-8"
+     inkscape:window-x="-8"
+     inkscape:cy="107.19209"
+     inkscape:cx="31.332406"
+     inkscape:zoom="1.7295106"
+     showguides="false"
+     showgrid="false"
+     id="namedview12865"
+     inkscape:window-height="1137"
+     inkscape:window-width="1920"
+     inkscape:pageshadow="2"
+     inkscape:pageopacity="0"
+     guidetolerance="10"
+     gridtolerance="10"
+     objecttolerance="10"
+     borderopacity="1"
+     bordercolor="#666666"
+     pagecolor="#ffffff" />
+  <defs
+     id="defs12857">
+    <linearGradient
+       id="linearGradient13464"
+       inkscape:collect="always">
+      <stop
+         id="stop13460"
+         offset="0"
+         style="stop-color:#9c8c55;stop-opacity:1" />
+      <stop
+         id="stop13462"
+         offset="1"
+         style="stop-color:#f3c926;stop-opacity:1" />
+    </linearGradient>
+    <linearGradient
+       gradientUnits="userSpaceOnUse"
+       x2="77.64"
+       x1="21.405"
+       id="0">
+      <stop
+         id="stop12852"
+         stop-color="#fff" />
+      <stop
+         id="stop12854"
+         stop-opacity="0"
+         stop-color="#fff"
+         offset="1" />
+    </linearGradient>
+    <linearGradient
+       gradientUnits="userSpaceOnUse"
+       y2="51.538971"
+       x2="87.865845"
+       y1="51.192822"
+       x1="115.58475"
+       id="linearGradient13468"
+       xlink:href="#linearGradient13464"
+       inkscape:collect="always" />
+    <clipPath
+       id="clipPath5191"
+       clipPathUnits="userSpaceOnUse">
+      <rect
+         clip-path="none"
+         y="4.0289068"
+         x="7.2068729"
+         height="15.671"
+         width="35.162529"
+         id="rect5193"
+         style="opacity:1;fill:#d40000;fill-opacity:1;stroke:#000000;stroke-width:0.2045171;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;paint-order:normal" />
+    </clipPath>
+    <linearGradient
+       gradientUnits="userSpaceOnUse"
+       x2="77.639999"
+       x1="21.375999"
+       id="0-2">
+      <stop
+         id="stop4571"
+         stop-color="#fff" />
+      <stop
+         id="stop4573"
+         stop-opacity="0"
+         stop-color="#fff"
+         offset="1" />
+    </linearGradient>
+    <linearGradient
+       id="0-1"
+       x1="21.253"
+       y1="37.220001"
+       x2="77.639999"
+       y2="37.349998"
+       gradientUnits="userSpaceOnUse"
+       xlink:href="#linearGradient9464">
+      <stop
+         stop-color="#fff"
+         id="stop7734"
+         style="stop-color:#f3c926;stop-opacity:1" />
+      <stop
+         offset="1"
+         stop-color="#fff"
+         stop-opacity="0"
+         id="stop7736" />
+    </linearGradient>
+    <linearGradient
+       inkscape:collect="always"
+       id="linearGradient9464">
+      <stop
+         id="stop9462"
+         offset="0"
+         style="stop-color:#806600;stop-opacity:1" />
+      <stop
+         id="stop9460"
+         offset="1"
+         style="stop-color:#ffd42a;stop-opacity:1" />
+    </linearGradient>
+  </defs>
+  <g
+     transform="matrix(1.0539134,0,0,1.1187798,-70.902198,-28.281003)"
+     id="g13475">
+    <path
+       style="fill:url(#linearGradient13468);fill-opacity:1;stroke:#1f1a17;stroke-width:1.55939555;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+       d="m 84.568171,35.093828 -6.217144,0.149811 c -6.203086,2.383935 -6.962587,5.934352 -4.793947,10.112228 -0.05331,-4.629564 3.609449,-3.313402 6.366959,-3.445648 9.559786,5.46999 4.25599,14.805717 -0.599244,18.426723 l 4.419419,0.449433 -0.524338,3.07112 4.269605,-2.92131 2.696594,3.520551 3.895081,-2.92131 1.573012,2.621691 2.022444,-2.696597 c 1.307039,1.013938 2.064854,2.354644 2.627738,3.526604 l 1.86659,-3.226981 c 1.23104,0.812023 1.87638,2.044599 2.8464,3.07112 v -4.119794 l 4.41942,2.621688 C 110.0094,46.435659 108.3116,35.260707 95.504357,31.573276 92.79365,31.513132 90.012856,31.228707 87.639293,32.247423 Z"
+       id="path13430"
+       inkscape:connector-curvature="0"
+       sodipodi:nodetypes="cccccccccccccccccccc" />
+    <path
+       style="fill:none;stroke:#1f1a17;stroke-width:1.55939555;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+       d="M 91.159846,44.531907 79.924039,41.910219"
+       id="path13432"
+       inkscape:connector-curvature="0" />
+    <path
+       style="fill:none;stroke:#1f1a17;stroke-width:1.55939555;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+       d="m 83.103812,35.805085 c -0.02515,1.008854 0.490503,1.148881 1.112288,1.324152"
+       id="path13434"
+       inkscape:connector-curvature="0"
+       sodipodi:nodetypes="cc" />
+    <path
+       style="opacity:1;fill:#1f1a17;fill-opacity:1;stroke:#1f1a17;stroke-width:1.69328892;stroke-linecap:square;stroke-linejoin:bevel;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;paint-order:normal"
+       id="path13436"
+       sodipodi:type="arc"
+       sodipodi:cx="88.897865"
+       sodipodi:cy="41.973846"
+       sodipodi:rx="2.5158896"
+       sodipodi:ry="1.8273305"
+       sodipodi:start="0"
+       sodipodi:end="3.2099747"
+       d="m 91.413755,41.973846 a 2.5158896,1.8273305 0 0 1 -1.307932,1.602928 2.5158896,1.8273305 0 0 1 -2.563889,-0.0637 2.5158896,1.8273305 0 0 1 -1.154078,-1.664092 l 2.510009,0.124859 z"
+       transform="rotate(-3.1672079)" />
+    <path
+       style="fill:#1f1a17;fill-opacity:1;stroke:#1f1a17;stroke-width:1.69324374;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+       d="m 93.644067,36.864407 3.760592,-0.423729"
+       id="path13438"
+       inkscape:connector-curvature="0" />
+  </g>
+</svg>
diff --git a/client/public/images/pieces/Orda/wa.svg b/client/public/images/pieces/Orda/wa.svg
new file mode 100644 (file)
index 0000000..5bb0aa5
--- /dev/null
@@ -0,0 +1,139 @@
+<?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:xlink="http://www.w3.org/1999/xlink"
+   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+   inkscape:version="1.0 (4035a4fb49, 2020-05-01)"
+   sodipodi:docname="wA.svg"
+   id="svg1163"
+   version="1.1"
+   viewBox="0 0 50 50"
+   clip-rule="evenodd"
+   fill-rule="evenodd"
+   image-rendering="optimizeQuality"
+   shape-rendering="geometricPrecision"
+   height="177.17"
+   width="177.17">
+  <metadata
+     id="metadata1167">
+    <rdf:RDF>
+      <cc:Work
+         rdf:about="">
+        <dc:format>image/svg+xml</dc:format>
+        <dc:type
+           rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+        <dc:title></dc:title>
+      </cc:Work>
+    </rdf:RDF>
+  </metadata>
+  <sodipodi:namedview
+     inkscape:document-rotation="0"
+     showguides="false"
+     inkscape:current-layer="svg1163"
+     inkscape:window-maximized="1"
+     inkscape:window-y="-8"
+     inkscape:window-x="-8"
+     inkscape:cy="109.65623"
+     inkscape:cx="34.095437"
+     inkscape:zoom="3.1933814"
+     showgrid="false"
+     id="namedview1165"
+     inkscape:window-height="1137"
+     inkscape:window-width="1920"
+     inkscape:pageshadow="2"
+     inkscape:pageopacity="0"
+     guidetolerance="10"
+     gridtolerance="10"
+     objecttolerance="10"
+     borderopacity="1"
+     bordercolor="#666666"
+     pagecolor="#ffffff" />
+  <defs
+     id="defs1157">
+    <inkscape:path-effect
+       oposite_fuse="true"
+       fuse_paths="true"
+       discard_orig_path="false"
+       mode="free"
+       is_visible="true"
+       id="path-effect7013"
+       center_point="-58.775696,15.502998"
+       end_point="-37.112887,28.418936"
+       start_point="-80.438505,2.5870606"
+       effect="mirror_symmetry" />
+    <linearGradient
+       inkscape:collect="always"
+       id="linearGradient6441">
+      <stop
+         style="stop-color:#ffffff;stop-opacity:1"
+         offset="0"
+         id="stop6437" />
+      <stop
+         style="stop-color:#b3b3b3;stop-opacity:1"
+         offset="1"
+         id="stop6439" />
+    </linearGradient>
+    <linearGradient
+       gradientUnits="userSpaceOnUse"
+       y2="37.429"
+       x2="77.74"
+       y1="37.552"
+       x1="21.19"
+       id="0">
+      <stop
+         id="stop1152"
+         stop-color="#fff" />
+      <stop
+         id="stop1154"
+         stop-opacity="0"
+         stop-color="#fff"
+         offset="1" />
+    </linearGradient>
+    <linearGradient
+       gradientUnits="userSpaceOnUse"
+       y2="4.3375702"
+       x2="-77.532143"
+       y1="37.56702"
+       x1="-24.988083"
+       id="linearGradient7051"
+       xlink:href="#linearGradient6441"
+       inkscape:collect="always" />
+  </defs>
+  <g
+     id="g7037">
+    <g
+       style="stroke-width:2.70321298;stroke-miterlimit:4;stroke-dasharray:none"
+       transform="matrix(-0.60837538,-0.14918007,0.14918007,-0.60837538,-12.414484,26.315252)"
+       id="g7043">
+      <path
+         sodipodi:nodetypes="ccscscccccccscccccscscc"
+         inkscape:connector-curvature="0"
+         id="path7011"
+         d="m -43.123605,24.607785 6.969175,-4.632689 c 4.132406,-8.680508 0.279219,-12.4367641 -2.433189,-16.2987855 -2.040264,-2.90499868 -3.444397,-4.33752222 -4.411012,-3.54164417 -0.103485,-3.72116613 -2.314112,-3.51386873 -2.973508,-6.01304743 -1.433446,-5.4329069 1.273826,-11.7459989 6.979084,-14.2191979 0,0 -1.512311,3.882956 -0.572227,5.190899 -0.610593,0.370364 -2.184878,1.657205 -2.329773,3.024618 0.130947,4.2573156 12.03911,14.993948 13.774277,26.077117 -1.458322,2.514982 -2.007543,1.98287 -2.784837,6.17596 -1.643076,3.646914 -2.068558,5.33563 -3.300614,6.832798 -0.488806,0.593988 -1.647773,0.683554 -2.451786,1.48633 -0.323924,1.089018 0.148354,2.151176 -0.14177,2.863622 -0.731269,1.795751 -2.014562,2.973018 -4.441578,6.152526 -3.319168,2.677558 -2.58991,2.907709 -4.108987,5.386467 -10.575171,3.743421 -25.682599,-1.627355 -29.490123,0.281741 -1.13405,0.777652 -1.517564,2.774462 -1.553054,3.487718 -1.597625,-0.205106 -4.29447,2.9716 -4.29447,2.9716 -0.537037,-6.19502 3.253074,-11.989514 8.714113,-13.311748 2.512119,-0.608237 3.857271,1.846129 7.180074,0.167806 -0.240541,1.228782 1.210934,1.371828 4.736646,1.785411 4.687222,0.549833 10.500269,2.229056 16.171816,-5.533776 z"
+         style="fill:url(#linearGradient7051);fill-opacity:1;stroke:#1f1a17;stroke-width:2.70321298;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
+      <path
+         sodipodi:nodetypes="ccc"
+         inkscape:connector-curvature="0"
+         id="path7026"
+         d="m -45.996129,-10.153971 -41.387752,8.0912848 12.128797,39.9457572"
+         style="fill:none;stroke:#1f1a17;stroke-width:2.70321298;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
+      <path
+         sodipodi:nodetypes="cc"
+         inkscape:connector-curvature="0"
+         id="path7028"
+         d="M -87.383881,-2.0626862 -33.757224,30.115606"
+         style="fill:none;stroke:#1f1a17;stroke-width:2.70321298;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
+      <path
+         sodipodi:nodetypes="ccccc"
+         inkscape:connector-curvature="0"
+         id="path7030"
+         d="m -33.757224,30.115606 -0.152441,3.622242 9.95057,2.6798 -6.489361,-7.775959 -3.308768,1.473917"
+         style="fill:#1f1a17;fill-opacity:1;stroke:#1f1a17;stroke-width:2.70321298;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
+    </g>
+  </g>
+</svg>
diff --git a/client/public/images/pieces/Orda/wf.svg b/client/public/images/pieces/Orda/wf.svg
new file mode 120000 (symlink)
index 0000000..d5ee68d
--- /dev/null
@@ -0,0 +1 @@
+../Schess/wh.svg
\ No newline at end of file
diff --git a/client/public/images/pieces/Orda/wk.svg b/client/public/images/pieces/Orda/wk.svg
new file mode 100644 (file)
index 0000000..bd3d948
--- /dev/null
@@ -0,0 +1,231 @@
+<?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:xlink="http://www.w3.org/1999/xlink"
+   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+   inkscape:version="1.0 (4035a4fb49, 2020-05-01)"
+   sodipodi:docname="wKhan.svg"
+   id="svg1163"
+   version="1.1"
+   viewBox="0 0 50 50"
+   clip-rule="evenodd"
+   fill-rule="evenodd"
+   image-rendering="optimizeQuality"
+   shape-rendering="geometricPrecision"
+   height="177.17"
+   width="177.17">
+  <metadata
+     id="metadata1167">
+    <rdf:RDF>
+      <cc:Work
+         rdf:about="">
+        <dc:format>image/svg+xml</dc:format>
+        <dc:type
+           rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+        <dc:title></dc:title>
+      </cc:Work>
+    </rdf:RDF>
+  </metadata>
+  <sodipodi:namedview
+     inkscape:document-rotation="0"
+     showguides="false"
+     inkscape:current-layer="svg1163"
+     inkscape:window-maximized="1"
+     inkscape:window-y="-8"
+     inkscape:window-x="-8"
+     inkscape:cy="62.874278"
+     inkscape:cx="105.78439"
+     inkscape:zoom="3.9515223"
+     showgrid="false"
+     id="namedview1165"
+     inkscape:window-height="1137"
+     inkscape:window-width="1920"
+     inkscape:pageshadow="2"
+     inkscape:pageopacity="0"
+     guidetolerance="10"
+     gridtolerance="10"
+     objecttolerance="10"
+     borderopacity="1"
+     bordercolor="#666666"
+     pagecolor="#ffffff" />
+  <defs
+     id="defs1157">
+    <linearGradient
+       inkscape:collect="always"
+       id="linearGradient344">
+      <stop
+         style="stop-color:#f9f9f9;stop-opacity:1"
+         offset="0"
+         id="stop340" />
+      <stop
+         style="stop-color:#e6e6e6;stop-opacity:1"
+         offset="1"
+         id="stop342" />
+    </linearGradient>
+    <linearGradient
+       inkscape:collect="always"
+       id="linearGradient338">
+      <stop
+         style="stop-color:#f9f9f9;stop-opacity:1"
+         offset="0"
+         id="stop334" />
+      <stop
+         style="stop-color:#cccccc;stop-opacity:1"
+         offset="1"
+         id="stop336" />
+    </linearGradient>
+    <linearGradient
+       id="linearGradient15731"
+       inkscape:collect="always">
+      <stop
+         id="stop15729"
+         offset="0"
+         style="stop-color:#ffd42a;stop-opacity:1" />
+      <stop
+         id="stop15727"
+         offset="1"
+         style="stop-color:#806600;stop-opacity:1" />
+    </linearGradient>
+    <linearGradient
+       gradientTransform="translate(-91.535601,53.38202)"
+       id="linearGradient9444"
+       x1="21.129999"
+       y1="37.220001"
+       x2="77.760002"
+       y2="37.469002"
+       gradientUnits="userSpaceOnUse">
+      <stop
+         id="stop9442"
+         stop-opacity="0"
+         stop-color="#fff"
+         offset="0"
+         style="stop-color:#a8a6a5;stop-opacity:1" />
+      <stop
+         offset="1"
+         id="stop9440"
+         stop-color="#fff" />
+    </linearGradient>
+    <inkscape:path-effect
+       oposite_fuse="true"
+       fuse_paths="true"
+       discard_orig_path="false"
+       mode="free"
+       is_visible="true"
+       id="path-effect7013"
+       center_point="-58.775696,15.502998"
+       end_point="-37.112887,28.418936"
+       start_point="-80.438505,2.5870606"
+       effect="mirror_symmetry" />
+    <linearGradient
+       gradientUnits="userSpaceOnUse"
+       y2="37.429"
+       x2="77.74"
+       y1="37.552"
+       x1="21.19"
+       id="0">
+      <stop
+         id="stop1152"
+         stop-color="#fff" />
+      <stop
+         id="stop1154"
+         stop-opacity="0"
+         stop-color="#fff"
+         offset="1" />
+    </linearGradient>
+    <linearGradient
+       gradientUnits="userSpaceOnUse"
+       y2="37.469002"
+       x2="77.760002"
+       y1="37.220001"
+       x1="21.129999"
+       id="0-4"
+       gradientTransform="translate(-91.535601,53.38202)">
+      <stop
+         id="stop8835"
+         stop-color="#fff" />
+      <stop
+         id="stop8837"
+         stop-opacity="0"
+         stop-color="#fff"
+         offset="1" />
+    </linearGradient>
+    <inkscape:path-effect
+       oposite_fuse="false"
+       fuse_paths="true"
+       discard_orig_path="false"
+       mode="free"
+       is_visible="true"
+       id="path-effect4557-0-4"
+       center_point="273.85776,413.92646"
+       end_point="273.50284,477.30227"
+       start_point="274.21267,350.55066"
+       effect="mirror_symmetry" />
+    <linearGradient
+       gradientTransform="matrix(1.1955304,0,0,1.1955304,69.381107,-16.275137)"
+       gradientUnits="userSpaceOnUse"
+       y2="29.826591"
+       x2="-24.59959"
+       y1="29.826591"
+       x1="-49.645481"
+       id="linearGradient17505"
+       xlink:href="#linearGradient338"
+       inkscape:collect="always" />
+    <linearGradient
+       gradientUnits="userSpaceOnUse"
+       y2="92.385574"
+       x2="338.07141"
+       y1="92.385574"
+       x1="293.16513"
+       id="linearGradient17513"
+       xlink:href="#linearGradient15731"
+       inkscape:collect="always" />
+    <linearGradient
+       y2="92.385574"
+       x2="338.07141"
+       y1="92.385574"
+       x1="293.16513"
+       gradientUnits="userSpaceOnUse"
+       id="linearGradient17515"
+       xlink:href="#linearGradient344"
+       inkscape:collect="always" />
+  </defs>
+  <g
+     id="g4698-2"
+     transform="matrix(1.0832527,0,0,1.0832527,-316.89434,-75.076923)"
+     style="fill:url(#linearGradient17513);fill-opacity:1;stroke:#1f1a17;stroke-width:1.5631523;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1">
+    <path
+       sodipodi:nodetypes="ccccc"
+       inkscape:connector-curvature="0"
+       id="path4559-3"
+       d="m 303.60166,106.86928 c 7.66719,2.10131 16.51137,1.72857 23.51399,-0.35626 l -4.92817,-18.880256 c -4.60008,0.196956 -9.92512,0.484373 -13.3113,0.03659 z"
+       style="fill:#1f1a17;fill-opacity:1;stroke:#1f1a17;stroke-width:1.5631523;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
+    <path
+       sodipodi:nodetypes="csccsc"
+       inkscape:original-d="m 275.61681,184.7147 c -30.98719,0.80813 -103.54305,38.73329 -113.10593,62.20704 -42.3113,103.86038 -85.58046,199.79956 -199.829859,294.42238 11.908253,16.00162 83.420666,6.52866 141.407899,62.88268 17.88418,-18.602 69.1607,-234.69942 84.21766,-286.09297 0.27569,-0.94101 87.31577,20.5843 87.31577,15.10156"
+       inkscape:path-effect="#path-effect4557-0-4"
+       inkscape:connector-curvature="0"
+       id="path4555-2"
+       d="m 275.14129,184.72989 c -31.24732,1.17794 -103.11612,38.83736 -112.63041,62.19185 -42.3113,103.86038 -85.58046,199.79956 -199.829859,294.42238 11.908253,16.00162 83.420666,6.52866 141.407899,62.88268 17.88418,-18.602 69.1607,-234.69942 84.21766,-286.09297 0.25562,-0.8725 75.10128,17.56897 85.99865,15.88871 10.87787,1.8022 85.92538,-15.79984 86.17121,-14.92454 14.48042,51.55897 63.33345,268.21712 81.00817,287.01826 58.61475,-55.70104 130.01658,-45.42774 142.10331,-61.29498 C 470.40545,448.92481 428.21351,352.50704 387.06809,248.17929 c -9.25213,-23.45958 -80.69463,-61.92156 -111.9268,-63.4494 z"
+       style="fill:url(#linearGradient17515);fill-opacity:1;stroke:#1f1a17;stroke-width:20.98776438;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+       transform="matrix(0.06852995,0,0,0.08094496,296.89962,61.263195)" />
+    <path
+       style="fill:#d8d8d8;fill-opacity:1;stroke:#1f1a17;stroke-width:1.56315231;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+       d="m 313.70114,76.659247 c 0.72602,-1.679766 1.16307,-2.973341 2.14455,-2.989719 1.017,-0.01697 1.58408,1.476492 2.11082,3.021922 -0.83846,0.823049 -3.69262,0.786403 -4.25537,-0.0322 z"
+       id="path4543-7-7"
+       inkscape:connector-curvature="0"
+       sodipodi:nodetypes="csccc" />
+  </g>
+  <rect
+     ry="5.8048873"
+     y="12.265562"
+     x="11.040617"
+     height="14.235797"
+     width="27.918745"
+     id="rect17497"
+     style="opacity:1;fill:url(#linearGradient17505);fill-opacity:1;stroke:#1f1a17;stroke-width:1.69328895;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;paint-order:normal" />
+</svg>
diff --git a/client/public/images/pieces/Orda/wl.svg b/client/public/images/pieces/Orda/wl.svg
new file mode 100644 (file)
index 0000000..f000df2
--- /dev/null
@@ -0,0 +1,138 @@
+<?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:xlink="http://www.w3.org/1999/xlink"
+   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+   inkscape:version="1.0 (4035a4fb49, 2020-05-01)"
+   sodipodi:docname="wL.svg"
+   id="svg1163"
+   version="1.1"
+   viewBox="0 0 50 50"
+   clip-rule="evenodd"
+   fill-rule="evenodd"
+   image-rendering="optimizeQuality"
+   shape-rendering="geometricPrecision"
+   height="177.17"
+   width="177.17">
+  <metadata
+     id="metadata1167">
+    <rdf:RDF>
+      <cc:Work
+         rdf:about="">
+        <dc:format>image/svg+xml</dc:format>
+        <dc:type
+           rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+        <dc:title></dc:title>
+      </cc:Work>
+    </rdf:RDF>
+  </metadata>
+  <sodipodi:namedview
+     inkscape:document-rotation="0"
+     inkscape:current-layer="svg1163"
+     inkscape:window-maximized="1"
+     inkscape:window-y="-8"
+     inkscape:window-x="-8"
+     inkscape:cy="172.96195"
+     inkscape:cx="-100.07003"
+     inkscape:zoom="1.7261595"
+     showgrid="false"
+     id="namedview1165"
+     inkscape:window-height="1137"
+     inkscape:window-width="1920"
+     inkscape:pageshadow="2"
+     inkscape:pageopacity="0"
+     guidetolerance="10"
+     gridtolerance="10"
+     objecttolerance="10"
+     borderopacity="1"
+     bordercolor="#666666"
+     pagecolor="#ffffff" />
+  <defs
+     id="defs1157">
+    <linearGradient
+       id="linearGradient169"
+       inkscape:collect="always">
+      <stop
+         id="stop165"
+         offset="0"
+         style="stop-color:#ffffff;stop-opacity:1" />
+      <stop
+         id="stop167"
+         offset="1"
+         style="stop-color:#999999;stop-opacity:1" />
+    </linearGradient>
+    <linearGradient
+       inkscape:collect="always"
+       id="linearGradient6441">
+      <stop
+         style="stop-color:#ffffff;stop-opacity:1"
+         offset="0"
+         id="stop6437" />
+      <stop
+         style="stop-color:#b3b3b3;stop-opacity:1"
+         offset="1"
+         id="stop6439" />
+    </linearGradient>
+    <linearGradient
+       gradientUnits="userSpaceOnUse"
+       y2="37.429"
+       x2="77.74"
+       y1="37.552"
+       x1="21.19"
+       id="0">
+      <stop
+         id="stop1152"
+         stop-color="#fff" />
+      <stop
+         id="stop1154"
+         stop-opacity="0"
+         stop-color="#fff"
+         offset="1" />
+    </linearGradient>
+    <linearGradient
+       gradientUnits="userSpaceOnUse"
+       y2="27.899749"
+       x2="92.036465"
+       y1="27.899749"
+       x1="54.37993"
+       id="linearGradient6427"
+       xlink:href="#linearGradient169"
+       inkscape:collect="always" />
+    <linearGradient
+       gradientUnits="userSpaceOnUse"
+       y2="18.40962"
+       x2="45.079731"
+       y1="18.40962"
+       x1="5.4108348"
+       id="linearGradient6435"
+       xlink:href="#linearGradient6441"
+       inkscape:collect="always" />
+  </defs>
+  <g
+     transform="matrix(0.87446347,0,0,1.0645027,-38.025884,-8.5072976)"
+     id="g6417">
+    <path
+       inkscape:connector-curvature="0"
+       style="fill:url(#linearGradient6427);fill-opacity:1;stroke:#1f1a17;stroke-width:1.86823937;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+       d="m 75.119024,43.874689 13.822887,0.589734 C 81.427711,39.083746 72.886976,23.620424 73.246263,10.293252 72.951274,23.647412 65.324765,39.18622 57.621403,44.429572 l 13.769501,-0.600428"
+       id="path3973"
+       sodipodi:nodetypes="ccccc" />
+    <path
+       sodipodi:nodetypes="ccccc"
+       inkscape:connector-curvature="0"
+       style="fill:#1f1a17;fill-opacity:1;stroke:#1f1a17;stroke-width:1.82060385;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+       d="m 71.390926,43.829113 -0.01045,8.207759 c 0.915096,-0.03656 2.830209,-0.01266 3.671608,0.0038 l 0.06694,-8.165983 c -1.206008,-0.09054 -2.434451,-0.135014 -3.728098,-0.04558 z"
+       id="path10325" />
+  </g>
+  <path
+     sodipodi:nodetypes="ccccccc"
+     inkscape:connector-curvature="0"
+     id="path6419"
+     d="M 26.025297,3.3747524 C 22.079635,9.011651 15.019756,13.407269 16.093167,20.95623 19.579066,32.277372 34.070023,30.953274 42.78623,33.207337 l -3.433417,-2.439104 3.956282,-0.139806 C 37.958313,26.760195 25.468994,30.180937 20.535525,19.649065 18.399613,13.309671 24.076279,8.737338 26.025297,3.3747524 Z"
+     style="fill:url(#linearGradient6435);fill-opacity:1;stroke:#1f1a17;stroke-width:1.20167375;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
+</svg>
diff --git a/client/public/images/pieces/Orda/wp.svg b/client/public/images/pieces/Orda/wp.svg
new file mode 120000 (symlink)
index 0000000..3a15545
--- /dev/null
@@ -0,0 +1 @@
+../wp.svg
\ No newline at end of file
index e70b9de..ee13d5e 100644 (file)
@@ -766,6 +766,7 @@ export const ChessRules = class ChessRules {
     const [sizeX, sizeY] = [V.size.x, V.size.y];
     const pawnShiftX = V.PawnSpecs.directions[color];
     const firstRank = (color == "w" ? sizeX - 1 : 0);
+    const forward = (color == 'w' ? -1 : 1);
 
     // Pawn movements in shiftX direction:
     const getPawnMoves = (shiftX) => {
@@ -773,7 +774,7 @@ export const ChessRules = class ChessRules {
       // NOTE: next condition is generally true (no pawn on last rank)
       if (x + shiftX >= 0 && x + shiftX < sizeX) {
         if (this.board[x + shiftX][y] == V.EMPTY) {
-          // One square forward
+          // One square forward (or backward)
           this.addPawnMoves([x, y], [x + shiftX, y], moves, promotions);
           // Next condition because pawns on 1st rank can generally jump
           if (
@@ -784,7 +785,10 @@ export const ChessRules = class ChessRules {
               (color == 'b' && x <= V.PawnSpecs.initShift['b'])
             )
           ) {
-            if (this.board[x + 2 * shiftX][y] == V.EMPTY) {
+            if (
+              shiftX == forward &&
+              this.board[x + 2 * shiftX][y] == V.EMPTY
+            ) {
               // Two squares jump
               moves.push(this.getBasicMove([x, y], [x + 2 * shiftX, y]));
               if (
@@ -811,13 +815,13 @@ export const ChessRules = class ChessRules {
                 );
               }
               if (
-                V.PawnSpecs.captureBackward &&
+                V.PawnSpecs.captureBackward && shiftX == forward &&
                 x - shiftX >= 0 && x - shiftX < V.size.x &&
                 this.board[x - shiftX][y + shiftY] != V.EMPTY &&
                 this.canTake([x, y], [x - shiftX, y + shiftY])
               ) {
                 this.addPawnMoves(
-                  [x, y], [x + shiftX, y + shiftY],
+                  [x, y], [x - shiftX, y + shiftY],
                   moves, promotions
                 );
               }
index 0e39df7..78e112c 100644 (file)
@@ -157,6 +157,7 @@ export const translations = {
 
   // Variants boxes:
   "64 pieces on the board": "64 pieces on the board",
+  "A Clockwork Orange": "A Clockwork Orange",
   "A pawns cloud": "A pawns cloud",
   "A wizard in the corner": "A wizard in the corner",
   "Absorb powers": "Absorb powers",
@@ -210,10 +211,12 @@ export const translations = {
   "Mate the knight": "Mate the knight",
   "Meet the Mammoth": "Meet the Mammoth",
   "Middle battle": "Middle battle",
-  "Mongolian Horde": "Mongolian Horde",
+  "Mongolian Horde (v1)": "Mongolian Horde (v1)",
+  "Mongolian Horde (v2)": "Mongolian Horde (v2)",
   "Move like a knight (v1)": "Move like a knight (v1)",
   "Move like a knight (v2)": "Move like a knight (v2)",
   "Move under cover": "Move under cover",
+  "Moving forward": "Moving forward",
   "Neverending rows": "Neverending rows",
   "No-check mode": "No-check mode",
   "Non-conformism and utopia": "Non-conformism and utopia",
index 4388c5a..0c7fca0 100644 (file)
@@ -157,6 +157,7 @@ export const translations = {
 
   // Variants boxes:
   "64 pieces on the board": "64 piezas en el tablero",
+  "A Clockwork Orange": "Naranja Mecánica",
   "A pawns cloud": "Une nube de peones",
   "A wizard in the corner": "Un mago en la esquina",
   "Absorb powers": "Absorber poderes",
@@ -210,10 +211,12 @@ export const translations = {
   "Mate the knight": "Matar el caballo",
   "Meet the Mammoth": "Conoce al Mamut",
   "Middle battle": "Batalla media",
-  "Mongolian Horde": "Horda mongol",
+  "Mongolian Horde (v1)": "Horda mongol (v1)",
+  "Mongolian Horde (v2)": "Horda mongol (v2)",
   "Move like a knight (v1)": "Moverse como un caballo (v1)",
   "Move like a knight (v2)": "Moverse como un caballo (v2)",
   "Move under cover": "Ir bajo cubierta",
+  "Moving forward": "Ir adelante",
   "Neverending rows": "Filas interminables",
   "No-check mode": "Modo sin jaque",
   "Non-conformism and utopia": "No-conformismo y utopía",
index 77e94e6..e6b1c48 100644 (file)
@@ -157,6 +157,7 @@ export const translations = {
 
   // Variants boxes:
   "64 pieces on the board": "64 pièces sur l'échiquier",
+  "A Clockwork Orange": "Orange Mécanique",
   "A pawns cloud": "Une nuée de pions",
   "A wizard in the corner": "Un sorcier dans le coin",
   "Absorb powers": "Absorber les pouvoirs",
@@ -210,10 +211,12 @@ export const translations = {
   "Mate the knight": "Matez le cavalier",
   "Meet the Mammoth": "Rencontrez le Mammouth",
   "Middle battle": "Bataille du milieu",
-  "Mongolian Horde": "Horde mongole",
+  "Mongolian Horde (v1)": "Horde mongole (v1)",
+  "Mongolian Horde (v2)": "Horde mongole (v2)",
   "Move like a knight (v1)": "Bouger comme un cavalier (v1)",
   "Move like a knight (v2)": "Bouger comme un cavalier (v2)",
   "Move under cover": "Avancez Ã  couvert",
+  "Moving forward": "Aller de l'avant",
   "Neverending rows": "Rangées sans fin",
   "No-check mode": "Mode sans Ã©chec",
   "Non-conformism and utopia": "Non-conformisme et utopie",
diff --git a/client/src/translations/rules/Clorange/en.pug b/client/src/translations/rules/Clorange/en.pug
new file mode 100644 (file)
index 0000000..3a33838
--- /dev/null
@@ -0,0 +1,2 @@
+p.boxed
+  | TODO
diff --git a/client/src/translations/rules/Clorange/es.pug b/client/src/translations/rules/Clorange/es.pug
new file mode 100644 (file)
index 0000000..3a33838
--- /dev/null
@@ -0,0 +1,2 @@
+p.boxed
+  | TODO
diff --git a/client/src/translations/rules/Clorange/fr.pug b/client/src/translations/rules/Clorange/fr.pug
new file mode 100644 (file)
index 0000000..3a33838
--- /dev/null
@@ -0,0 +1,2 @@
+p.boxed
+  | TODO
diff --git a/client/src/translations/rules/Doubleorda/en.pug b/client/src/translations/rules/Doubleorda/en.pug
new file mode 100644 (file)
index 0000000..62ef153
--- /dev/null
@@ -0,0 +1,23 @@
+p.boxed
+  | Pieces move generally like a knight, and capture differently.
+
+figure.diagram-container
+  .diagram
+    | fen:lhafkahl/8/pppppppp/8/8/PPPPPPPP/8/LHAFKAHL:
+  figcaption Deterministic initial position
+
+p
+  | Most pieces move and capture as described in 
+  a(href="/#/variants/Orda") Orda
+  | . They all belong to the Mongolian army: let's say a rebellion occured :)
+
+p The new piece is a falcon, moving like a queen and capturing like a knight.
+
+figure.diagram-container
+  .diagram
+    | fen:8/1P6/8/3F2p1/3Pp3/2p1p3/8/8 d6,d7,d8,a5,b5,c5,a2,b3,c4,e5,f5,c6,e6,f7,g8,c3,e3:
+  figcaption Movements of the falcon
+
+p.
+  Same as in Orda, win by checkmate or "campmate" when the king reaches
+  the last rank.
diff --git a/client/src/translations/rules/Doubleorda/es.pug b/client/src/translations/rules/Doubleorda/es.pug
new file mode 100644 (file)
index 0000000..a6141b2
--- /dev/null
@@ -0,0 +1,27 @@
+p.boxed
+  | Las piezas generalmente se mueven como un caballo,
+  | y capturan de manera diferente.
+
+figure.diagram-container
+  .diagram
+    | fen:lhaykahl/8/pppppppp/8/8/PPPPPPPP/8/LHAYKAHL:
+  figcaption Posición determinista inicial
+
+p
+  | Las piezas se mueven y capturan como se describe en 
+  a(href="/#/variants/Orda") Orda
+  | . Todas pertenecen al ejército mongol: digamos que una rebelión
+  | tuvo lugar :)
+
+p.
+  La nueva pieza es un halcón que se mueve como una dama,
+  y captura como un caballo.
+
+figure.diagram-container
+  .diagram
+    | fen:8/1P6/8/3F2p1/3Pp3/2p1p3/8/8 d6,d7,d8,a5,b5,c5,a2,b3,c4,e5,f5,c6,e6,f7,g8,c3,e3:
+  figcaption Movimientos de halcón
+
+p.
+  En cuanto a Orda, gana por jaque mate o "campmate" cuando el rey
+  llega a la Ãºltima fila.
diff --git a/client/src/translations/rules/Doubleorda/fr.pug b/client/src/translations/rules/Doubleorda/fr.pug
new file mode 100644 (file)
index 0000000..7e25792
--- /dev/null
@@ -0,0 +1,27 @@
+p.boxed
+  | Les pièces se déplacent en général comme un cavalier,
+  | et capturent différemment.
+
+figure.diagram-container
+  .diagram
+    | fen:lhaykahl/8/pppppppp/8/8/PPPPPPPP/8/LHAYKAHL:
+  figcaption Position initiale déterministe
+
+p
+  | Les pièces se déplacent et capturent comme décrit dans 
+  a(href="/#/variants/Orda") Orda
+  | . Elles appartiennent toutes Ã  l'armée mongole : disons qu'une rébellion
+  | a eu lieu :)
+
+p.
+  La nouvelle pièce est un faucon, se déplaçant comme une dame
+  et capturant comme un cavalier.
+
+figure.diagram-container
+  .diagram
+    | fen:8/1P6/8/3F2p1/3Pp3/2p1p3/8/8 d6,d7,d8,a5,b5,c5,a2,b3,c4,e5,f5,c6,e6,f7,g8,c3,e3:
+  figcaption Déplacements du faucon
+
+p.
+  De même que pour Orda, gagnez par Ã©chec et mat ou "campmate" quand le roi
+  atteint la dernière rangée.
diff --git a/client/src/translations/rules/Forward/en.pug b/client/src/translations/rules/Forward/en.pug
new file mode 100644 (file)
index 0000000..223cd3e
--- /dev/null
@@ -0,0 +1,27 @@
+p.boxed
+  | Pieces only move forward,
+  | until they reach the last rank where they promote.
+
+p.
+  Knights and bishops must move strictly forward, as in Draughts game.
+  Rooks, queen and king can also move laterally, on the same rank.
+  Pawns move as usual and are promoted into bidirectional pawns,
+  able to move and capture both ways.
+
+figure.diagram-container
+  .diagram.diag12
+    | fen:1qnrkrbb/pppppp1p/1n4p1/8/3B1P2/8/PPPPP1PP/RBKQNR1N c5,b6,e5,f6,g7,h8:
+  .diagram.diag22
+    | fen:1qnrkrbC/pppppp1p/1n4p1/8/5P2/8/PPPPP1PP/RBKQNR1N:
+  figcaption Before and after 1.Bxh8
+
+p Promoted pieces appear in yellow (for white) and red (for black).
+
+h3 Source
+
+p
+  a(href="https://www.chessvariants.com/diffmove.dir/checkers.html")
+    | Checkers Chess
+  | &nbsp;on chessvariants.com.
+
+p Inventor: Hans Multhopp (1974)
diff --git a/client/src/translations/rules/Forward/es.pug b/client/src/translations/rules/Forward/es.pug
new file mode 100644 (file)
index 0000000..1207e9a
--- /dev/null
@@ -0,0 +1,32 @@
+p.boxed
+  | Las piezas siempre avanzan.
+  | Una vez que se alcanza la Ãºltima fila, son promovidos.
+
+p.
+  Los caballos y los alfiles deben avanzar estrictamente,
+  como las damas.
+  Las torres, la dama y el rey también pueden moverse lateralmente, en el
+  misma fila.
+  Los peones se mueven como de costumbre y son promovidos a peones
+  bidireccional, capaz de moverse y capturar en ambas direcciones.
+
+figure.diagram-container
+  .diagram.diag12
+    | fen:1qnrkrbb/pppppp1p/1n4p1/8/3B1P2/8/PPPPP1PP/RBKQNR1N c5,b6,e5,f6,g7,h8:
+  .diagram.diag22
+    | fen:1qnrkrbC/pppppp1p/1n4p1/8/5P2/8/PPPPP1PP/RBKQNR1N:
+  figcaption Antes y después 1.Bxh8
+
+p.
+  Las piezas promocionadas aparecen en amarillo (para las blancas)
+  y en rojo (para las negras).
+
+h3 Fuente
+
+p
+  | La 
+  a(href="https://www.chessvariants.com/diffmove.dir/checkers.html")
+    | variante Checkers
+  | &nbsp;en chessvariants.com.
+
+p Inventor: Hans Multhopp (1974)
diff --git a/client/src/translations/rules/Forward/fr.pug b/client/src/translations/rules/Forward/fr.pug
new file mode 100644 (file)
index 0000000..09024a9
--- /dev/null
@@ -0,0 +1,32 @@
+p.boxed
+  | Les pièces se déplacent toujours vers l'avant.
+  | Une fois la dernière rangée atteinte, elles sont promues.
+
+p.
+  Les cavaliers et les fous doivent se déplacer strictement en avant,
+  comme aux Dames.
+  Les tours, la dame et le roi peuvent aussi Ã©voluer latéralement, sur la
+  même rangée.
+  Les pions se déplacent comme d'habitude et sont promus en des pions
+  bidirectionnels, pouvant se déplacer et capturer dans les deux sens.
+
+figure.diagram-container
+  .diagram.diag12
+    | fen:1qnrkrbb/pppppp1p/1n4p1/8/3B1P2/8/PPPPP1PP/RBKQNR1N c5,b6,e5,f6,g7,h8:
+  .diagram.diag22
+    | fen:1qnrkrbC/pppppp1p/1n4p1/8/5P2/8/PPPPP1PP/RBKQNR1N:
+  figcaption Before and after 1.Bxh8
+
+p.
+  Les pièces promues apparaissent en jaune (pour les blancs)
+  et en rouge (pour les noirs)
+
+h3 Source
+
+p
+  | La 
+  a(href="https://www.chessvariants.com/diffmove.dir/checkers.html")
+    | variante Checkers
+  | &nbsp;sur chessvariants.com.
+
+p Inventeur : Hans Multhopp (1974)
index a7ddca7..1e2aed2 100644 (file)
@@ -7,6 +7,7 @@ p.
   that is to say squares attacked by more friendly pieces than enemy pieces.
   The king in check may only move as in orthodox chess, but "rampage" moves
   of other pieces are allowed to cover the check.
+  Pawns cannot promote with a rampage move.
 
 p.
   Attacks on the same row, file or diagonal are cumulative. So,
index 4fedc77..6f14382 100644 (file)
@@ -8,6 +8,7 @@ p.
   mismo lado que las piezas opuestas.
   El rey en jaque solo puede hacer movimientos normales, pero las jugadas
   "rampage" de las otras piezas pueden contrarrestar el jaque.
+  Los peones no pueden ser promovidos a través de un movimiento "rampage".
 
 p.
   Los ataques a la misma columna, fila o diagonal son acumulativos. Entonces
index d0a57f5..3319a64 100644 (file)
@@ -8,6 +8,7 @@ p.
   même camp que de pièces adverses.
   Le roi en Ã©chec ne peut effectuer que des coups normaux, mais les coups
   "rampage" des autres pièces sont autorisés pour parer l'échec.
+  Les pions ne peuvent pas Ãªtre promus via un coup "rampage".
 
 p.
   Les attaques sur la même colonne, rangée ou diagonale se cumulent. Ainsi,
@@ -19,6 +20,7 @@ figure.diagram-container
     | fen:k7/p7/2n1r3/8/8/8/4R2P/4Q2K e5:
   figcaption Pas de coups de repositionnement vers e5.
 
+
 h3 Source
 
 p
diff --git a/client/src/variants/Clorange.js b/client/src/variants/Clorange.js
new file mode 100644 (file)
index 0000000..a999131
--- /dev/null
@@ -0,0 +1,239 @@
+import { ChessRules, PiPo, Move } from "@/base_rules";
+import { ArrayFun } from "@/utils/array";
+
+export class ClorangeRules extends ChessRules {
+  static get PawnSpecs() {
+    return Object.assign(
+      {},
+      ChessRules.PawnSpecs,
+      // TODO: pawns reaching last rank promote normally? Seems better
+      { promotions: [V.PAWN] }
+    );
+  }
+
+  static IsGoodFen(fen) {
+    if (!ChessRules.IsGoodFen(fen)) return false;
+    const fenParsed = V.ParseFen(fen);
+    // 5) Check reserves
+    if (!fenParsed.reserve || !fenParsed.reserve.match(/^[0-9]{20,20}$/))
+      return false;
+    return true;
+  }
+
+  static ParseFen(fen) {
+    const fenParts = fen.split(" ");
+    return Object.assign(
+      ChessRules.ParseFen(fen),
+      { reserve: fenParts[5] }
+    );
+  }
+
+  static GenRandInitFen(randomness) {
+    // Capturing and non-capturing reserves:
+    return ChessRules.GenRandInitFen(randomness) + " 00000000000000000000";
+  }
+
+  getFen() {
+    return super.getFen() + " " + this.getReserveFen();
+  }
+
+  getFenForRepeat() {
+    return super.getFenForRepeat() + "_" + this.getReserveFen();
+  }
+
+  getReserveFen() {
+    let counts = new Array(10);
+    for (
+      let i = 0;
+      i < V.PIECES.length - 1;
+      i++ //-1: no king reserve
+    ) {
+      // TODO: adapt
+      counts[i] = this.reserve["w"][V.PIECES[i]];
+      counts[5 + i] = this.reserve["b"][V.PIECES[i]];
+    }
+    return counts.join("");
+  }
+
+  setOtherVariables(fen) {
+    super.setOtherVariables(fen);
+    const fenParsed = V.ParseFen(fen);
+    // Also init reserves (used by the interface to show landable pieces)
+    // TODO: adapt
+    this.reserve = {
+      w: {
+        [V.PAWN]: parseInt(fenParsed.reserve[0]),
+        [V.ROOK]: parseInt(fenParsed.reserve[1]),
+        [V.KNIGHT]: parseInt(fenParsed.reserve[2]),
+        [V.BISHOP]: parseInt(fenParsed.reserve[3]),
+        [V.QUEEN]: parseInt(fenParsed.reserve[4])
+      },
+      b: {
+        [V.PAWN]: parseInt(fenParsed.reserve[5]),
+        [V.ROOK]: parseInt(fenParsed.reserve[6]),
+        [V.KNIGHT]: parseInt(fenParsed.reserve[7]),
+        [V.BISHOP]: parseInt(fenParsed.reserve[8]),
+        [V.QUEEN]: parseInt(fenParsed.reserve[9])
+      }
+    };
+  }
+
+  getColor(i, j) {
+    if (i >= V.size.x) return i == V.size.x ? "w" : "b";
+    return this.board[i][j].charAt(0);
+  }
+
+  getPiece(i, j) {
+    if (i >= V.size.x) return V.RESERVE_PIECES[j];
+    return this.board[i][j].charAt(1);
+  }
+
+  getReservePpath(index, color) {
+    return color + V.RESERVE_PIECES[index];
+  }
+
+  static get NON_VIOLENT() {
+    return ['s', 'u', 'o', 'c', 't', 'l'];
+  }
+
+  // Ordering on reserve pieces
+  static get RESERVE_PIECES() {
+    return ChessRules.PIECES.concat(V.NON_VIOLENT);
+  }
+
+  getReserveMoves([x, y]) {
+    const color = this.turn;
+    const p = V.RESERVE_PIECES[y];
+    if (this.reserve[color][p] == 0) return [];
+    let moves = [];
+    const pawnShift = p == V.PAWN ? 1 : 0;
+    for (let i = pawnShift; i < V.size.x - pawnShift; i++) {
+      for (let j = 0; j < V.size.y; j++) {
+        if (this.board[i][j] == V.EMPTY) {
+          let mv = new Move({
+            appear: [
+              new PiPo({
+                x: i,
+                y: j,
+                c: color,
+                p: p
+              })
+            ],
+            vanish: [],
+            start: { x: x, y: y }, //a bit artificial...
+            end: { x: i, y: j }
+          });
+          moves.push(mv);
+        }
+      }
+    }
+    return moves;
+  }
+
+  // TODO: adapt all below:
+  getPotentialMovesFrom([x, y]) {
+    if (x >= V.size.x) {
+      // Reserves, outside of board: x == sizeX(+1)
+      return this.getReserveMoves([x, y]);
+    }
+    // Standard moves
+    return super.getPotentialMovesFrom([x, y]);
+  }
+
+  getPotentialPawnMoves([x, y]) {
+    
+    let moves = super.getPotentialPawnMoves([x, y]);
+    // Remove pawns on 8th rank ("fallen"):
+    const color = this.turn;
+    const lastRank = (color == "w" ? 0 : V.size.x - 1);
+    moves.forEach(m => {
+      if (m.appear[0].x == lastRank) m.appear.pop();
+    });
+    return moves;
+  }
+
+  getAllValidMoves() {
+    let moves = super.getAllPotentialMoves();
+    const color = this.turn;
+    for (let i = 0; i < V.RESERVE_PIECES.length; i++) {
+      moves = moves.concat(
+        this.getReserveMoves([V.size.x + (color == "w" ? 0 : 1), i])
+      );
+    }
+    return this.filterValid(moves);
+  }
+
+  atLeastOneMove() {
+    if (!super.atLeastOneMove()) {
+      // Search one reserve move
+      for (let i = 0; i < V.RESERVE_PIECES.length; i++) {
+        let moves = this.filterValid(
+          this.getReserveMoves([V.size.x + (this.turn == "w" ? 0 : 1), i])
+        );
+        if (moves.length > 0) return true;
+      }
+      return false;
+    }
+    return true;
+  }
+
+  canTake([x1, y1], [x2, y2]) {
+    // Self-captures allowed, except for the king:
+    return this.getPiece(x2, y2) != V.KING;
+  }
+
+  prePlay(move) {
+    super.prePlay(move);
+    // Skip castle:
+    if (move.vanish.length == 2 && move.appear.length == 2) return;
+    const color = this.turn;
+    if (move.vanish.length == 0) this.reserve[color][move.appear[0].p]--;
+    else if (move.vanish.length == 2 && move.vanish[1].c == color)
+      // Self-capture
+      this.reserve[color][move.vanish[1].p]++;
+  }
+
+  postUndo(move) {
+    super.postUndo(move);
+    if (move.vanish.length == 2 && move.appear.length == 2) return;
+    const color = this.turn;
+    if (move.vanish.length == 0) this.reserve[color][move.appear[0].p]++;
+    else if (move.vanish.length == 2 && move.vanish[1].c == color)
+      this.reserve[color][move.vanish[1].p]--;
+  }
+
+  static get SEARCH_DEPTH() {
+    return 2;
+  }
+
+  evalPosition() {
+    let evaluation = super.evalPosition();
+    // Add reserves:
+    for (let i = 0; i < V.RESERVE_PIECES.length; i++) {
+      const p = V.RESERVE_PIECES[i];
+      evaluation += this.reserve["w"][p] * V.VALUES[p];
+      evaluation -= this.reserve["b"][p] * V.VALUES[p];
+    }
+    return evaluation;
+  }
+
+  getNotation(move) {
+    const finalSquare = V.CoordsToSquare(move.end);
+    if (move.vanish.length > 0) {
+      if (move.appear.length > 0) {
+        // Standard move
+        return super.getNotation(move);
+      } else {
+        // Pawn fallen: capturing or not
+        let res = "";
+        if (move.vanish.length == 2)
+          res += V.CoordToColumn(move.start.y) + "x";
+        return res + finalSquare;
+      }
+    }
+    // Rebirth:
+    const piece =
+      move.appear[0].p != V.PAWN ? move.appear[0].p.toUpperCase() : "";
+    return piece + "@" + V.CoordsToSquare(move.end);
+  }
+};
diff --git a/client/src/variants/Doubleorda.js b/client/src/variants/Doubleorda.js
new file mode 100644 (file)
index 0000000..290ab23
--- /dev/null
@@ -0,0 +1,148 @@
+import { ChessRules } from "@/base_rules";
+import { OrdaRules } from "@/variants/Orda";
+import { ArrayFun } from "@/utils/array";
+import { randInt } from "@/utils/alea";
+
+export class DoubleordaRules extends OrdaRules {
+  static get PawnSpecs() {
+    return Object.assign(
+      {},
+      ChessRules.PawnSpecs,
+      { promotions: [V.LANCER, V.ARCHER, V.KHESHIG, V.FALCON] }
+    );
+  }
+
+  static get HasFlags() {
+    return false;
+  }
+
+  static get HasEnpassant() {
+    return false;
+  }
+
+  getPpath(b) {
+    return "Orda/" + b;
+  }
+
+  static GenRandInitFen(randomness) {
+    if (randomness == 0)
+      return "lhafkahl/8/pppppppp/8/8/PPPPPPPP/8/LHAFKAHL w 0 ah -";
+
+    let pieces = { w: new Array(8), b: new Array(8) };
+    // Shuffle pieces on first (and last rank if randomness == 2)
+    for (let c of ["w", "b"]) {
+      if (c == 'b' && randomness == 1) {
+        pieces['b'] = pieces['w'];
+        break;
+      }
+
+      let positions = ArrayFun.range(8);
+
+      let randIndex = 2 * randInt(4);
+      const bishop1Pos = positions[randIndex];
+      let randIndex_tmp = 2 * randInt(4) + 1;
+      const bishop2Pos = positions[randIndex_tmp];
+      positions.splice(Math.max(randIndex, randIndex_tmp), 1);
+      positions.splice(Math.min(randIndex, randIndex_tmp), 1);
+
+      randIndex = randInt(6);
+      const knight1Pos = positions[randIndex];
+      positions.splice(randIndex, 1);
+      randIndex = randInt(5);
+      const knight2Pos = positions[randIndex];
+      positions.splice(randIndex, 1);
+
+      randIndex = randInt(4);
+      const queenPos = positions[randIndex];
+      positions.splice(randIndex, 1);
+
+      const rook1Pos = positions[0];
+      const kingPos = positions[1];
+      const rook2Pos = positions[2];
+
+      pieces[c][rook1Pos] = "l";
+      pieces[c][knight1Pos] = "h";
+      pieces[c][bishop1Pos] = "a";
+      pieces[c][queenPos] = "f";
+      pieces[c][kingPos] = "k";
+      pieces[c][bishop2Pos] = "a";
+      pieces[c][knight2Pos] = "h";
+      pieces[c][rook2Pos] = "l";
+    }
+    return (
+      pieces["b"].join("") +
+      "/8/pppppppp/8/8/PPPPPPPP/8/" +
+      pieces["w"].join("").toUpperCase() +
+      " w 0"
+    );
+  }
+
+  static get FALCON() {
+    return 'f';
+  }
+
+  static get PIECES() {
+    return [V.LANCER, V.ARCHER, V.KHESHIG, V.FALCON, V.KING];
+  }
+
+  getPotentialMovesFrom(sq) {
+    switch (this.getPiece(sq[0], sq[1])) {
+      case V.PAWN:
+        return super.getPotentialPawnMoves(sq);
+      case V.LANCER:
+        return super.getPotentialLancerMoves(sq);
+      case V.ARCHER:
+        return super.getPotentialArcherMoves(sq);
+      case V.KHESHIG:
+        return super.getPotentialKheshigMoves(sq);
+      case V.FALCON:
+        return this.getPotentialFalconMoves(sq);
+      case V.KING:
+        return super.getPotentialKingMoves(sq)
+    }
+    return []; //never reached
+  }
+
+  getPotentialFalconMoves(sq) {
+    const onlyMoves = this.getSlideNJumpMoves(
+      sq,
+      V.steps[V.ROOK].concat(V.steps[V.BISHOP]),
+      null,
+      { onlyMove: true }
+    );
+    const onlyTakes = this.getSlideNJumpMoves(
+      sq,
+      V.steps[V.KNIGHT],
+      "oneStep",
+      { onlyTake: true }
+    );
+    return onlyMoves.concat(onlyTakes);
+  }
+
+  isAttacked(sq, color) {
+    return (
+      super.isAttackedByPawn(sq, color) ||
+      super.isAttackedByLancer(sq, color) ||
+      super.isAttackedByKheshig(sq, color) ||
+      super.isAttackedByArcher(sq, color) ||
+      this.isAttackedByFalcon(sq, color) ||
+      super.isAttackedByKing(sq, color)
+    );
+  }
+
+  isAttackedByFalcon(sq, color) {
+    return this.isAttackedBySlideNJump(
+      sq, color, V.FALCON, V.steps[V.KNIGHT], "oneStep");
+  }
+
+  static get VALUES() {
+    return {
+      p: 1,
+      f: 7,
+      a: 4,
+      h: 7,
+      l: 4,
+      k: 1000
+    };
+  }
+};
diff --git a/client/src/variants/Forward.js b/client/src/variants/Forward.js
new file mode 100644 (file)
index 0000000..5c5b641
--- /dev/null
@@ -0,0 +1,143 @@
+import { ChessRules } from "@/base_rules";
+
+export class ForwardRules extends ChessRules {
+  static get PawnSpecs() {
+    return Object.assign(
+      {},
+      ChessRules.PawnSpecs,
+      {
+        bidirectional: true,
+        captureBackward: true,
+        promotions: [V.PAWN]
+      }
+    );
+  }
+
+  static get PROMOTED() {
+    return ['s', 'u', 'o', 'c', 't', 'l'];
+  }
+
+  static get PIECES() {
+    return ChessRules.PIECES.concat(V.PROMOTED);
+  }
+
+  getPpath(b) {
+    return (V.PROMOTED.includes(b[1]) ? "Forward/" : "") + b;
+  }
+
+  scanKings(fen) {
+    this.INIT_COL_KING = { w: -1, b: -1 };
+    // Squares of white and black king:
+    this.kingPos = { w: [-1, -1], b: [-1, -1] };
+    const fenRows = V.ParseFen(fen).position.split("/");
+    const startRow = { 'w': V.size.x - 1, 'b': 0 };
+    for (let i = 0; i < fenRows.length; i++) {
+      let k = 0; //column index on board
+      for (let j = 0; j < fenRows[i].length; j++) {
+        switch (fenRows[i].charAt(j)) {
+          case "k":
+          case "l":
+            this.kingPos["b"] = [i, k];
+            this.INIT_COL_KING["b"] = k;
+            break;
+          case "K":
+          case "L":
+            this.kingPos["w"] = [i, k];
+            this.INIT_COL_KING["w"] = k;
+            break;
+          default: {
+            const num = parseInt(fenRows[i].charAt(j));
+            if (!isNaN(num)) k += num - 1;
+          }
+        }
+        k++;
+      }
+    }
+  }
+
+  getPotentialMovesFrom(sq) {
+    const piece = this.getPiece(sq[0], sq[1]);
+    if (V.PROMOTED.includes(piece)) {
+      switch (piece) {
+        case 's':
+          return (
+            super.getPotentialPawnMoves(sq)
+            // Promoted pawns back on initial rank don't jump 2 squares:
+            .filter(m => Math.abs(m.end.x - m.start.x) == 1)
+          );
+        case 'u': return super.getPotentialRookMoves(sq);
+        case 'o': return super.getPotentialKnightMoves(sq);
+        case 'c': return super.getPotentialBishopMoves(sq);
+        case 't': return super.getPotentialQueenMoves(sq);
+        case 'l': return super.getPotentialKingMoves(sq);
+      }
+    }
+    // Unpromoted piece: only go forward
+    const color = this.turn;
+    let moves =
+      super.getPotentialMovesFrom(sq)
+      .filter(m => {
+        const delta = m.end.x - m.start.x;
+        return ((color == 'w' && delta <= 0) || (color == 'b' && delta >= 0));
+      });
+    // Apply promotions:
+    const lastRank = (color == 'w' ? 0 : 7);
+    moves.forEach(m => {
+      if (m.end.x == lastRank) {
+        const pIdx = ChessRules.PIECES.findIndex(p => p == m.appear[0].p);
+        m.appear[0].p = V.PROMOTED[pIdx];
+      }
+    });
+    return moves;
+  }
+
+  isAttackedBySlideNJump([x, y], color, piece, steps, oneStep) {
+    const pIdx = ChessRules.PIECES.findIndex(p => p == piece);
+    const ppiece = V.PROMOTED[pIdx];
+    const forward = (color == 'w' ? -1 : 1);
+    for (let step of steps) {
+      let rx = x + step[0],
+          ry = y + step[1];
+      while (V.OnBoard(rx, ry) && this.board[rx][ry] == V.EMPTY && !oneStep) {
+        rx += step[0];
+        ry += step[1];
+      }
+      if (V.OnBoard(rx, ry) && this.getColor(rx, ry) == color) {
+        const pieceR = this.getPiece(rx, ry);
+        if (
+          pieceR == ppiece ||
+          (pieceR == piece && (step[0] == 0 || -step[0] == forward))
+        ) {
+          return true;
+        }
+      }
+    }
+    return false;
+  }
+
+  postPlay(move) {
+    super.postPlay(move);
+    if (move.appear[0].p == "l")
+      this.kingPos[move.appear[0].c] = [move.appear[0].x, move.appear[0].y];
+  }
+
+  postUndo(move) {
+    super.postUndo(move);
+    if (move.appear[0].p == "l")
+      this.kingPos[this.turn] = [move.start.x, move.start.y];
+  }
+
+  static get VALUES() {
+    return Object.assign(
+      {
+        s: 2,
+        u: 8,
+        o: 5,
+        c: 5,
+        t: 15,
+        l: 1500
+      },
+      ChessRules.VALUES
+    );
+  }
+};
index afb736a..1ff4898 100644 (file)
@@ -143,7 +143,7 @@ export class OrdaRules extends ChessRules {
       let j = y + step[1];
       while (V.OnBoard(i, j) && this.board[i][j] == V.EMPTY) {
         if (!options.onlyTake) moves.push(this.getBasicMove([x, y], [i, j]));
-        if (oneStep) continue outerLoop;
+        if (!!oneStep) continue outerLoop;
         i += step[0];
         j += step[1];
       }
index 2fe96db..79b8b95 100644 (file)
@@ -62,13 +62,19 @@ export class RampageRules extends ChessRules {
       return moves;
     // Remember current final squares to not add moves twice:
     const destinations = {};
+    const lastRank = (color == 'w' ? 0 : 7);
+    const piece = this.getPiece(x, y);
     moves.forEach(m => destinations[m.end.x + "_" + m.end.y] = true);
     for (let i=0; i<8; i++) {
       for (let j=0; j<8; j++) {
         if (this.board[i][j] == V.EMPTY && !destinations[i + "_" + j]) {
           const sa = this.sumAttacks([i, j]);
-          if ((color == 'w' && sa > 0) || (color == 'b' && sa < 0))
+          if (
+            ((color == 'w' && sa > 0) || (color == 'b' && sa < 0)) &&
+            (piece != V.PAWN || i != lastRank)
+          ) {
             moves.push(this.getBasicMove([x, y], [i, j]));
+          }
         }
       }
     }
index 229c7b3..b940d0a 100644 (file)
@@ -76,6 +76,7 @@ export class SwitchingRules extends ChessRules {
         this.castleFlags[a.c] = [V.size.y, V.size.y];
       }
     });
+    const firstRank = (move.vanish[0].c == 'w' ? 7 : 0);
     for (let coords of [move.start, move.end]) {
       if (
         Object.keys(firstRank).includes(coords.x) &&
@@ -106,7 +107,7 @@ export class SwitchingRules extends ChessRules {
     return super.getAllPotentialMoves().filter(m => {
       return (
         m.appear.length == 1 ||
-        (move.appear[0].p == V.KING && move.appear[1].p == V.ROOK) ||
+        (m.appear[0].p == V.KING && m.appear[1].p == V.ROOK) ||
         (m.appear[1].x <= m.vanish[1].x && m.appear[1].y <= m.vanish[1].y)
       );
     });
index 2959557..703297a 100644 (file)
@@ -33,6 +33,7 @@ insert or ignore into Variants (name, description) values
   ('Checkless', 'No-check mode'),
   ('Chess960', 'Standard rules'),
   ('Circular', 'Run forward'),
+  ('Clorange', 'A Clockwork Orange'),
   ('Colorbound', 'The colorbound clobberers'),
   ('Coregal', 'Two royal pieces'),
   ('Coronation', 'Long live the Queen'),
@@ -42,11 +43,13 @@ insert or ignore into Variants (name, description) values
   ('Doublearmy', '64 pieces on the board'),
   ('Doublemove1', 'Double moves (v1)'),
   ('Doublemove2', 'Double moves (v2)'),
+  ('Doubleorda', 'Mongolian Horde (v2)'),
   ('Dynamo', 'Push and pull'),
   ('Eightpieces', 'Each piece is unique'),
   ('Enpassant', 'Capture en passant'),
   ('Extinction', 'Capture all of a kind'),
   ('Football', 'Score a goal'),
+  ('Forward', 'Moving forward'),
   ('Freecapture', 'Capture both colors'),
   ('Grand', 'Big board'),
   ('Grasshopper', 'Long jumps over pieces'),
@@ -69,7 +72,7 @@ insert or ignore into Variants (name, description) values
   ('Monochrome', 'All of the same color'),
   ('Monster', 'White move twice'),
   ('Omega', 'A wizard in the corner'),
-  ('Orda', 'Mongolian Horde'),
+  ('Orda', 'Mongolian Horde (v1)'),
   ('Pacifist1', 'Convert & support (v1)'),
   ('Pacifist2', 'Convert & support (v2)'),
   ('Parachute', 'Landing on the board'),