From 305ede7ec3753fc669b7c86af5b5c5b2fc78a164 Mon Sep 17 00:00:00 2001 From: Benjamin Auder <benjamin.auder@somewhere> Date: Sun, 22 Mar 2020 04:10:46 +0100 Subject: [PATCH] First draft of S-chess variant + a few fixes --- TODO | 2 - client/public/images/pieces/Schess/be.svg | 177 +++++++++++ client/public/images/pieces/Schess/bh.svg | 118 ++++++++ client/public/images/pieces/Schess/we.svg | 201 +++++++++++++ client/public/images/pieces/Schess/wh.svg | 157 ++++++++++ client/src/base_rules.js | 8 +- client/src/translations/en.js | 1 + client/src/translations/es.js | 1 + client/src/translations/fr.js | 1 + client/src/translations/rules/Ball/en.pug | 4 +- client/src/translations/rules/Ball/es.pug | 4 +- client/src/translations/rules/Ball/fr.pug | 4 +- client/src/translations/rules/Schess/en.pug | 40 +++ client/src/translations/rules/Schess/es.pug | 42 +++ client/src/translations/rules/Schess/fr.pug | 41 +++ client/src/variants/Ball.js | 2 +- client/src/variants/Cannibal.js | 15 + client/src/variants/Checkered.js | 18 +- client/src/variants/Schess.js | 308 ++++++++++++++++++++ client/src/variants/Twokings.js | 46 ++- client/src/views/Hall.vue | 1 + server/db/populate.sql | 1 + 22 files changed, 1169 insertions(+), 23 deletions(-) create mode 100644 client/public/images/pieces/Schess/be.svg create mode 100644 client/public/images/pieces/Schess/bh.svg create mode 100644 client/public/images/pieces/Schess/we.svg create mode 100644 client/public/images/pieces/Schess/wh.svg create mode 100644 client/src/translations/rules/Schess/en.pug create mode 100644 client/src/translations/rules/Schess/es.pug create mode 100644 client/src/translations/rules/Schess/fr.pug create mode 100644 client/src/variants/Schess.js diff --git a/TODO b/TODO index 4a638435..1a566ad6 100644 --- 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 index 00000000..5868980b --- /dev/null +++ b/client/public/images/pieces/Schess/be.svg @@ -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 index 00000000..da180149 --- /dev/null +++ b/client/public/images/pieces/Schess/bh.svg @@ -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 index 00000000..05f8ffa8 --- /dev/null +++ b/client/public/images/pieces/Schess/we.svg @@ -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 index 00000000..2b8b5e55 --- /dev/null +++ b/client/public/images/pieces/Schess/wh.svg @@ -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> diff --git a/client/src/base_rules.js b/client/src/base_rules.js index f51e8d01..52ec2c54 100644 --- a/client/src/base_rules.js +++ b/client/src/base_rules.js @@ -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) ) { diff --git a/client/src/translations/en.js b/client/src/translations/en.js index 90d7daf5..f5139ce9 100644 --- a/client/src/translations/en.js +++ b/client/src/translations/en.js @@ -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", diff --git a/client/src/translations/es.js b/client/src/translations/es.js index 6894fcab..57e85b70 100644 --- a/client/src/translations/es.js +++ b/client/src/translations/es.js @@ -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", diff --git a/client/src/translations/fr.js b/client/src/translations/fr.js index 02b168de..dc3329db 100644 --- a/client/src/translations/fr.js +++ b/client/src/translations/fr.js @@ -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", diff --git a/client/src/translations/rules/Ball/en.pug b/client/src/translations/rules/Ball/en.pug index 475a1609..49005d8a 100644 --- a/client/src/translations/rules/Ball/en.pug +++ b/client/src/translations/rules/Ball/en.pug @@ -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. diff --git a/client/src/translations/rules/Ball/es.pug b/client/src/translations/rules/Ball/es.pug index 68940c7f..42922c47 100644 --- a/client/src/translations/rules/Ball/es.pug +++ b/client/src/translations/rules/Ball/es.pug @@ -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. diff --git a/client/src/translations/rules/Ball/fr.pug b/client/src/translations/rules/Ball/fr.pug index 9fae0806..070021d2 100644 --- a/client/src/translations/rules/Ball/fr.pug +++ b/client/src/translations/rules/Ball/fr.pug @@ -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 index 00000000..de4435a6 --- /dev/null +++ b/client/src/translations/rules/Schess/en.pug @@ -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 + | 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 index 00000000..ecac438a --- /dev/null +++ b/client/src/translations/rules/Schess/es.pug @@ -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 + | 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 index 00000000..ed55d9f5 --- /dev/null +++ b/client/src/translations/rules/Schess/fr.pug @@ -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 + | 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) diff --git a/client/src/variants/Ball.js b/client/src/variants/Ball.js index cf50a809..5a23e9f8 100644 --- a/client/src/variants/Ball.js +++ b/client/src/variants/Ball.js @@ -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"]) { diff --git a/client/src/variants/Cannibal.js b/client/src/variants/Cannibal.js index a08f1975..b66ac382 100644 --- a/client/src/variants/Cannibal.js +++ b/client/src/variants/Cannibal.js @@ -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; + } }; diff --git a/client/src/variants/Checkered.js b/client/src/variants/Checkered.js index 882a32ac..799c3e54 100644 --- a/client/src/variants/Checkered.js +++ b/client/src/variants/Checkered.js @@ -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 index 00000000..7cbb47a1 --- /dev/null +++ b/client/src/variants/Schess.js @@ -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); + } +}; diff --git a/client/src/variants/Twokings.js b/client/src/variants/Twokings.js index 9e82a245..ce30d653 100644 --- a/client/src/variants/Twokings.js +++ b/client/src/variants/Twokings.js @@ -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) { diff --git a/client/src/views/Hall.vue b/client/src/views/Hall.vue index 9bb913c4..28635469 100644 --- a/client/src/views/Hall.vue +++ b/client/src/views/Hall.vue @@ -80,6 +80,7 @@ main option(value="") option( v-for="p in Object.values(people)" + v-if="!!p.name" :value="p.name" ) | {{ p.name }} diff --git a/server/db/populate.sql b/server/db/populate.sql index a0d4c843..215a9b72 100644 --- a/server/db/populate.sql +++ b/server/db/populate.sql @@ -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'), -- 2.44.0