First draft of S-chess variant + a few fixes
authorBenjamin Auder <benjamin.auder@somewhere>
Sun, 22 Mar 2020 03:10:46 +0000 (04:10 +0100)
committerBenjamin Auder <benjamin.auder@somewhere>
Sun, 22 Mar 2020 03:10:46 +0000 (04:10 +0100)
22 files changed:
TODO
client/public/images/pieces/Schess/be.svg [new file with mode: 0644]
client/public/images/pieces/Schess/bh.svg [new file with mode: 0644]
client/public/images/pieces/Schess/we.svg [new file with mode: 0644]
client/public/images/pieces/Schess/wh.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/Ball/en.pug
client/src/translations/rules/Ball/es.pug
client/src/translations/rules/Ball/fr.pug
client/src/translations/rules/Schess/en.pug [new file with mode: 0644]
client/src/translations/rules/Schess/es.pug [new file with mode: 0644]
client/src/translations/rules/Schess/fr.pug [new file with mode: 0644]
client/src/variants/Ball.js
client/src/variants/Cannibal.js
client/src/variants/Checkered.js
client/src/variants/Schess.js [new file with mode: 0644]
client/src/variants/Twokings.js
client/src/views/Hall.vue
server/db/populate.sql

diff --git a/TODO b/TODO
index 4a63843..1a566ad 100644 (file)
--- a/TODO
+++ b/TODO
@@ -2,8 +2,6 @@
 Landing pieces from empty board:
 https://www.chessvariants.com/diffsetup.dir/unachess.html
 
-S-chess https://en.wikipedia.org/wiki/Seirawan_chess
-
 Generator variant, called "Matrix" ?
 Peces on first rank never move but generate new pieces. Pawn don't generate.
 A generator captured and replaced by a similar piece does not generate.
diff --git a/client/public/images/pieces/Schess/be.svg b/client/public/images/pieces/Schess/be.svg
new file mode 100644 (file)
index 0000000..5868980
--- /dev/null
@@ -0,0 +1,177 @@
+<?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"
+   width="177.17"
+   height="177.17"
+   shape-rendering="geometricPrecision"
+   image-rendering="optimizeQuality"
+   fill-rule="evenodd"
+   clip-rule="evenodd"
+   viewBox="0 0 50 50"
+   version="1.1"
+   id="svg12863"
+   sodipodi:docname="BE.svg"
+   inkscape:version="0.92.4 (5da689c313, 2019-01-14)">
+  <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
+     pagecolor="#ffffff"
+     bordercolor="#666666"
+     borderopacity="1"
+     objecttolerance="10"
+     gridtolerance="10"
+     guidetolerance="10"
+     inkscape:pageopacity="0"
+     inkscape:pageshadow="2"
+     inkscape:window-width="958"
+     inkscape:window-height="1008"
+     id="namedview12865"
+     showgrid="false"
+     showguides="false"
+     inkscape:zoom="1.7295106"
+     inkscape:cx="113.03876"
+     inkscape:cy="25.507445"
+     inkscape:window-x="953"
+     inkscape:window-y="0"
+     inkscape:window-maximized="0"
+     inkscape:current-layer="g13475" />
+  <defs
+     id="defs12857">
+    <linearGradient
+       inkscape:collect="always"
+       id="linearGradient7924">
+      <stop
+         style="stop-color:#bdbdbd;stop-opacity:1"
+         offset="0"
+         id="stop7920" />
+      <stop
+         style="stop-color:#ffffff;stop-opacity:1"
+         offset="1"
+         id="stop7922" />
+    </linearGradient>
+    <linearGradient
+       id="0"
+       x1="21.405"
+       x2="77.64"
+       gradientUnits="userSpaceOnUse">
+      <stop
+         stop-color="#fff"
+         id="stop12852" />
+      <stop
+         offset="1"
+         stop-color="#fff"
+         stop-opacity="0"
+         id="stop12854" />
+    </linearGradient>
+    <linearGradient
+       gradientTransform="matrix(-0.1675513,0,0,0.13095695,124.76512,-29.396941)"
+       inkscape:collect="always"
+       xlink:href="#linearGradient15233"
+       id="linearGradient15235"
+       x1="233.09853"
+       y1="541.73389"
+       x2="313.64203"
+       y2="543.00366"
+       gradientUnits="userSpaceOnUse" />
+    <linearGradient
+       inkscape:collect="always"
+       id="linearGradient15233">
+      <stop
+         style="stop-color:#ffffff;stop-opacity:1;"
+         offset="0"
+         id="stop15229" />
+      <stop
+         style="stop-color:#808080;stop-opacity:1"
+         offset="1"
+         id="stop15231" />
+    </linearGradient>
+    <linearGradient
+       gradientTransform="matrix(0.9198676,0,0,0.9198676,70.368497,62.093614)"
+       id="0-9"
+       x1="21.405001"
+       x2="77.639999"
+       gradientUnits="userSpaceOnUse">
+      <stop
+         stop-color="#fff"
+         id="stop832" />
+      <stop
+         offset="1"
+         stop-color="#fff"
+         stop-opacity="0"
+         id="stop834" />
+    </linearGradient>
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient7924"
+       id="linearGradient7926"
+       x1="72.16153"
+       y1="60.468464"
+       x2="102.88117"
+       y2="61.068867"
+       gradientUnits="userSpaceOnUse" />
+  </defs>
+  <g
+     id="g13475"
+     transform="matrix(1.087113,0,0,1.087113,-73.92342,-28.092572)">
+    <g
+       id="g3742"
+       transform="matrix(1.0010156,0,0,0.96471961,1.3426644,4.4892019)"
+       style="stroke-width:1.29800129;stroke-miterlimit:4;stroke-dasharray:none">
+      <path
+         sodipodi:nodetypes="ccccccccccccccccccsccccscc"
+         inkscape:connector-curvature="0"
+         id="path15217"
+         d="m 80.170737,65.446865 c 7.959966,0.05175 12.863181,0.134926 20.764343,0.173751 -0.0313,-1.787287 -0.57046,-3.574566 -1.564593,-5.361853 3.335183,-5.444552 2.470753,-8.628563 -0.601773,-10.817777 -1.497374,-2.28856 -2.816741,-4.697661 -4.934499,-7.713548 -2.194464,-1.576302 -4.89172,-2.984182 -6.378752,-4.797452 -0.910852,-1.833367 -0.488519,-2.972058 1.323892,-3.386435 4.4914,0.357556 2.357004,3.951786 2.768138,6.302535 7.43243,5.383284 10.365377,-0.813629 10.109717,-3.010167 -0.78922,-0.387682 -1.30908,0.386374 -2.116516,0.813351 -0.679496,-0.410687 -1.206499,-0.547042 -1.855162,-0.531147 -1.165715,0.697219 -0.911748,1.138135 -1.27192,1.992758 1.068542,-6.140328 -0.411256,-10.15656 -8.717439,-10.646984 -5.267627,0.497669 -7.800554,3.231384 -8.417453,7.895978 0.719979,0.470339 1.479558,0.907418 1.557299,1.510788 -0.109149,1.972593 0.950229,4.059356 1.684938,6.114398 l -0.764677,0.458925 0.170216,1.173483 c 0.136101,0.319128 0.923481,-0.368319 1.168278,-0.06651 0.303052,0.373609 0.633202,2.346961 0.569544,2.620121 -0.970882,-2.521911 -3.434646,-3.945637 -5.716799,-5.50296 -1.031381,-1.196133 -2.44949,-2.18241 -2.486529,-1.568473 0.348905,1.779496 1.051645,4.586961 2.447877,7.432109 -0.115746,2.689798 -0.674193,5.073016 -0.202043,7.682109 0.667915,3.690864 2.621218,4.742331 2.463913,9.233005 z"
+         style="fill:#1f1a17;fill-opacity:1;stroke:#1f1a17;stroke-width:1.58502242;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
+      <path
+         sodipodi:nodetypes="cccc"
+         inkscape:connector-curvature="0"
+         id="path15219"
+         d="m 85.617775,45.612152 c -0.949811,3.856625 -1.96871,4.338269 -3.346087,4.685844 -6.222,-8.589631 -5.974098,-14.325406 -4.057871,-16.292866 1.898378,3.33009 3.710947,9.102032 7.403958,11.607022 z"
+         style="fill:url(#linearGradient15235);fill-opacity:1;stroke:#1f1a17;stroke-width:1.58502242;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
+      <ellipse
+         transform="scale(-1,1)"
+         ry="1.30557"
+         rx="0.67696226"
+         cy="46.857224"
+         cx="-93.159279"
+         id="path15267"
+         style="opacity:1;fill:#ffffff;fill-opacity:1;stroke:#ffffff;stroke-width:1.29800129;stroke-linecap:square;stroke-linejoin:bevel;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:0.98431373;paint-order:normal" />
+      <path
+         sodipodi:nodetypes="ccc"
+         inkscape:connector-curvature="0"
+         id="path18972"
+         d="m 99.208344,53.500595 c 1.622596,2.882086 3.961876,5.732799 4.393136,11.337916 -5.232241,-1.86886 -1.39599,-0.545523 -4.680756,-0.751623"
+         style="fill:#1f1a17;fill-opacity:1;stroke:#1f1a17;stroke-width:1.58502242;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
+      <path
+         sodipodi:nodetypes="cc"
+         inkscape:connector-curvature="0"
+         id="path19000"
+         d="m 101.47622,56.506134 -2.267876,-3.00554"
+         style="fill:#2b0000;stroke:#ffffff;stroke-width:1.58502242;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
+      <path
+         sodipodi:nodetypes="ccc"
+         inkscape:connector-curvature="0"
+         id="path19002"
+         d="M 101.42685,64.206224 C 98.936706,63.34891 92.454719,64.31533 87.895907,64.715496 89.57682,62.663941 89.716729,59.58505 89.890762,56.528908"
+         style="fill:none;fill-opacity:1;stroke:url(#linearGradient7926);stroke-width:1.58502242;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/Schess/bh.svg b/client/public/images/pieces/Schess/bh.svg
new file mode 100644 (file)
index 0000000..da18014
--- /dev/null
@@ -0,0 +1,118 @@
+<?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"
+   width="177.17"
+   height="177.17"
+   shape-rendering="geometricPrecision"
+   image-rendering="optimizeQuality"
+   fill-rule="evenodd"
+   clip-rule="evenodd"
+   viewBox="0 0 50 50"
+   version="1.1"
+   id="svg12863"
+   sodipodi:docname="BH.svg"
+   inkscape:version="0.92.4 (5da689c313, 2019-01-14)">
+  <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
+     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="1017"
+     id="namedview12865"
+     showgrid="false"
+     showguides="false"
+     inkscape:zoom="2.8284271"
+     inkscape:cx="182.47608"
+     inkscape:cy="55.534186"
+     inkscape:window-x="-8"
+     inkscape:window-y="-8"
+     inkscape:window-maximized="1"
+     inkscape:current-layer="g13475" />
+  <defs
+     id="defs12857">
+    <linearGradient
+       id="0"
+       x1="21.405"
+       x2="77.64"
+       gradientUnits="userSpaceOnUse">
+      <stop
+         stop-color="#fff"
+         id="stop12852" />
+      <stop
+         offset="1"
+         stop-color="#fff"
+         stop-opacity="0"
+         id="stop12854" />
+    </linearGradient>
+  </defs>
+  <g
+     id="g13475"
+     transform="matrix(1.087113,0,0,1.087113,-73.92342,-28.092572)">
+    <g
+       id="g3155"
+       transform="matrix(0.97074389,0,0,0.97074389,2.6622636,3.5031888)">
+      <g
+         transform="matrix(0.99867819,0,0,1.060145,0.12021655,-3.9657669)"
+         id="g3145">
+        <path
+           sodipodi:nodetypes="cccccccccccccccccccc"
+           inkscape:connector-curvature="0"
+           id="path13430"
+           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"
+           style="fill:#1f1a17;fill-opacity:1;stroke:#1f1a17;stroke-width:1.69328892;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
+        <path
+           sodipodi:nodetypes="cc"
+           inkscape:connector-curvature="0"
+           id="path13434"
+           d="m 83.103812,35.805085 c -0.02515,1.008854 0.490503,1.148881 1.112288,1.324152"
+           style="fill:#ffffff;stroke:#ffffff;stroke-width:1.29800129;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
+        <path
+           transform="rotate(-3.1672079)"
+           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"
+           sodipodi:end="3.2099747"
+           sodipodi:start="0"
+           sodipodi:ry="1.8273305"
+           sodipodi:rx="2.5158896"
+           sodipodi:cy="41.973846"
+           sodipodi:cx="88.897865"
+           sodipodi:type="arc"
+           id="path13436"
+           style="opacity:1;fill:#ffffff;fill-opacity:0.98431373;stroke:#ffffff;stroke-width:1.69328892;stroke-linecap:square;stroke-linejoin:bevel;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:0.98431373;paint-order:normal" />
+        <path
+           inkscape:connector-curvature="0"
+           id="path13438"
+           d="m 93.644067,36.864407 3.760592,-0.423729"
+           style="fill:#ffffff;stroke:#ffffff;stroke-width:1.69328892;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
+      </g>
+      <path
+         sodipodi:nodetypes="ccccc"
+         inkscape:connector-curvature="0"
+         id="path3147"
+         d="m 79.742662,41.383025 c 0.310502,0.194594 0.639867,0.423478 1.021127,0.70652 l 10.764209,2.445766 0.131338,-0.769265 z"
+         style="fill:#ffffff;stroke:none;stroke-width:0.25960028px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
+    </g>
+  </g>
+</svg>
diff --git a/client/public/images/pieces/Schess/we.svg b/client/public/images/pieces/Schess/we.svg
new file mode 100644 (file)
index 0000000..05f8ffa
--- /dev/null
@@ -0,0 +1,201 @@
+<?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"
+   width="177.17"
+   height="177.17"
+   shape-rendering="geometricPrecision"
+   image-rendering="optimizeQuality"
+   fill-rule="evenodd"
+   clip-rule="evenodd"
+   viewBox="0 0 50 50"
+   version="1.1"
+   id="svg12863"
+   sodipodi:docname="WE.svg"
+   inkscape:version="0.92.4 (5da689c313, 2019-01-14)">
+  <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 />
+      </cc:Work>
+    </rdf:RDF>
+  </metadata>
+  <sodipodi:namedview
+     pagecolor="#ffffff"
+     bordercolor="#666666"
+     borderopacity="1"
+     objecttolerance="10"
+     gridtolerance="10"
+     guidetolerance="10"
+     inkscape:pageopacity="0"
+     inkscape:pageshadow="2"
+     inkscape:window-width="960"
+     inkscape:window-height="1017"
+     id="namedview12865"
+     showgrid="false"
+     showguides="false"
+     inkscape:zoom="1.7295106"
+     inkscape:cx="41.727425"
+     inkscape:cy="216.44851"
+     inkscape:window-x="952"
+     inkscape:window-y="-8"
+     inkscape:window-maximized="0"
+     inkscape:current-layer="g13475" />
+  <defs
+     id="defs12857">
+    <linearGradient
+       inkscape:collect="always"
+       id="linearGradient18986">
+      <stop
+         style="stop-color:#ffffff;stop-opacity:1"
+         offset="0"
+         id="stop18982" />
+      <stop
+         style="stop-color:#999999;stop-opacity:1"
+         offset="1"
+         id="stop18984" />
+    </linearGradient>
+    <linearGradient
+       inkscape:collect="always"
+       id="linearGradient18978">
+      <stop
+         style="stop-color:#ffffff;stop-opacity:1"
+         offset="0"
+         id="stop18974" />
+      <stop
+         style="stop-color:#808080;stop-opacity:1"
+         offset="1"
+         id="stop18976" />
+    </linearGradient>
+    <linearGradient
+       id="0"
+       x1="21.405"
+       x2="77.64"
+       gradientUnits="userSpaceOnUse">
+      <stop
+         stop-color="#fff"
+         id="stop12852" />
+      <stop
+         offset="1"
+         stop-color="#fff"
+         stop-opacity="0"
+         id="stop12854" />
+    </linearGradient>
+    <linearGradient
+       gradientTransform="matrix(0.18388585,0,0,0.14372393,52.70999,-34.229473)"
+       inkscape:collect="always"
+       xlink:href="#linearGradient15233"
+       id="linearGradient15235"
+       x1="263.8862"
+       y1="556.02753"
+       x2="226.60266"
+       y2="613.10144"
+       gradientUnits="userSpaceOnUse" />
+    <linearGradient
+       inkscape:collect="always"
+       id="linearGradient15233">
+      <stop
+         style="stop-color:#ffffff;stop-opacity:1;"
+         offset="0"
+         id="stop15229" />
+      <stop
+         style="stop-color:#808080;stop-opacity:1"
+         offset="1"
+         id="stop15231" />
+    </linearGradient>
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient18978"
+       id="linearGradient18980"
+       x1="99.346107"
+       y1="53.234913"
+       x2="78.265686"
+       y2="53.234913"
+       gradientUnits="userSpaceOnUse" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient18986"
+       id="linearGradient18988"
+       x1="103.51731"
+       y1="65.571739"
+       x2="80.967453"
+       y2="65.571739"
+       gradientUnits="userSpaceOnUse" />
+    <clipPath
+       clipPathUnits="userSpaceOnUse"
+       id="clipPath5191">
+      <rect
+         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"
+         id="rect5193"
+         width="35.162529"
+         height="15.671"
+         x="7.2068729"
+         y="4.0289068"
+         clip-path="none" />
+    </clipPath>
+    <linearGradient
+       id="0-8"
+       x1="21.375999"
+       x2="77.639999"
+       gradientUnits="userSpaceOnUse">
+      <stop
+         stop-color="#fff"
+         id="stop4571" />
+      <stop
+         offset="1"
+         stop-color="#fff"
+         stop-opacity="0"
+         id="stop4573" />
+    </linearGradient>
+  </defs>
+  <g
+     id="g13475"
+     transform="matrix(1.087113,0,0,1.087113,-73.92342,-28.092572)">
+    <g
+       id="g4360"
+       transform="matrix(0.91209554,0,0,0.8790237,7.9997623,6.8776245)"
+       style="stroke-width:1.42454326;stroke-miterlimit:4;stroke-dasharray:none">
+      <g
+         transform="matrix(-1,0,0,1,182.33976,-0.75050212)"
+         id="g18994"
+         style="stroke-width:1.42454326;stroke-miterlimit:4;stroke-dasharray:none">
+        <path
+           style="fill:url(#linearGradient18980);fill-opacity:1;stroke:#1f1a17;stroke-width:1.73954604;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+           d="m 101.65188,69.860643 c -8.735986,0.0568 -14.117214,0.14808 -22.788666,0.19069 0.03444,-1.96153 0.626084,-3.92305 1.717131,-5.88458 -3.660327,-5.97534 -2.711629,-9.46976 0.660435,-11.8724 1.643358,-2.511672 3.09135,-5.155635 5.415568,-8.465541 2.408402,-1.729975 5.368613,-3.27511 7.000615,-5.265155 0.999651,-2.012102 0.536145,-3.261803 -1.452958,-3.716578 -4.929266,0.392414 -2.586788,4.337045 -3.038003,6.916968 -8.157022,5.9081 -11.375898,-0.892949 -11.09531,-3.303627 0.866167,-0.425478 1.436706,0.424041 2.322856,0.892644 0.745737,-0.450725 1.324113,-0.600373 2.036018,-0.582929 1.279361,0.765191 1.000634,1.249092 1.395919,2.187032 -1.172713,-6.738948 0.45135,-11.146721 9.567302,-11.684957 5.781167,0.546187 8.561033,3.546411 9.238073,8.665756 -0.79017,0.516192 -1.6238,0.995882 -1.70912,1.658075 0.11979,2.1649 -1.042871,4.455102 -1.849206,6.710489 l 0.839225,0.503666 -0.18681,1.287886 c -0.14937,0.350239 -1.013511,-0.404227 -1.282174,-0.07299 -0.332596,0.410032 -0.549328,2.109829 -0.479463,2.409619 1.065533,-2.767772 3.623888,-3.864359 6.128528,-5.573506 1.13193,-1.312743 2.68829,-2.395172 2.72894,-1.721383 -0.38292,1.952979 -1.15417,5.034143 -2.68652,8.156665 0.12703,2.952026 0.73992,5.567583 0.22174,8.431036 -0.73303,4.050686 -2.87676,5.20466 -2.70412,10.13313 z"
+           id="path15217"
+           inkscape:connector-curvature="0"
+           sodipodi:nodetypes="ccccccccccccccccccsccccscc" />
+        <path
+           style="fill:url(#linearGradient15235);fill-opacity:1;stroke:#1f1a17;stroke-width:1.73954604;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+           d="m 95.673807,48.092246 c 1.042408,4.232607 2.16064,4.761207 3.672297,5.142667 6.828586,-9.427033 6.556516,-15.721988 4.453476,-17.881256 -2.08345,3.65474 -4.072731,9.989388 -8.125773,12.738589 z"
+           id="path15219"
+           inkscape:connector-curvature="0"
+           sodipodi:nodetypes="cccc" />
+        <ellipse
+           style="opacity:1;fill:#1f1a17;fill-opacity:1;stroke:#1f1a17;stroke-width:1.42454326;stroke-linecap:square;stroke-linejoin:bevel;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;paint-order:normal"
+           id="path15267"
+           cx="87.397079"
+           cy="49.458702"
+           rx="0.7429592"
+           ry="1.4328499" />
+        <path
+           style="fill:url(#linearGradient18988);fill-opacity:1;stroke:#1f1a17;stroke-width:1.73954604;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+           d="m 80.758294,56.749733 c -1.780779,3.16306 -4.348115,6.291688 -4.821424,12.443248 5.742335,-2.051055 13.154089,1.099485 17.23671,-0.135008 -2.50154,-4.0381 -1.208197,-3.908699 -2.189333,-8.984699"
+           id="path18972"
+           inkscape:connector-curvature="0"
+           sodipodi:nodetypes="cccc" />
+      </g>
+    </g>
+  </g>
+</svg>
diff --git a/client/public/images/pieces/Schess/wh.svg b/client/public/images/pieces/Schess/wh.svg
new file mode 100644 (file)
index 0000000..2b8b5e5
--- /dev/null
@@ -0,0 +1,157 @@
+<?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"
+   width="177.17"
+   height="177.17"
+   shape-rendering="geometricPrecision"
+   image-rendering="optimizeQuality"
+   fill-rule="evenodd"
+   clip-rule="evenodd"
+   viewBox="0 0 50 50"
+   version="1.1"
+   id="svg12863"
+   sodipodi:docname="WH.svg"
+   inkscape:version="0.92.4 (5da689c313, 2019-01-14)">
+  <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
+     pagecolor="#ffffff"
+     bordercolor="#666666"
+     borderopacity="1"
+     objecttolerance="10"
+     gridtolerance="10"
+     guidetolerance="10"
+     inkscape:pageopacity="0"
+     inkscape:pageshadow="2"
+     inkscape:window-width="958"
+     inkscape:window-height="1008"
+     id="namedview12865"
+     showgrid="false"
+     showguides="false"
+     inkscape:zoom="1.7295106"
+     inkscape:cx="31.332406"
+     inkscape:cy="107.19209"
+     inkscape:window-x="1912"
+     inkscape:window-y="-8"
+     inkscape:window-maximized="1"
+     inkscape:current-layer="svg12863" />
+  <defs
+     id="defs12857">
+    <linearGradient
+       inkscape:collect="always"
+       id="linearGradient13464">
+      <stop
+         style="stop-color:#808080;stop-opacity:1;"
+         offset="0"
+         id="stop13460" />
+      <stop
+         style="stop-color:#ffffff;stop-opacity:1"
+         offset="1"
+         id="stop13462" />
+    </linearGradient>
+    <linearGradient
+       id="0"
+       x1="21.405"
+       x2="77.64"
+       gradientUnits="userSpaceOnUse">
+      <stop
+         stop-color="#fff"
+         id="stop12852" />
+      <stop
+         offset="1"
+         stop-color="#fff"
+         stop-opacity="0"
+         id="stop12854" />
+    </linearGradient>
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient13464"
+       id="linearGradient13468"
+       x1="115.58475"
+       y1="51.192822"
+       x2="87.865845"
+       y2="51.538971"
+       gradientUnits="userSpaceOnUse" />
+    <clipPath
+       clipPathUnits="userSpaceOnUse"
+       id="clipPath5191">
+      <rect
+         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"
+         id="rect5193"
+         width="35.162529"
+         height="15.671"
+         x="7.2068729"
+         y="4.0289068"
+         clip-path="none" />
+    </clipPath>
+    <linearGradient
+       id="0-2"
+       x1="21.375999"
+       x2="77.639999"
+       gradientUnits="userSpaceOnUse">
+      <stop
+         stop-color="#fff"
+         id="stop4571" />
+      <stop
+         offset="1"
+         stop-color="#fff"
+         stop-opacity="0"
+         id="stop4573" />
+    </linearGradient>
+  </defs>
+  <g
+     id="g13475"
+     transform="matrix(1.0539134,0,0,1.1187798,-70.902198,-28.281003)">
+    <path
+       sodipodi:nodetypes="cccccccccccccccccccc"
+       inkscape:connector-curvature="0"
+       id="path13430"
+       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"
+       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" />
+    <path
+       inkscape:connector-curvature="0"
+       id="path13432"
+       d="M 91.159846,44.531907 79.924039,41.910219"
+       style="fill:none;stroke:#1f1a17;stroke-width:1.55939555;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
+    <path
+       sodipodi:nodetypes="cc"
+       inkscape:connector-curvature="0"
+       id="path13434"
+       d="m 83.103812,35.805085 c -0.02515,1.008854 0.490503,1.148881 1.112288,1.324152"
+       style="fill:none;stroke:#1f1a17;stroke-width:1.55939555;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
+    <path
+       transform="rotate(-3.1672079)"
+       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"
+       sodipodi:end="3.2099747"
+       sodipodi:start="0"
+       sodipodi:ry="1.8273305"
+       sodipodi:rx="2.5158896"
+       sodipodi:cy="41.973846"
+       sodipodi:cx="88.897865"
+       sodipodi:type="arc"
+       id="path13436"
+       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" />
+    <path
+       inkscape:connector-curvature="0"
+       id="path13438"
+       d="m 93.644067,36.864407 3.760592,-0.423729"
+       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" />
+  </g>
+</svg>
index f51e8d0..52ec2c5 100644 (file)
@@ -191,9 +191,9 @@ export const ChessRules = class ChessRules {
     return V.CoordToColumn(coords.y) + (V.size.x - coords.x);
   }
 
-  // Path to pieces
+  // Path to pieces (standard ones in pieces/ folder)
   getPpath(b) {
-    return b; //usual pieces in pieces/ folder
+    return b;
   }
 
   // Path to promotion pieces (usually the same)
@@ -1101,7 +1101,9 @@ export const ChessRules = class ChessRules {
     ) {
       const flagIdx = (move.start.y == this.castleFlags[c][0] ? 0 : 1);
       this.castleFlags[c][flagIdx] = V.size.y;
-    } else if (
+    }
+    // NOTE: not "else if" because a rook could take an opposing rook
+    if (
       move.end.x == oppFirstRank && //we took opponent rook?
       this.castleFlags[oppCol].includes(move.end.y)
     ) {
index 90d7daf..f5139ce 100644 (file)
@@ -193,6 +193,7 @@ export const translations = {
   "Reverse captures": "Reverse captures",
   "Run forward": "Run forward",
   "Score a goal": "Score a goal",
+  "Seirawan-Harper Chess": "Seirawan-Harper Chess",
   "Shared pieces": "Shared pieces",
   "Shoot pieces": "Shoot pieces",
   "Squares disappear": "Squares disappear",
index 6894fca..57e85b7 100644 (file)
@@ -193,6 +193,7 @@ export const translations = {
   "Reverse captures": "Capturas invertidas",
   "Run forward": "Correr hacia adelante",
   "Score a goal": "Marcar una meta",
+  "Seirawan-Harper Chess": "Ajedrez Seirawan-Harper",
   "Shared pieces": "Piezas compartidas",
   "Shoot pieces": "Tirar de las piezas",
   "Squares disappear": "Las casillas desaparecen",
index 02b168d..dc3329d 100644 (file)
@@ -193,6 +193,7 @@ export const translations = {
   "Reverse captures": "Captures inversées",
   "Run forward": "Courir vers l'avant",
   "Score a goal": "Marquer un but",
+  "Seirawan-Harper Chess": "Échecs Seirawan-Harper",
   "Shared pieces": "Pièces partagées",
   "Shoot pieces": "Tirez sur les pièces",
   "Squares disappear": "Les cases disparaissent",
index 475a160..49005d8 100644 (file)
@@ -14,9 +14,9 @@ ul
 
 figure.diagram-container
   .diagram.diag12
-    | fen:rnbqkwbnr/ppppp1ppp/9/5p3/4a4/9/2N3N2/PPPPPPPPP/R1BQKWB1R:
+    | fen:rnbqkwnbr/ppppp1ppp/9/5p3/4a4/9/2N4N1/PPPPPPPPP/R1BQKW1BR:
   .diagram.diag22
-    | fen:rnbqkwbnr/ppppp1ppp/9/9/4s4/9/2N3N2/PPPPPPPPP/R1BQKWB1R:
+    | fen:rnbqkwnbr/ppppp1ppp/9/9/4s4/9/2N4N1/PPPPPPPPP/R1BQKW1BR:
   figcaption Left: before ...fxe5 (taking ball). Right: after ...fxe5.
 
 p.
index 68940c7..42922c4 100644 (file)
@@ -14,9 +14,9 @@ ul
 
 figure.diagram-container
   .diagram.diag12
-    | fen:rnbqkwbnr/ppppp1ppp/9/5p3/4a4/9/2N3N2/PPPPPPPPPP/R1BQKWB1R:
+    | fen:rnbqkwnbr/ppppp1ppp/9/5p3/4a4/9/2N4N1/PPPPPPPPPP/R1BQKW1BR:
   .diagram.diag22
-    | fen:rnbqkwbnr/ppppp1ppp/9/9/4s4/9/2N3N2/PPPPPPPPPP/R1BQKWB1R:
+    | fen:rnbqkwnbr/ppppp1ppp/9/9/4s4/9/2N4N1/PPPPPPPPPP/R1BQKW1BR:
   figcaption.
     Izquierda: antes de ...fxe5 (tomando la pelota).
     Derecha: después de ...fxe5.
index 9fae080..070021d 100644 (file)
@@ -14,9 +14,9 @@ ul
 
 figure.diagram-container
   .diagram.diag12
-    | fen:rnbqkwbnr/ppppp1ppp/9/5p3/4a4/9/2N3N2/PPPPPPPPP/R1BQKWB1R:
+    | fen:rnbqkwnbr/ppppp1ppp/9/5p3/4a4/9/2N4N1/PPPPPPPPP/R1BQKW1BR:
   .diagram.diag22
-    | fen:rnbqkwbnr/ppppp1ppp/9/9/4s4/9/2N3N2/PPPPPPPPP/R1BQKWB1R:
+    | fen:rnbqkwnbr/ppppp1ppp/9/9/4s4/9/2N4N1/PPPPPPPPP/R1BQKW1BR:
   figcaption Gauche : avant ...fxe5 (prenant le ballon). Droite : après ...fxe5.
 
 p.
diff --git a/client/src/translations/rules/Schess/en.pug b/client/src/translations/rules/Schess/en.pug
new file mode 100644 (file)
index 0000000..de4435a
--- /dev/null
@@ -0,0 +1,40 @@
+p.boxed
+  | You have two new pieces in a pocket, which can appear after any
+  | first piece movement.
+
+p.
+  When a piece is moved for the first time, it is possible to place a new
+  piece at its initial square.
+  You have two pieces that can enter the game like this:
+ul
+  li The Hawk (H): moving like a bishop + knight.
+  li The Elephant (E): moving like a rook + knight.
+
+figure.diagram-container
+  .diagram
+    | fen:rnbqkbnr/pppppppp/8/8/8/2N5/PPPPPPPP/REBQKBNR:
+  figcaption.
+    Position after 1.Nc3/E. White moved his knight from b1 to c3 and placed
+    the elephant on b1.
+
+p.
+  After castling, a new piece can be put at the initial king square
+  (if not occupied), or at the initial rook square - but not both.
+
+p.
+  If a move let the king under check, then it is forbidden,
+  even if placing a pocket piece would have covered the check.
+
+h3 Source
+
+p
+  | Some explanations about the rules and a link to buy a physical S-Chess set
+  | on the 
+  a(href="http://www.seirawanchess.com/") Seirawan Chess page
+  | . This variant is playable on 
+  a(href="https://www.pychess.org/variant/seirawan") pychess-variants
+  | &nbsp;with an engine available for analysis. See also the 
+  a(href="https://en.wikipedia.org/wiki/Seirawan_chess") Wikipedia page
+  | .
+
+p Inventors: Yasser Seirawan and Bruce Harper (2008)
diff --git a/client/src/translations/rules/Schess/es.pug b/client/src/translations/rules/Schess/es.pug
new file mode 100644 (file)
index 0000000..ecac438
--- /dev/null
@@ -0,0 +1,42 @@
+p.boxed
+  | Tienes dos piezas en tu bolsillo, que pueden aparecer después
+  | cualquier movimiento inicial de una pieza.
+
+p.
+  Cuando una pieza se mueve por la primera vez, una pieza nueva
+  se puede colocar en su casilla inicial.
+  Tienes dos piezas que también pueden ingresar al juego:
+ul
+  li El Aguila (H): se mueve como un alfil + caballo.
+  li El Elefante (E): se mueve como una torre + caballo.
+
+figure.diagram-container
+  .diagram
+    | fen:rnbqkbnr/pppppppp/8/8/8/2N5/PPPPPPPP/REBQKBNR:
+  figcaption.
+    Posición después de 1.Nc3/E. Las blancas mueven su caballo de b1 a c3
+    y colocar el elefante en b1.
+
+p.
+  Después de haberse enrocado, se puede colocar una nueva pieza en la
+  casilla inicial del rey (si no está ocupado), o en el espacio inicial de
+  la torre, pero no en ambos.
+
+p.
+  Si un movimiento deja al rey en jaque, entonces está prohibido,
+  incluso si colocar una nueva pieza hubiera sido el jaque.
+
+h3 Fuente
+
+p
+  | Algunas explicaciones sobre las reglas, así como un enlace para comprar
+  | un conjunto de piezas de S-Chess en el
+  a(href="http://www.seirawanchess.com/") página Seirawan Chess
+  | . Esta variante se puede jugar en 
+  a(href="https://www.pychess.org/variant/seirawan") pychess-variantes
+  | &nbsp;con un módulo disponible para análisis. Ver también la 
+  a(href= "https://www.pousseurdebois.fr/variantes-du-jeu-dechecs/echecsseirawan/")
+  a(href="https://en.wikipedia.org/wiki/Seirawan_chess") página Wikipedia
+  | .
+
+p Inventores: Yasser Seirawan y Bruce Harper (2008)
diff --git a/client/src/translations/rules/Schess/fr.pug b/client/src/translations/rules/Schess/fr.pug
new file mode 100644 (file)
index 0000000..ed55d9f
--- /dev/null
@@ -0,0 +1,41 @@
+p.boxed
+  | Vous avez deux pièces en poche, qui peuvent apparaitre après
+  | n'importe quel déplacement initial d'une pièce.
+
+p.
+  Quand une pièce est déplacée pour la première fois, une nouvelle pièce
+  peut être placée sur sa case de départ.
+  Vous avez deux pièces pouvant entrer dans le jeu ainsi :
+ul
+  li L'Aigle (H) : se déplace comme un fou + cavalier.
+  li L'Éléphant (E) : se déplace comme une tour + cavalier.
+
+figure.diagram-container
+  .diagram
+    | fen:rnbqkbnr/pppppppp/8/8/8/2N5/PPPPPPPP/REBQKBNR:
+  figcaption.
+    Position après 1.Nc3/E. Les blancs déplacent leur cavalier de b1 à c3
+    et placent l'éléphant en b1.
+
+p.
+  Après avoir roqué, une nouvelle pièce peut être placée sur la case
+  initiale du roi (si elle n'est pas occupée), ou sur la case initiale de la
+  tour - mais pas sur les deux.
+
+p.
+  Si un coup laisse le roi en échec, alors il est interdit,
+  même si le placement d'une nouvelle pièce aurait paré l'échec.
+
+h3 Source
+
+p
+  | Quelques explications sur les règles ainsi qu'un lien pour acheter
+  | un jeu de pièces de S-Chess sur la 
+  a(href="http://www.seirawanchess.com/") page Seirawan Chess
+  | . Cette variante est jouable sur 
+  a(href="https://www.pychess.org/variant/seirawan") pychess-variants
+  | &nbsp;avec un module disponible pour l'analyse. Voir aussi 
+  a(href="https://www.pousseurdebois.fr/variantes-du-jeu-dechecs/echecsseirawan/")
+    | cette page.
+
+p Inventeurs : Yasser Seirawan et Bruce Harper (2008)
index cf50a80..5a23e9f 100644 (file)
@@ -129,7 +129,7 @@ export class BallRules extends ChessRules {
 
   static GenRandInitFen(randomness) {
     if (randomness == 0)
-      return "rnbqkwbnr/ppppppppp/9/9/4a4/9/9/PPPPPPPPP/RNBQKWBNR w 0 -";
+      return "rnbqkwnbr/ppppppppp/9/9/4a4/9/9/PPPPPPPPP/RNBQKWNBR w 0 -";
 
     let pieces = { w: new Array(9), b: new Array(9) };
     for (let c of ["w", "b"]) {
index a08f197..b66ac38 100644 (file)
@@ -234,4 +234,19 @@ export class CannibalRules extends ChessRules {
   static get SEARCH_DEPTH() {
     return 4;
   }
+
+  getNotation(move) {
+    let notation = super.getNotation(move);
+    const lastRank = (move.appear[0].c == "w" ? 0 : 7);
+    if (
+      move.end.x != lastRank &&
+      this.getPiece(move.start.x, move.start.y) == V.PAWN &&
+      move.vanish.length == 2 &&
+      move.appear[0].p != V.PAWN
+    ) {
+      // Fix "promotion" (transform indicator) from base_rules notation
+      notation = notation.slice(0, -2);
+    }
+    return notation;
+  }
 };
index 882a32a..799c3e5 100644 (file)
@@ -71,8 +71,8 @@ export class CheckeredRules extends ChessRules {
   setFlags(fenflags) {
     super.setFlags(fenflags); //castleFlags
     this.pawnFlags = {
-      w: [...Array(8).fill(true)], //pawns can move 2 squares?
-      b: [...Array(8).fill(true)]
+      w: [...Array(8)], //pawns can move 2 squares?
+      b: [...Array(8)]
     };
     const flags = fenflags.substr(4); //skip first 4 letters, for castle
     for (let c of ["w", "b"]) {
@@ -402,19 +402,19 @@ export class CheckeredRules extends ChessRules {
 
   getFen() {
     const L = this.cmoves.length;
-    const cmoveFen = !this.cmoves[L - 1]
-      ? "-"
-      : ChessRules.CoordsToSquare(this.cmoves[L - 1].start) +
-        ChessRules.CoordsToSquare(this.cmoves[L - 1].end);
+    const cmoveFen =
+      !this.cmoves[L - 1]
+        ? "-"
+        : ChessRules.CoordsToSquare(this.cmoves[L - 1].start) +
+          ChessRules.CoordsToSquare(this.cmoves[L - 1].end);
     return super.getFen() + " " + cmoveFen;
   }
 
   getFlagsFen() {
     let fen = super.getFlagsFen();
     // Add pawns flags
-    for (let c of ["w", "b"]) {
-      for (let i = 0; i < 8; i++) fen += this.pawnFlags[c][i] ? "1" : "0";
-    }
+    for (let c of ["w", "b"])
+      for (let i = 0; i < 8; i++) fen += (this.pawnFlags[c][i] ? "1" : "0");
     return fen;
   }
 
diff --git a/client/src/variants/Schess.js b/client/src/variants/Schess.js
new file mode 100644 (file)
index 0000000..7cbb47a
--- /dev/null
@@ -0,0 +1,308 @@
+import { ChessRules, PiPo } from "@/base_rules";
+
+export class SchessRules extends ChessRules {
+  static get PawnSpecs() {
+    return Object.assign(
+      {},
+      ChessRules.PawnSpecs,
+      {
+        promotions:
+          ChessRules.PawnSpecs.promotions.concat([V.HAWK, V.ELEPHANT])
+      }
+    );
+  }
+
+  static get HAWK() {
+    return 'h';
+  }
+
+  static get ELEPHANT() {
+    return 'e';
+  }
+
+  static get PIECES() {
+    return ChessRules.PIECES.concat([V.HAWK, V.ELEPHANT]);
+  }
+
+  getPpath(b) {
+    if ([V.HAWK, V.ELEPHANT].includes(b[1])) return "Schess/" + b;
+    return b;
+  }
+
+  // TODO: maybe changes could be done to this method to show "empty"
+  // instead of a piece to not use a pocket piece...
+//  getPPpath(b) { }
+
+  static IsGoodFen(fen) {
+    if (!ChessRules.IsGoodFen(fen)) return false;
+    const fenParsed = V.ParseFen(fen);
+    // Check pocket state
+    if (!fenParsed.pocket || !fenParsed.pocket.match(/^[0-1]{4,4}$/))
+      return false;
+    return true;
+  }
+
+  static IsGoodFlags(flags) {
+    // 4 for castle + 16 for generators
+    return !!flags.match(/^[a-z]{4,4}[01]{16,16}$/);
+  }
+
+  setFlags(fenflags) {
+    super.setFlags(fenflags); //castleFlags
+    this.pieceFlags = {
+      w: [...Array(8)], //pawns can move 2 squares?
+      b: [...Array(8)]
+    };
+    const flags = fenflags.substr(4); //skip first 4 letters, for castle
+    for (let c of ["w", "b"]) {
+      for (let i = 0; i < 8; i++)
+        this.pieceFlags[c][i] = flags.charAt((c == "w" ? 0 : 8) + i) == "1";
+    }
+  }
+
+  aggregateFlags() {
+    return [this.castleFlags, this.pieceFlags];
+  }
+
+  disaggregateFlags(flags) {
+    this.castleFlags = flags[0];
+    this.pieceFlags = flags[1];
+  }
+
+  static ParseFen(fen) {
+    const fenParts = fen.split(" ");
+    return Object.assign(
+      ChessRules.ParseFen(fen),
+      { pocket: fenParts[5] }
+    );
+  }
+
+  static GenRandInitFen(randomness) {
+    return (
+      ChessRules.GenRandInitFen(randomness).slice(0, -2) +
+      // Add pieceFlags + pocket
+      "1111111111111111 - 1111"
+    );
+  }
+
+  getFen() {
+    return (
+      super.getFen() + " " +
+      this.getPocketFen()
+    );
+  }
+
+  getFenForRepeat() {
+    return (
+      super.getFenForRepeat() + "_" +
+      this.getPocketFen()
+    );
+  }
+
+  getFlagsFen() {
+    let fen = super.getFlagsFen();
+    // Add pieces flags
+    for (let c of ["w", "b"])
+      for (let i = 0; i < 8; i++) fen += (this.pieceFlags[c][i] ? "1" : "0");
+    return fen;
+  }
+
+  getPocketFen() {
+    let res = "";
+    for (let c of ["w", "b"])
+      res += this.pocket[c][V.HAWK] + this.pocket[c][V.ELEPHANT];
+    return res;
+  }
+
+  setOtherVariables(fen) {
+    super.setOtherVariables(fen);
+    const fenParsed = V.ParseFen(fen);
+    this.pocket = {
+      "w": {
+        h: parseInt(fenParsed.pocket[0]),
+        e: parseInt(fenParsed.pocket[1])
+      },
+      "b": {
+        h: parseInt(fenParsed.pocket[2]),
+        e: parseInt(fenParsed.pocket[3])
+      }
+    };
+  }
+
+  getPotentialMovesFrom([x, y]) {
+    let moves = undefined;
+    switch (this.getPiece(x, y)) {
+      case V.HAWK:
+        moves = this.getPotentialHawkMoves([x, y]);
+        break;
+      case V.ELEPHANT:
+        moves = this.getPotentialElephantMoves([x, y]);
+        break;
+      default:
+        moves = super.getPotentialMovesFrom([x, y]);
+    }
+    // Post-processing: add choices for hawk and elephant,
+    // except for moves letting the king under check.
+    const color = this.turn;
+    if (Object.values(this.pocket[color]).some(v => v > 0)) {
+      const firstRank = (color == "w" ? 7 : 0);
+      let pocketMoves = [];
+      moves.forEach(m => {
+        let inCheckAfter = false;
+        this.play(m);
+        if (this.underCheck(color)) inCheckAfter = true;
+        this.undo(m);
+        if (!inCheckAfter) {
+          for (let pp of ['h', 'e']) {
+            if (this.pocket[color][pp] > 0) {
+              if (
+                m.start.x == firstRank &&
+                this.pieceFlags[color][m.start.y] &&
+                (
+                  m.appear.length == 1 ||
+                  // Special castle case: is initial king square free?
+                  ![m.appear[0].y, m.appear[1].y].includes(m.vanish[0].y)
+                )
+              ) {
+                let pMove = JSON.parse(JSON.stringify(m));
+                // NOTE: unshift instead of push, for choices presentation
+                pMove.appear.unshift(new PiPo({
+                  p: pp,
+                  c: color,
+                  x: x,
+                  y: y
+                }));
+                pocketMoves.push(pMove);
+              }
+              if (
+                m.appear.length == 2 &&
+                ![m.appear[0].y, m.appear[1].y].includes(m.vanish[1].y)
+              ) {
+                // Special castle case: rook flag was necessarily on
+                let pMove = JSON.parse(JSON.stringify(m));
+                pMove.appear.unshift(new PiPo({
+                  p: pp,
+                  c: color,
+                  x: m.vanish[1].x,
+                  y: m.vanish[1].y
+                }));
+                pocketMoves.push(pMove);
+              }
+            }
+          }
+        }
+      });
+      // NOTE: the order matter, for presentation on screen
+      moves = moves.concat(pocketMoves);
+    }
+    return moves;
+  }
+
+  getPotentialHawkMoves(sq) {
+    return this.getSlideNJumpMoves(
+      sq,
+      V.steps[V.BISHOP].concat(V.steps[V.KNIGHT])
+    );
+  }
+
+  getPotentialElephantMoves(sq) {
+    return this.getSlideNJumpMoves(
+      sq,
+      V.steps[V.ROOK].concat(V.steps[V.KNIGHT])
+    );
+  }
+
+  isAttacked(sq, color) {
+    return (
+      super.isAttacked(sq, color) ||
+      this.isAttackedByHawk(sq, color) ||
+      this.isAttackedByElephant(sq, color)
+    );
+  }
+
+  isAttackedByHawk(sq, color) {
+    return this.isAttackedBySlideNJump(
+      sq,
+      color,
+      V.HAWK,
+      V.steps[V.BISHOP].concat(V.steps[V.KNIGHT])
+    );
+  }
+
+  isAttackedByElephant(sq, color) {
+    return this.isAttackedBySlideNJump(
+      sq,
+      color,
+      V.ELEPHANT,
+      V.steps[V.ROOK].concat(V.steps[V.KNIGHT])
+    );
+  }
+
+  prePlay(move) {
+    super.prePlay(move);
+    if (move.appear.length >= 2) {
+      if ([V.HAWK, V.ELEPHANT].includes(move.appear[0].p)) {
+        // A pocket piece is used
+        const color = this.turn;
+        this.pocket[color][move.appear[0].p] = 0;
+      }
+    }
+  }
+
+  postPlay(move) {
+    super.postPlay(move);
+    const color = move.vanish[0].c;
+    const oppCol = V.GetOppCol(color);
+    const firstRank = (color == 'w' ? 7 : 0);
+    const oppFirstRank = 7 - firstRank;
+    // Does this move turn off a piece init square flag?
+    if (move.start.x == firstRank) {
+      if (this.pieceFlags[color][move.start.y])
+        this.pieceFlags[color][move.start.y] = false;
+      // Special castle case:
+      if (move.appear.length >= 2) {
+        const L = move.appear.length;
+        if (move.appear[L-1].p == V.ROOK)
+          this.pieceFlags[color][move.vanish[1].y] = false;
+      }
+    }
+    if (move.end.x == oppFirstRank && this.pieceFlags[oppCol][move.end.y])
+      this.pieceFlags[oppCol][move.end.y] = false;
+  }
+
+  postUndo(move) {
+    super.postUndo(move);
+    if (move.appear.length >= 2) {
+      if ([V.HAWK, V.ELEPHANT].includes(move.appear[0].p)) {
+        // A pocket piece was used
+        const color = this.turn;
+        this.pocket[color][move.appear[0].p] = 1;
+      }
+    }
+  }
+
+  static get SEARCH_DEPTH() {
+    return 2;
+  }
+
+  static get VALUES() {
+    return Object.assign(
+      {},
+      ChessRules.VALUES,
+      { 'h': 5, 'e': 7 }
+    );
+  }
+
+  getNotation(move) {
+    if (
+      move.appear.length >= 2 &&
+      [V.HAWK, V.ELEPHANT].includes(move.appear[0].p)
+    ) {
+      const suffix = "/" + move.appear[0].p.toUpperCase();
+      let cmove = JSON.parse(JSON.stringify(move));
+      cmove.appear.shift();
+      return super.getNotation(cmove) + suffix;
+    }
+    return super.getNotation(move);
+  }
+};
index 9e82a24..ce30d65 100644 (file)
@@ -54,8 +54,50 @@ export class TwokingsRules extends CoregalRules {
   }
 
   static GenRandInitFen(randomness) {
-    const fen = CoregalRules.GenRandInitFen(randomness);
-    return fen.replace("q", "k").replace("Q", "K");
+    if (randomness == 0)
+      return "rnqkkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNQKKBNR w 0 adehadeh -";
+
+    const replaceBishop = (fen, first, ch1, ch2) => {
+      // Remove and re-add final part:
+      const suffix = fen.substr(-15);
+      fen = fen.slice(0, -15);
+      if (first) fen = fen.replace(ch1, ch2);
+      else {
+        fen =
+          fen.split("").reverse().join("")
+          .replace(ch1, ch2)
+          .split("").reverse().join("")
+      }
+      return fen + suffix;
+    };
+
+    const sameIndexReplace = (fen) => {
+      const first = (Math.random() < 0.5);
+      return replaceBishop(
+        replaceBishop(fen, first, 'B', 'Q'),
+        first,
+        'b',
+        'q'
+      );
+    };
+
+    const fen =
+      CoregalRules.GenRandInitFen(randomness)
+      .replace("q", "k").replace("Q", "K");
+    // Now replace a bishop by the queen,
+    // so that bishops are of different colors:
+    if (randomness == 1) return sameIndexReplace(fen);
+    const wOdd = fen.indexOf('B') % 2;
+    const bOdd = fen.indexOf('b') % 2;
+    // Since there are 7 slashes, different oddities means symmetric
+    if (wOdd != bOdd) return sameIndexReplace(fen);
+    const wFirst = (Math.random() < 0.5);
+    return replaceBishop(
+      replaceBishop(fen, wFirst, 'B', 'Q'),
+      !wFirst,
+      'b',
+      'q'
+    );
   }
 
   underCheck(color) {
index 9bb913c..2863546 100644 (file)
@@ -80,6 +80,7 @@ main
             option(value="")
             option(
               v-for="p in Object.values(people)"
+              v-if="!!p.name"
               :value="p.name"
             )
               | {{ p.name }}
index a0d4c84..215a9b7 100644 (file)
@@ -41,6 +41,7 @@ insert or ignore into Variants (name,description) values
   ('Recycle', 'Reuse pieces'),
   ('Royalrace', 'Kings cross the 11x11 board'),
   ('Rugby', 'Transform an essay'),
+  ('Schess', 'Seirawan-Harper Chess'),
   ('Shatranj', 'Ancient rules'),
   ('Suicide', 'Lose all pieces'),
   ('Suction', 'Attract opposite king'),