Implement Wildebeest castle rules
=> (1, 2, 3 or 4 squares slide; randomized: may be impossible >1, but possible >4...)
-getRepetitionStatus() lose or draw... (for some variants)
+Fix Omega squares' color (queen on its color: need new static customization "getSquareColor()")
Embedded rules language not updated when language is set (in Analyse, Game and Problems)
If new live game starts in background, "new game" notify OK but not first move (not too serious however)
(=> comme pour corr) + option "confirm moves in corr games"?
NEW VARIANTS:
+https://www.pychess.org/variant/manchu
+https://www.pychess.org/variant/dobutsu
+https://www.pychess.org/variant/cambodian
+https://www.pychess.org/variant/makpong
+https://www.pychess.org/variant/janggi
+https://www.pychess.org/variant/kyotoshogi
+https://www.pychess.org/variant/hoppelpoppel
+https://musketeerchess.net/games/musketeer/index.php Attention règle de promotion + SVG / PNG
+(https://www.pychess.org/variant/shogun)
Isardam (type B) : https://echekk.fr/spip.php?page=article&id_article=280
https://www.reddit.com/r/TotemChess/comments/imi3v7/totem_rules/
https://www.chessvariants.com/other.dir/fugue.html
--- /dev/null
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://creativecommons.org/ns#"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:xlink="http://www.w3.org/1999/xlink"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ inkscape:version="1.0 (4035a4fb49, 2020-05-01)"
+ sodipodi:docname="bAdvisor.svg"
+ id="svg4798"
+ version="1.1"
+ viewBox="0 0 50 50"
+ clip-rule="evenodd"
+ fill-rule="evenodd"
+ image-rendering="optimizeQuality"
+ shape-rendering="geometricPrecision"
+ height="177.17"
+ width="177.17">
+ <metadata
+ id="metadata4802">
+ <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
+ inkscape:document-rotation="0"
+ inkscape:snap-nodes="false"
+ inkscape:current-layer="g6945"
+ inkscape:window-maximized="1"
+ inkscape:window-y="-8"
+ inkscape:window-x="1912"
+ inkscape:cy="238.0449"
+ inkscape:cx="-284.63182"
+ inkscape:zoom="0.33301349"
+ showgrid="false"
+ id="namedview4800"
+ inkscape:window-height="1017"
+ inkscape:window-width="1920"
+ inkscape:pageshadow="2"
+ inkscape:pageopacity="0"
+ guidetolerance="10"
+ gridtolerance="10"
+ objecttolerance="10"
+ borderopacity="1"
+ bordercolor="#666666"
+ pagecolor="#ffffff" />
+ <defs
+ id="defs4788">
+ <linearGradient
+ id="linearGradient6661"
+ inkscape:collect="always">
+ <stop
+ id="stop6657"
+ offset="0"
+ style="stop-color:#ffffff;stop-opacity:1;" />
+ <stop
+ id="stop6659"
+ offset="1"
+ style="stop-color:#b3b3b3;stop-opacity:1" />
+ </linearGradient>
+ <linearGradient
+ gradientUnits="userSpaceOnUse"
+ x2="77.64"
+ x1="21.376"
+ id="0">
+ <stop
+ id="stop4783"
+ stop-color="#fff" />
+ <stop
+ id="stop4785"
+ stop-opacity="0"
+ stop-color="#fff"
+ offset="1" />
+ </linearGradient>
+ <linearGradient
+ gradientUnits="userSpaceOnUse"
+ y2="37.469002"
+ x2="77.760002"
+ y1="37.220001"
+ x1="21.129999"
+ id="0-3"
+ gradientTransform="translate(50.708427,-1.9548155)">
+ <stop
+ id="stop5461"
+ stop-color="#fff" />
+ <stop
+ id="stop5463"
+ stop-opacity="0"
+ stop-color="#fff"
+ offset="1" />
+ </linearGradient>
+ <linearGradient
+ gradientUnits="userSpaceOnUse"
+ x2="77.639999"
+ x1="21.375999"
+ id="0-2"
+ gradientTransform="translate(-54.458725,-1.3555716)">
+ <stop
+ id="stop6058"
+ stop-color="#fff" />
+ <stop
+ id="stop6060"
+ stop-opacity="0"
+ stop-color="#fff"
+ offset="1" />
+ </linearGradient>
+ <linearGradient
+ gradientTransform="matrix(1.0621371,0,0,1.0621371,-24.440596,-23.156796)"
+ gradientUnits="userSpaceOnUse"
+ y2="56.907249"
+ x2="57.639572"
+ y1="56.907249"
+ x1="35.077618"
+ id="linearGradient6891"
+ xlink:href="#linearGradient6661"
+ inkscape:collect="always" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient6661"
+ id="linearGradient2385"
+ x1="11.670013"
+ y1="22.729551"
+ x2="45.708981"
+ y2="22.729551"
+ gradientUnits="userSpaceOnUse" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient6661"
+ id="linearGradient2387"
+ x1="8.2346859"
+ y1="22.035364"
+ x2="46.419407"
+ y2="22.035364"
+ gradientUnits="userSpaceOnUse" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient6661"
+ id="linearGradient2389"
+ x1="10.684234"
+ y1="21.707344"
+ x2="43.823338"
+ y2="21.707344"
+ gradientUnits="userSpaceOnUse" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient6661"
+ id="linearGradient2391"
+ x1="10.007514"
+ y1="21.862101"
+ x2="47.762268"
+ y2="21.862101"
+ gradientUnits="userSpaceOnUse" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient6661"
+ id="linearGradient2393"
+ x1="8.3331928"
+ y1="22.63376"
+ x2="45.827827"
+ y2="22.63376"
+ gradientUnits="userSpaceOnUse" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient6661"
+ id="linearGradient2395"
+ x1="8.894763"
+ y1="23.77869"
+ x2="45.472706"
+ y2="23.77869"
+ gradientUnits="userSpaceOnUse" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient6661"
+ id="linearGradient2397"
+ x1="6.3566332"
+ y1="23.83882"
+ x2="44.533714"
+ y2="23.83882"
+ gradientUnits="userSpaceOnUse" />
+ </defs>
+ <g
+ transform="translate(0.26838843)"
+ id="g6945">
+ <path
+ sodipodi:nodetypes="cccccccccccccc"
+ inkscape:connector-curvature="0"
+ id="path7039"
+ d="M 24.751559,35.188201 C 20.548343,35.085377 16.21866,35.317651 10.655241,34.806768 6.4505782,31.266278 1.2240415,15.495669 3.4561535,7.6570539 3.9719681,7.3735286 4.5106026,6.9074442 4.8911412,7.7061269 L 5.838493,13.046052 c 0.9606117,-1.366443 4.719863,-3.2330998 6.188013,-0.692271 3.253564,-2.196048 4.212055,-1.564794 6.551115,-0.474054 2.470569,-2.0860048 3.992587,-1.791212 5.931741,-0.221514 2.586417,-1.636583 3.093761,-2.4593768 6.340873,-0.249152 1.4804,-1.9177197 5.681366,-1.315831 6.919712,0.674627 0.774531,-1.539848 4.123488,-1.700815 5.447819,0.749211 l 1.3684,-4.892276 c 0.528081,-0.7162826 1.056162,-0.529191 1.584243,-0.4274876 1.80114,7.9361196 -3.336135,24.0620566 -7.417103,27.1746826"
+ style="fill:#1a1a1a;fill-opacity:1;stroke:none;stroke-width:1.11789;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
+ <path
+ sodipodi:nodetypes="ccccccc"
+ inkscape:connector-curvature="0"
+ id="path7043"
+ d="m 10.655241,34.433746 c 0.702845,3.654335 0.568786,3.651199 1.553949,7.305535 4.532078,2.014902 8.033022,2.24062 12.191526,2.336567 4.158506,-0.07705 8.816246,-0.69469 12.602277,-2.443145 0.985164,-3.654336 1.021271,-3.591562 1.771048,-7.198957 l -14.034727,0.480532 z"
+ style="fill:#1a1a1a;fill-opacity:1;stroke:none;stroke-width:0.604799;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
+ <path
+ sodipodi:nodetypes="cc"
+ inkscape:connector-curvature="0"
+ id="path7051"
+ d="m 12.340248,14.849097 c 0.171935,8.101282 2.345076,10.382055 4.511299,18.05599"
+ style="fill:none;fill-opacity:1;stroke:url(#linearGradient2385);stroke-width:1.12886;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
+ <path
+ sodipodi:nodetypes="cc"
+ inkscape:connector-curvature="0"
+ id="path7053"
+ d="M 36.420905,14.878887 C 35.802669,22.916646 34.62102,25.251423 32.6245,32.938332"
+ style="fill:none;fill-opacity:1;stroke:url(#linearGradient2393);stroke-width:1.12886;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
+ <path
+ sodipodi:nodetypes="cc"
+ inkscape:connector-curvature="0"
+ id="path7088"
+ d="m 30.415374,14.90829 c -0.618235,8.037759 -0.722892,12.755544 -1.653266,17.225727"
+ style="fill:none;fill-opacity:1;stroke:url(#linearGradient2391);stroke-width:1.12886;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
+ <path
+ style="fill:none;fill-opacity:1;stroke:url(#linearGradient2387);stroke-width:1.12886;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ d="m 18.429755,14.735366 c 0.596372,9.419037 1.840121,14.769424 2.340482,17.609774"
+ id="path7090"
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="cc" />
+ <path
+ sodipodi:nodetypes="cc"
+ inkscape:connector-curvature="0"
+ id="path7092"
+ d="M 24.656725,32.07496 24.576443,14.941426"
+ style="fill:none;fill-opacity:1;stroke:url(#linearGradient2389);stroke-width:1.12886;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
+ <path
+ style="fill:url(#linearGradient6891);fill-opacity:1;stroke:none;stroke-width:2.12427;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ d="m 36.780533,35.854108 c -8.223002,-1.926882 -13.064949,-2.829191 -23.96389,-0.0127 l 1.065029,4.678872 c 7.197508,-3.430543 14.395016,-3.32854 21.592525,0 z"
+ id="path7094"
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="ccccc" />
+ <path
+ sodipodi:nodetypes="cc"
+ inkscape:connector-curvature="0"
+ id="path7051-0"
+ d="m 7.1318325,15.729605 c 1.0557333,8.434127 2.9154725,10.358064 5.8638915,18.064591"
+ style="display:inline;fill:none;fill-opacity:1;stroke:url(#linearGradient2397);stroke-width:1.12886;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
+ <path
+ style="display:inline;fill:none;fill-opacity:1;stroke:url(#linearGradient2395);stroke-width:1.12886;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ d="m 42.089373,15.30897 c -1.188501,8.129043 -3.528562,13.315756 -5.78336,18.672251"
+ id="path7645"
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="cc" />
+ </g>
+</svg>
--- /dev/null
+../Shako/bc.svg
\ No newline at end of file
--- /dev/null
+../Shako/be.svg
\ No newline at end of file
--- /dev/null
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://creativecommons.org/ns#"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:xlink="http://www.w3.org/1999/xlink"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ inkscape:version="1.0 (4035a4fb49, 2020-05-01)"
+ sodipodi:docname="bKingDynasty.svg"
+ id="svg4798"
+ version="1.1"
+ viewBox="0 0 50 50"
+ clip-rule="evenodd"
+ fill-rule="evenodd"
+ image-rendering="optimizeQuality"
+ shape-rendering="geometricPrecision"
+ height="177.17"
+ width="177.17">
+ <metadata
+ id="metadata4802">
+ <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
+ inkscape:document-rotation="0"
+ inkscape:snap-nodes="false"
+ inkscape:current-layer="g6945"
+ inkscape:window-maximized="1"
+ inkscape:window-y="-8"
+ inkscape:window-x="1912"
+ inkscape:cy="-829.43924"
+ inkscape:cx="-1876.8767"
+ inkscape:zoom="0.2354761"
+ showgrid="false"
+ id="namedview4800"
+ inkscape:window-height="1017"
+ inkscape:window-width="1920"
+ inkscape:pageshadow="2"
+ inkscape:pageopacity="0"
+ guidetolerance="10"
+ gridtolerance="10"
+ objecttolerance="10"
+ borderopacity="1"
+ bordercolor="#666666"
+ pagecolor="#ffffff" />
+ <defs
+ id="defs4788">
+ <linearGradient
+ id="linearGradient6661"
+ inkscape:collect="always">
+ <stop
+ id="stop6657"
+ offset="0"
+ style="stop-color:#ffffff;stop-opacity:1;" />
+ <stop
+ id="stop6659"
+ offset="1"
+ style="stop-color:#b3b3b3;stop-opacity:1" />
+ </linearGradient>
+ <linearGradient
+ gradientUnits="userSpaceOnUse"
+ x2="77.64"
+ x1="21.376"
+ id="0">
+ <stop
+ id="stop4783"
+ stop-color="#fff" />
+ <stop
+ id="stop4785"
+ stop-opacity="0"
+ stop-color="#fff"
+ offset="1" />
+ </linearGradient>
+ <linearGradient
+ gradientUnits="userSpaceOnUse"
+ y2="37.469002"
+ x2="77.760002"
+ y1="37.220001"
+ x1="21.129999"
+ id="0-3"
+ gradientTransform="translate(50.708427,-1.9548155)">
+ <stop
+ id="stop5461"
+ stop-color="#fff" />
+ <stop
+ id="stop5463"
+ stop-opacity="0"
+ stop-color="#fff"
+ offset="1" />
+ </linearGradient>
+ <linearGradient
+ gradientUnits="userSpaceOnUse"
+ x2="77.639999"
+ x1="21.375999"
+ id="0-2"
+ gradientTransform="translate(-54.458725,-1.3555716)">
+ <stop
+ id="stop6058"
+ stop-color="#fff" />
+ <stop
+ id="stop6060"
+ stop-opacity="0"
+ stop-color="#fff"
+ offset="1" />
+ </linearGradient>
+ <linearGradient
+ gradientUnits="userSpaceOnUse"
+ y2="42.911686"
+ x2="66.719086"
+ y1="42.911686"
+ x1="38.532917"
+ id="linearGradient2375"
+ xlink:href="#linearGradient6661"
+ inkscape:collect="always" />
+ <linearGradient
+ gradientUnits="userSpaceOnUse"
+ y2="43.054028"
+ x2="65.753746"
+ y1="43.054028"
+ x1="38.016586"
+ id="linearGradient2371"
+ xlink:href="#linearGradient6661"
+ inkscape:collect="always" />
+ <linearGradient
+ gradientUnits="userSpaceOnUse"
+ y2="44.177059"
+ x2="67.144081"
+ y1="44.177059"
+ x1="33.101456"
+ id="linearGradient2361"
+ xlink:href="#linearGradient6661"
+ inkscape:collect="always" />
+ <linearGradient
+ gradientUnits="userSpaceOnUse"
+ y2="43.88435"
+ x2="66.596489"
+ y1="43.88435"
+ x1="38.470192"
+ id="linearGradient2377"
+ xlink:href="#linearGradient6661"
+ inkscape:collect="always" />
+ <linearGradient
+ gradientUnits="userSpaceOnUse"
+ y2="36.387611"
+ x2="67.033264"
+ y1="36.387611"
+ x1="32.930401"
+ id="linearGradient2373"
+ xlink:href="#linearGradient6661"
+ inkscape:collect="always" />
+ <linearGradient
+ gradientTransform="matrix(1.1507613,0,0,1.1507613,-7.0739765,-4.6754817)"
+ gradientUnits="userSpaceOnUse"
+ y2="56.907249"
+ x2="57.639572"
+ y1="56.907249"
+ x1="41.291985"
+ id="linearGradient6891-9"
+ xlink:href="#linearGradient6661"
+ inkscape:collect="always" />
+ <linearGradient
+ gradientTransform="translate(49.09174,-1.6184006)"
+ id="0-9"
+ x1="21.129999"
+ y1="37.220001"
+ x2="77.760002"
+ y2="37.469002"
+ gradientUnits="userSpaceOnUse">
+ <stop
+ stop-color="#fff"
+ id="stop871" />
+ <stop
+ offset="1"
+ stop-color="#fff"
+ stop-opacity="0"
+ id="stop873" />
+ </linearGradient>
+ <linearGradient
+ gradientUnits="userSpaceOnUse"
+ y2="50.209568"
+ x2="71.770737"
+ y1="50.209568"
+ x1="37.951797"
+ id="linearGradient1528"
+ xlink:href="#linearGradient6661"
+ inkscape:collect="always" />
+ </defs>
+ <g
+ transform="translate(0.26838843)"
+ id="g6945">
+ <g
+ transform="matrix(0.98459729,0,0,0.98459729,-20.431178,-23.446678)"
+ id="g2299">
+ <path
+ style="fill:#1a1a1a;fill-opacity:1;stroke:none;stroke-width:1.15365;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ d="m 46.213835,59.000144 c -4.337713,-0.106113 -8.805939,0.133592 -14.547379,-0.393637 -3.058483,-4.365293 -7.669835,-20.160522 -6.59342,-27.568225 8.133658,-4.954192 35.196714,-5.374469 41.572966,0.164983 1.076415,7.407703 -2.923901,22.91519 -5.982386,27.280482"
+ id="path7039-8"
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="ccccc" />
+ <path
+ style="fill:#1a1a1a;fill-opacity:1;stroke:none;stroke-width:0.624152;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ d="m 31.268708,57.912189 c 0.303804,3.771269 0.984734,7.129255 2.001421,10.900524 4.677097,2.079376 8.290066,2.312316 12.581636,2.411335 4.291572,-0.07951 9.098353,-0.716921 13.005531,-2.521323 1.016687,-3.771269 2.010052,-7.461209 2.358048,-11.14409 l -15.014146,1.158821 z"
+ id="path7043-7"
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="ccccccc" />
+ <path
+ style="fill:none;fill-opacity:1;stroke:url(#linearGradient2375);stroke-width:1.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ d="M 50.482706,37.019363 48.205791,48.804009"
+ id="path7088-5"
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="cc" />
+ <path
+ sodipodi:nodetypes="cc"
+ inkscape:connector-curvature="0"
+ id="path7090-2"
+ d="m 42.155289,37.590934 1.420123,10.899289"
+ style="fill:none;fill-opacity:1;stroke:url(#linearGradient2371);stroke-width:1.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
+ <path
+ style="fill:none;fill-opacity:1;stroke:url(#linearGradient2361);stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ d="m 27.587757,32.692194 c 2.719145,3.377296 3.372058,4.14335 4.059665,5.285163 1.61736,6.763907 2.151767,10.795959 3.985826,17.621844"
+ id="path8714"
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="ccc" />
+ <path
+ sodipodi:nodetypes="ccc"
+ inkscape:connector-curvature="0"
+ id="path8716"
+ d="m 64.33054,32.766367 c -4.844145,6.252297 -2.797097,3.680309 -3.484705,4.822122 -1.622031,6.851331 -2.218557,11.130813 -3.849643,17.899632"
+ style="fill:none;fill-opacity:1;stroke:url(#linearGradient2377);stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
+ <path
+ style="fill:none;fill-opacity:1;stroke:url(#linearGradient2373);stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ d="m 31.66271,37.833441 c 5.355804,-5.075728 7.816328,-1.155853 10.503881,-0.329965 3.303382,-3.841535 4.660648,-3.822774 8.4727,-0.241951 2.914409,-2.839336 7.470518,-2.8371 10.2803,0.241951"
+ id="path8718"
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="cccc" />
+ <path
+ style="display:inline;fill:url(#linearGradient1528);fill-opacity:1;stroke:none;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ d="m 39.634611,54.527495 c -2.592578,-3.914807 -2.216812,-4.060205 2.728774,-4.998649 -0.745516,-5.002369 7.894027,-4.950468 7.477698,0.03804 4.271036,0.485973 5.581838,0.95303 2.944534,4.710005 -5.800933,-1.120762 -7.751755,-1.117524 -13.151006,0.250604 z"
+ id="path8722"
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="ccccc" />
+ <path
+ sodipodi:nodetypes="ccccc"
+ inkscape:connector-curvature="0"
+ id="path7094-2"
+ d="M 58.637571,59.313059 C 48.48942,55.685265 43.57537,56.316347 33.713117,59.406889 c 0.179676,2.723504 0.658479,4.616447 1.390628,7.892424 7.798065,-3.274844 14.509744,-3.48095 21.836824,-0.277475 0.889405,-3.211349 1.228218,-4.68228 1.697002,-7.708779 z"
+ style="fill:url(#linearGradient6891-9);fill-opacity:1;stroke:none;stroke-width:2.30152;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
+ <path
+ id="ellipse1567"
+ style="opacity:1;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1.53582;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;paint-order:normal"
+ sodipodi:type="arc"
+ sodipodi:cx="45.869301"
+ sodipodi:cy="60.699242"
+ sodipodi:rx="2.7839172"
+ sodipodi:ry="2.7839172"
+ sodipodi:start="0"
+ sodipodi:end="6.0213859"
+ sodipodi:open="true"
+ sodipodi:arc-type="arc"
+ d="m 48.653218,60.699242 a 2.7839172,2.7839172 0 0 1 -2.60184,2.777956 2.7839172,2.7839172 0 0 1 -2.942178,-2.414582 2.7839172,2.7839172 0 0 1 2.216986,-3.093799 2.7839172,2.7839172 0 0 1 3.232172,2.009894" />
+ </g>
+ </g>
+</svg>
--- /dev/null
+../bn.svg
\ No newline at end of file
--- /dev/null
+<?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="svg25581"
+ sodipodi:docname="bChariot.svg"
+ inkscape:version="1.0 (4035a4fb49, 2020-05-01)">
+ <metadata
+ id="metadata25585">
+ <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="1920"
+ inkscape:window-height="1017"
+ id="namedview25583"
+ showgrid="false"
+ showguides="true"
+ inkscape:zoom="0.9419044"
+ inkscape:cx="-306.46825"
+ inkscape:cy="-14.350321"
+ inkscape:window-x="1912"
+ inkscape:window-y="-8"
+ inkscape:window-maximized="1"
+ inkscape:current-layer="svg25581"
+ inkscape:document-rotation="0" />
+ <defs
+ id="defs25573">
+ <inkscape:path-effect
+ effect="mirror_symmetry"
+ start_point="25.052965,26.906777"
+ end_point="25.052965,46.948547"
+ center_point="25.052965,36.927662"
+ id="path-effect35483"
+ is_visible="true"
+ mode="free"
+ discard_orig_path="false"
+ fuse_paths="false"
+ oposite_fuse="false" />
+ <inkscape:path-effect
+ effect="mirror_symmetry"
+ start_point="54.02291,56.37239"
+ end_point="54.02291,91.212206"
+ center_point="54.02291,73.792298"
+ id="path-effect34810"
+ is_visible="true"
+ mode="free"
+ discard_orig_path="false"
+ fuse_paths="true"
+ oposite_fuse="false" />
+ <inkscape:path-effect
+ effect="mirror_symmetry"
+ start_point="54.050553,59.606528"
+ end_point="54.050553,67.15242"
+ center_point="54.050553,63.379474"
+ id="path-effect34808"
+ is_visible="true"
+ mode="free"
+ discard_orig_path="false"
+ fuse_paths="false"
+ oposite_fuse="false" />
+ <inkscape:path-effect
+ effect="mirror_symmetry"
+ start_point="54.005451,54.541048"
+ end_point="54.005451,69.79768"
+ center_point="54.005451,62.169364"
+ id="path-effect34806"
+ is_visible="true"
+ mode="free"
+ discard_orig_path="false"
+ fuse_paths="true"
+ oposite_fuse="false" />
+ <inkscape:path-effect
+ effect="mirror_symmetry"
+ start_point="54.015927,28.828759"
+ end_point="54.015927,67.965665"
+ center_point="54.015927,48.397212"
+ id="path-effect34804"
+ is_visible="true"
+ mode="free"
+ discard_orig_path="false"
+ fuse_paths="true"
+ oposite_fuse="false" />
+ <linearGradient
+ id="0"
+ x1="21.253"
+ y1="37.22"
+ x2="77.64"
+ y2="37.35"
+ gradientUnits="userSpaceOnUse">
+ <stop
+ stop-color="#fff"
+ id="stop25568" />
+ <stop
+ offset="1"
+ stop-color="#fff"
+ stop-opacity="0"
+ id="stop25570" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient2229"
+ inkscape:collect="always">
+ <stop
+ id="stop2225"
+ offset="0"
+ style="stop-color:#ffffff;stop-opacity:1" />
+ <stop
+ id="stop2227"
+ offset="1"
+ style="stop-color:#808080;stop-opacity:1" />
+ </linearGradient>
+ <linearGradient
+ gradientUnits="userSpaceOnUse"
+ y2="14.893166"
+ x2="45.383141"
+ y1="14.893166"
+ x1="15.755494"
+ id="linearGradient8050"
+ xlink:href="#linearGradient2229"
+ inkscape:collect="always" />
+ <linearGradient
+ gradientUnits="userSpaceOnUse"
+ y2="34.546993"
+ x2="42.508442"
+ y1="34.546993"
+ x1="18.080154"
+ id="linearGradient8098"
+ xlink:href="#linearGradient2229"
+ inkscape:collect="always" />
+ <linearGradient
+ gradientUnits="userSpaceOnUse"
+ y2="34.60239"
+ x2="42.431862"
+ y1="34.60239"
+ x1="18.209703"
+ id="linearGradient8106"
+ xlink:href="#linearGradient2229"
+ inkscape:collect="always" />
+ <linearGradient
+ gradientUnits="userSpaceOnUse"
+ y2="34.708321"
+ x2="42.170368"
+ y1="34.708321"
+ x1="18.312302"
+ id="linearGradient8108"
+ xlink:href="#linearGradient2229"
+ inkscape:collect="always" />
+ <linearGradient
+ gradientUnits="userSpaceOnUse"
+ y2="34.60239"
+ x2="42.545734"
+ y1="34.60239"
+ x1="18.307699"
+ id="linearGradient8110"
+ xlink:href="#linearGradient2229"
+ inkscape:collect="always" />
+ <linearGradient
+ gradientUnits="userSpaceOnUse"
+ y2="34.60239"
+ x2="42.223335"
+ y1="34.60239"
+ x1="18.04747"
+ id="linearGradient8112"
+ xlink:href="#linearGradient2229"
+ inkscape:collect="always" />
+ </defs>
+ <g
+ id="g1989"
+ transform="translate(-1.7566349,-1.5486635)">
+ <path
+ id="path5178"
+ style="display:inline;fill:#1f1a17;fill-opacity:1;stroke:none;stroke-width:1.48477px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+ d="m 40.540446,8.0903131 c -6.606313,1.3891001 -14.065157,2.0360919 -18.145634,8.9940329 -1.568004,2.673723 -1.502989,4.307473 -3.023453,7.518328 0,0.721834 -2.581559,6.327784 -2.590492,7.411867 -1.151775,0.07695 -4.814604,-0.581951 -6.734063,0.598785 -2.018442,1.241628 -4.2276949,4.089546 -3.7553985,6.036456 3.1579671,0.44797 30.6851105,0.466537 36.6605285,0.09931 2.682932,-0.89482 3.399646,-23.251581 4.519815,-30.9860818 -2.497032,0.00449 -3.774485,-0.047968 -6.931303,0.3273029 z"
+ sodipodi:nodetypes="csccacccc" />
+ <circle
+ style="display:inline;fill:#1f1a17;fill-opacity:1;stroke:none;stroke-width:3.58161;stroke-linecap:round;stroke-linejoin:round"
+ id="path979"
+ cx="27.725443"
+ cy="34.546993"
+ r="14.910736" />
+ <circle
+ r="11.022715"
+ cy="34.546993"
+ cx="27.725443"
+ id="circle995"
+ style="display:inline;fill:none;stroke:url(#linearGradient8098);stroke-width:2.64769;stroke-linecap:round;stroke-linejoin:round" />
+ <path
+ style="display:inline;fill:url(#linearGradient8050);stroke:none;stroke-width:1.14367px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;fill-opacity:1"
+ d="m 24.018205,20.208693 2.289767,-0.109033 c 2.952063,-6.372037 11.421144,-6.820772 18.590715,-7.85063 l 0.27259,-2.671392 c -6.802828,0.762036 -6.272731,0.597337 -10.631053,1.799102 -4.83508,1.333226 -9.659128,3.816276 -10.522019,8.831953 z"
+ id="path1023"
+ sodipodi:nodetypes="ccccsc" />
+ <path
+ style="display:inline;fill:url(#linearGradient8110);stroke:none;stroke-width:0.399487px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;fill-opacity:1"
+ d="m 16.877615,33.561227 h 21.695661 v 2.082327 H 16.877615 Z"
+ id="path1027" />
+ <path
+ id="path1035"
+ d="m 20.791084,26.195602 15.341149,15.34115 -1.472427,1.472427 -15.341149,-15.34115 z"
+ style="display:inline;fill:url(#linearGradient8112);stroke:none;stroke-width:0.399487px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;fill-opacity:1" />
+ <path
+ style="display:inline;fill:url(#linearGradient8108);stroke:none;stroke-width:0.399487px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;fill-opacity:1"
+ d="m 34.659806,26.195602 -15.341149,15.34115 1.472427,1.472427 15.341149,-15.34115 z"
+ id="path1037" />
+ <path
+ id="path1039"
+ d="M 28.766608,23.754559 V 45.450222 H 26.684281 V 23.754559 Z"
+ style="display:inline;fill:url(#linearGradient8106);stroke:none;stroke-width:0.399487px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;fill-opacity:1" />
+ </g>
+</svg>
--- /dev/null
+<?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"
+ inkscape:version="1.0 (4035a4fb49, 2020-05-01)"
+ sodipodi:docname="bSoldier.svg"
+ id="svg4260"
+ version="1.1"
+ viewBox="0 0 50 50"
+ clip-rule="evenodd"
+ fill-rule="evenodd"
+ image-rendering="optimizeQuality"
+ shape-rendering="geometricPrecision"
+ height="177.17"
+ width="177.17">
+ <metadata
+ id="metadata4266">
+ <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>
+ <defs
+ id="defs4264">
+ <inkscape:path-effect
+ effect="mirror_symmetry"
+ start_point="-103.61098,-3.3341898"
+ end_point="-103.61098,147.39645"
+ center_point="-103.61098,72.03113"
+ id="path-effect4256"
+ is_visible="true"
+ lpeversion="1"
+ mode="free"
+ discard_orig_path="false"
+ fuse_paths="true"
+ oposite_fuse="false"
+ split_items="false" />
+ </defs>
+ <sodipodi:namedview
+ inkscape:current-layer="svg4260"
+ inkscape:window-maximized="1"
+ inkscape:window-y="-8"
+ inkscape:window-x="-8"
+ inkscape:cy="85.458226"
+ inkscape:cx="28.637861"
+ inkscape:zoom="0.30620309"
+ showgrid="false"
+ id="namedview4262"
+ inkscape:window-height="1017"
+ inkscape:window-width="1920"
+ inkscape:pageshadow="2"
+ inkscape:pageopacity="0"
+ guidetolerance="10"
+ gridtolerance="10"
+ objecttolerance="10"
+ borderopacity="1"
+ bordercolor="#666666"
+ pagecolor="#ffffff" />
+ <path
+ inkscape:path-effect="#path-effect4256"
+ inkscape:original-d="m -103.25391,-3.5996094 c -5.26569,35.1774994 -49.68654,67.5615074 -63.05981,78.5738504 23.39443,-1.486303 41.84318,-5.969219 49.87893,-5.905687 -3.78985,50.016626 -46.94654,39.365156 -46.95985,71.818166 33.16237,0 80.332873,-0.35352 115.787218,-0.35352 -0.006,-11.54918 -5.174356,-28.25734 -18.099609,-30.09179 -44.142829,-81.107313 6.642805,-43.090295 -37.546879,-114.0410194 z"
+ transform="matrix(0.28221482,0,0,0.28221482,54.240554,7.3625466)"
+ id="path2176-6"
+ style="fill:#1f1a17;fill-opacity:1;stroke:none;stroke-width:3.59623;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;paint-order:stroke fill markers"
+ d="m -103.61098,-1.5197891 c -6.65027,34.3678821 -49.59346,65.6990721 -62.70274,76.4940301 23.39443,-1.486303 41.84318,-5.969219 49.87893,-5.905687 -3.78985,50.016626 -46.94654,39.365156 -46.95985,71.818166 17.32685,0 38.47778,-0.0965 59.78366,-0.18868 21.305878,0.0922 42.456814,0.18868 59.78366,0.18868 -0.01331,-32.45301 -43.17,-21.80154 -46.95985,-71.818166 8.03575,-0.06353 26.4845,4.419384 49.87893,5.905687 -13.109279,-10.794958 -56.052469,-42.126148 -62.70274,-76.4940301 z"
+ sodipodi:nodetypes="ccccccc" />
+</svg>
// Some variants have more than sizeY reserve pieces (Clorange: 10)
const reserveSquareNb = Math.max(sizeY, V.RESERVE_PIECES.length);
let myReservePiecesArray = [];
- for (let i = 0; i < V.RESERVE_PIECES.length; i++) {
- const qty = this.vr.reserve[playingColor][V.RESERVE_PIECES[i]];
- myReservePiecesArray.push(
+ if (!!this.vr.reserve[playingColor]) {
+ for (let i = 0; i < V.RESERVE_PIECES.length; i++) {
+ const qty = this.vr.reserve[playingColor][V.RESERVE_PIECES[i]];
+ myReservePiecesArray.push(
+ h(
+ "div",
+ {
+ "class": { board: true, ["board" + reserveSquareNb]: true },
+ attrs: { id: getSquareId({ x: sizeX + shiftIdx, y: i }) },
+ style: { opacity: qty > 0 ? 1 : 0.35 }
+ },
+ [
+ h("img", {
+ // NOTE: class "reserve" not used currently
+ "class": { piece: true, reserve: true },
+ attrs: {
+ src:
+ "/images/pieces/" +
+ this.vr.getReservePpath(i, playingColor, orientation) +
+ ".svg"
+ }
+ }),
+ h(
+ "sup",
+ {
+ "class": { "reserve-count": true },
+ style: { top: "calc(100% + 5px)" }
+ },
+ [ qty ]
+ )
+ ]
+ )
+ );
+ }
+ }
+ let oppReservePiecesArray = [];
+ const oppCol = V.GetOppCol(playingColor);
+ if (!!this.vr.reserve[oppCol]) {
+ for (let i = 0; i < V.RESERVE_PIECES.length; i++) {
+ const qty = this.vr.reserve[oppCol][V.RESERVE_PIECES[i]];
+ oppReservePiecesArray.push(
+ h(
+ "div",
+ {
+ "class": { board: true, ["board" + reserveSquareNb]: true },
+ attrs: { id: getSquareId({ x: sizeX + (1 - shiftIdx), y: i }) },
+ style: { opacity: qty > 0 ? 1 : 0.35 }
+ },
+ [
+ h("img", {
+ "class": { piece: true, reserve: true },
+ attrs: {
+ src:
+ "/images/pieces/" +
+ this.vr.getReservePpath(i, oppCol, orientation) +
+ ".svg"
+ }
+ }),
+ h(
+ "sup",
+ {
+ "class": { "reserve-count": true },
+ style: { top: "calc(100% + 5px)" }
+ },
+ [ qty ]
+ )
+ ]
+ )
+ );
+ }
+ }
+ const myReserveTop = (
+ (playingColor == 'w' && orientation == 'b') ||
+ (playingColor == 'b' && orientation == 'w')
+ );
+ const hasReserveTop = (
+ (myReserveTop && !!this.vr.reserve[playingColor]) ||
+ (!myReserveTop && !!this.vr.reserve[oppCol])
+ );
+ // "var" because must be reachable from outside this block
+ var hasReserveBottom = (
+ (myReserveTop && !!this.vr.reserve[oppCol]) ||
+ (!myReserveTop && !!this.vr.reserve[playingColor])
+ );
+ // Center reserves, assuming same number of pieces for each side:
+ const nbReservePieces = myReservePiecesArray.length;
+ const marginLeft =
+ ((100 - nbReservePieces * (100 / reserveSquareNb)) / 2) + "%";
+ if (hasReserveTop) {
+ var reserveTop =
h(
"div",
{
- "class": { board: true, ["board" + reserveSquareNb]: true },
- attrs: { id: getSquareId({ x: sizeX + shiftIdx, y: i }) },
- style: { opacity: qty > 0 ? 1 : 0.35 }
+ "class": {
+ game: true,
+ "reserve-div": true
+ },
+ style: {
+ "margin-left": marginLeft
+ }
},
[
- h("img", {
- // NOTE: class "reserve" not used currently
- "class": { piece: true, reserve: true },
- attrs: {
- src:
- "/images/pieces/" +
- this.vr.getReservePpath(i, playingColor, orientation) +
- ".svg"
- }
- }),
h(
- "sup",
+ "div",
{
- "class": { "reserve-count": true },
- style: { top: "calc(100% + 5px)" }
+ "class": {
+ row: true,
+ "reserve-row": true
+ }
},
- [ qty ]
+ myReserveTop ? myReservePiecesArray : oppReservePiecesArray
)
]
- )
- );
+ );
}
- let oppReservePiecesArray = [];
- const oppCol = V.GetOppCol(playingColor);
- for (let i = 0; i < V.RESERVE_PIECES.length; i++) {
- const qty = this.vr.reserve[oppCol][V.RESERVE_PIECES[i]];
- oppReservePiecesArray.push(
+ if (hasReserveBottom) {
+ var reserveBottom =
h(
"div",
{
- "class": { board: true, ["board" + reserveSquareNb]: true },
- attrs: { id: getSquareId({ x: sizeX + (1 - shiftIdx), y: i }) },
- style: { opacity: qty > 0 ? 1 : 0.35 }
+ "class": {
+ game: true,
+ "reserve-div": true
+ },
+ style: {
+ "margin-left": marginLeft
+ }
},
[
- h("img", {
- "class": { piece: true, reserve: true },
- attrs: {
- src:
- "/images/pieces/" +
- this.vr.getReservePpath(i, oppCol, orientation) +
- ".svg"
- }
- }),
h(
- "sup",
+ "div",
{
- "class": { "reserve-count": true },
- style: { top: "calc(100% + 5px)" }
+ "class": {
+ row: true,
+ "reserve-row": true
+ }
},
- [ qty ]
+ myReserveTop ? oppReservePiecesArray : myReservePiecesArray
)
]
- )
- );
+ );
}
- const myReserveTop = (
- (playingColor == 'w' && orientation == 'b') ||
- (playingColor == 'b' && orientation == 'w')
- );
- // Center reserves, assuming same number of pieces for each side:
- const nbReservePieces = myReservePiecesArray.length;
- const marginLeft =
- ((100 - nbReservePieces * (100 / reserveSquareNb)) / 2) + "%";
- const reserveTop =
- h(
- "div",
- {
- "class": {
- game: true,
- "reserve-div": true
- },
- style: {
- "margin-left": marginLeft
- }
- },
- [
- h(
- "div",
- {
- "class": {
- row: true,
- "reserve-row": true
- }
- },
- myReserveTop ? myReservePiecesArray : oppReservePiecesArray
- )
- ]
- );
- var reserveBottom =
- h(
- "div",
- {
- "class": {
- game: true,
- "reserve-div": true
- },
- style: {
- "margin-left": marginLeft
- }
- },
- [
- h(
- "div",
- {
- "class": {
- row: true,
- "reserve-row": true
- }
- },
- myReserveTop ? oppReservePiecesArray : myReservePiecesArray
- )
- ]
- );
- elementArray.push(reserveTop);
+ if (hasReserveTop) elementArray.push(reserveTop);
}
elementArray.push(gameDiv);
- if (!!this.vr.reserve) elementArray.push(reserveBottom);
+ if (!!this.vr.reserve && hasReserveBottom)
+ elementArray.push(reserveBottom);
const boardElt = document.getElementById("gamePosition");
// boardElt might be undefine (at first drawing)
if (this.choices.length > 0 && !!boardElt) {
touchend: this.mouseup
}
};
- } else {
+ }
+ else {
onEvents = {
on: {
mousedown: this.mousedown,
"Dangerous collisions": "Dangerous collisions",
"Double moves (v1)": "Double moves (v1)",
"Double moves (v2)": "Double moves (v2)",
+ "Dynasty versus Kingdom": "Dynasty versus Kingdom",
"Each piece is unique": "Each piece is unique",
+ "Empire versus Kingdom": "Empire versus Kingdom",
"Enter the disco": "Enter the disco",
"Exchange pieces' positions": "Exchange pieces' positions",
"Exotic captures": "Exotic captures",
"Dangerous collisions": "Colisiones peligrosas",
"Double moves (v1)": "Jugadas doble (v1)",
"Double moves (v2)": "Jugadas doble (v2)",
+ "Dynasty versus Kingdom": "Dinastía contra Reino",
"Each piece is unique": "Cada pieza es única",
+ "Empire versus Kingdom": "Imperio contra Reino",
"Enter the disco": "Entrar en la discoteca",
"Exchange pieces' positions": "Intercambiar posiciones de piezas",
"Exotic captures": "Capturas exóticas",
"Dangerous collisions": "Collisions dangeureuses",
"Double moves (v1)": "Coups doubles (v1)",
"Double moves (v2)": "Coups doubles (v2)",
+ "Dynasty versus Kingdom": "Dynastie contre Royaume",
"Each piece is unique": "Chaque pièce est unique",
+ "Empire versus Kingdom": "Empire contre Royaume",
"Enter the disco": "Entrez dans la boîte",
"Exchange pieces' positions": "Échangez les positions des pièces",
"Exotic captures": "Captures exotiques",
p.boxed TODO
+
+p.
+ Synochess is a chess variant designed in 2020 by Couch Tomato.
+ The idea of the game was to create a variant where the western chess army
+ can fight against the xiangqi or Chinese chess army in a fair manner.
+ In this game, the white army represents the western chess side and is
+ called the Kingdom, while the black army represents an amalgamation of
+ xiangqi and janggi (Korean chess) and is called the Dynasty.
+
+p.
+ The name Synochess is based off an earlier name, Sinochess, but it was
+ changed as the Dynasty became less "Sino" (as in Chinese) and more a
+ mixture of Chinese and Korean. Instead, the prefix syn- means together,
+ and the game represents two different historic branches of chess coming
+ together into one.
+
+ul
+ li The Kingdom (white) always moves first.
+ li The Dynasty (black) cannot castle.
+ li.
+ Kingdom pawns can only promote to their own pieces (queen, rook, knight,
+ bishop). Dynasty soldiers do not promote.
+
+h3 Special Rules
+
+ul
+ li.
+ King Faceoff — As in Xiangqi, Kings may not face each other
+ (on a file or rank) without intervening pieces.
+ li.
+ Reinforcement Soldiers — Black starts with two soldiers in hand.
+ Instead of moving a piece on the board, the Dynasty player can drop a
+ soldier onto an open square in rank 5 (Dynasty's 4th rank).
+ li.
+ Campmate — A king that reaches the final rank (without moving
+ into check) wins the game.
+ li.
+ Stalemate — As in Xiangqi, stalemates
+ and moves repetitions are a loss.
+
+h3 Dynasty Pieces
+
+p.
+ There are four new units unique to the Dynasty: 6 Soldiers (2 start in
+ hand), 2 Cannons, 2 Elephants, and 1 Advisor.
+p.
+ The Chariots are equal to the Rooks and use the same abbreviation (R)
+ — the difference is purely cosmetic. Similarly, the Kings are the
+ same, but just appear different.
+
+p.
+ Details and diagrams of each piece are below.
+
+p TODO: continue
+
+p https://www.pychess.org/variant/synochess
-
var varlist = [
"Colorbound",
+ "Empire",
"Horde",
- "Orda"
+ "Orda",
+ "Synochess"
]
ul
for v in varlist
"Sittuyin",
"Xiangqi"
]
- //Chinese chess (TODO)
ul
for v in varlist
li #[a(href="/#/variants/"+v) #{v}]
-
var varlist = [
"Colorbound",
+ "Empire",
"Horde",
- "Orda"
+ "Orda",
+ "Synochess"
]
ul
for v in varlist
"Sittuyin",
"Xiangqi"
]
- //Chinese chess (TODO)
ul
for v in varlist
li #[a(href="/#/variants/"+v) #{v}]
-
var varlist = [
"Colorbound",
+ "Empire",
"Horde",
- "Orda"
+ "Orda",
+ "Synochess"
]
ul
for v in varlist
"Sittuyin",
"Xiangqi"
]
- //Chinese chess (TODO)
ul
for v in varlist
li #[a(href="/#/variants/"+v) #{v}]
}
getPotentialMovesFrom([x, y]) {
- if (x >= V.size.x) {
+ if (x >= V.size.x)
// Reserves, outside of board: x == sizeX(+1)
return this.getReserveMoves([x, y]);
- }
// Standard moves
return super.getPotentialMovesFrom([x, y]);
}
-import { ChessRules } from "@/base_rules";
+import { ChessRules, Move, PiPo } from "@/base_rules";
export class SynochessRules extends ChessRules {
- // TODO
+ static get LoseOnRepetition() {
+ return true;
+ }
+
+ static IsGoodFlags(flags) {
+ // Only white can castle
+ return !!flags.match(/^[a-z]{2,2}$/);
+ }
+
+ static IsGoodFen(fen) {
+ if (!ChessRules.IsGoodFen(fen)) return false;
+ const fenParsed = V.ParseFen(fen);
+ // 5) Check reserves
+ if (!fenParsed.reserve || !fenParsed.reserve.match(/^[0-2]$/))
+ return false;
+ return true;
+ }
+
+ static ParseFen(fen) {
+ const fenParts = fen.split(" ");
+ return Object.assign(
+ ChessRules.ParseFen(fen),
+ { reserve: fenParts[5] }
+ );
+ }
+
+ static GenRandInitFen(randomness) {
+ if (randomness == 0)
+ return "rneakenr/8/1c4c1/1ss2ss1/8/8/PPPPPPPP/RNBQKBNR w 0 ah - 2";
+
+ // Mapping kingdom --> dynasty:
+ const piecesMap = {
+ 'r': 'r',
+ 'n': 'n',
+ 'b': 'e',
+ 'q': 'a',
+ 'k': 'k'
+ };
+
+ // Always symmetric (randomness = 1), because open files.
+ const baseFen = ChessRules.GenRandInitFen(1);
+ return (
+ baseFen.substr(0, 8).split("").map(p => piecesMap[p]).join("") +
+ "/8/1c4c1/1ss2ss1/" + baseFen.substr(22, 28) + " - 2"
+ );
+ }
+
+ getReserveFen() {
+ return (!!this.reserve ? this.reserve["b"][V.SOLDIER] : 0);
+ }
+
+ getFen() {
+ return super.getFen() + " " + this.getReserveFen();
+ }
+
+ getFenForRepeat() {
+ return super.getFenForRepeat() + "_" + this.getReserveFen();
+ }
+
+ setOtherVariables(fen) {
+ super.setOtherVariables(fen);
+ // Also init reserve (used by the interface to show landable soldiers)
+ const reserve = parseInt(V.ParseFen(fen).reserve, 10);
+ if (reserve > 0) this.reserve = { 'b': { [V.SOLDIER]: reserve } };
+ }
+
+ getColor(i, j) {
+ if (i >= V.size.x) return 'b';
+ return this.board[i][j].charAt(0);
+ }
+
+ getPiece(i, j) {
+ if (i >= V.size.x) return V.SOLDIER;
+ return this.board[i][j].charAt(1);
+ }
+
+ getReservePpath(index, color) {
+ // Only one piece type: soldier
+ return "Synochess/" + color + V.SOLDIER;
+ }
+
+ static get RESERVE_PIECES() {
+ return [V.SOLDIER];
+ }
+
+ getReserveMoves(x) {
+ const color = this.turn;
+ if (!this.reserve || this.reserve[color][V.SOLDIER] == 0) return [];
+ let moves = [];
+ for (let i = 0; i < V.size.y; i++) {
+ if (this.board[3][i] == V.EMPTY) {
+ let mv = new Move({
+ appear: [
+ new PiPo({
+ x: 3,
+ y: i,
+ c: color,
+ p: V.SOLDIER
+ })
+ ],
+ vanish: [],
+ start: { x: x, y: 0 }, //a bit artificial...
+ end: { x: 3, y: i }
+ });
+ moves.push(mv);
+ }
+ }
+ return moves;
+ }
+
+ getPpath(b) {
+ return (ChessRules.PIECES.includes(b[1]) ? "" : "Synochess/") + b;
+ }
+
+ getFlagsFen() {
+ return this.castleFlags['w'].map(V.CoordToColumn).join("");
+ }
+
+ setFlags(fenflags) {
+ this.castleFlags = { 'w': [-1, -1] };
+ for (let i = 0; i < 2; i++)
+ this.castleFlags['w'][i] = V.ColumnToCoord(fenflags.charAt(i));
+ }
+
+ static get ELEPHANT() {
+ return "e";
+ }
+
+ static get CANNON() {
+ return "c";
+ }
+
+ static get SOLDIER() {
+ return "s";
+ }
+
+ static get ADVISOR() {
+ return "a";
+ }
+
+ static get PIECES() {
+ return (
+ ChessRules.PIECES.concat([V.ELEPHANT, V.ADVISOR, V.SOLDIER, V.CANNON])
+ );
+ }
+
+ static get steps() {
+ return Object.assign(
+ {},
+ ChessRules.steps,
+ {
+ e: [
+ [-1, -1],
+ [-1, 1],
+ [1, -1],
+ [1, 1],
+ [-2, -2],
+ [-2, 2],
+ [2, -2],
+ [2, 2]
+ ]
+ }
+ );
+ }
+
+ getPotentialMovesFrom(sq) {
+ if (sq[0] >= V.size.x)
+ // Reserves, outside of board: x == sizeX(+1)
+ return this.getReserveMoves(sq[0]);
+ let moves = [];
+ const piece = this.getPiece(sq[0], sq[1]);
+ switch (piece) {
+ case V.CANNON:
+ moves = this.getPotentialCannonMoves(sq);
+ break;
+ case V.ELEPHANT:
+ moves = this.getPotentialElephantMoves(sq);
+ break;
+ case V.ADVISOR:
+ moves = this.getPotentialAdvisorMoves(sq);
+ break;
+ case V.SOLDIER:
+ moves = this.getPotentialSoldierMoves(sq);
+ break;
+ default:
+ moves = super.getPotentialMovesFrom(sq);
+ }
+ if (
+ piece != V.KING &&
+ this.kingPos['w'][0] != this.kingPos['b'][0] &&
+ this.kingPos['w'][1] != this.kingPos['b'][1]
+ ) {
+ return moves;
+ }
+ // TODO: from here, copy/paste from EmpireChess
+ // TODO: factor two next "if" into one (rank/column...)
+ if (this.kingPos['w'][1] == this.kingPos['b'][1]) {
+ const colKing = this.kingPos['w'][1];
+ let intercept = 0; //count intercepting pieces
+ let [kingPos1, kingPos2] = [this.kingPos['w'][0], this.kingPos['b'][0]];
+ if (kingPos1 > kingPos2) [kingPos1, kingPos2] = [kingPos2, kingPos1];
+ for (let i = kingPos1 + 1; i < kingPos2; i++) {
+ if (this.board[i][colKing] != V.EMPTY) intercept++;
+ }
+ if (intercept >= 2) return moves;
+ // intercept == 1 (0 is impossible):
+ // Any move not removing intercept is OK
+ return moves.filter(m => {
+ return (
+ // From another column?
+ m.start.y != colKing ||
+ // From behind a king? (including kings themselves!)
+ m.start.x <= kingPos1 ||
+ m.start.x >= kingPos2 ||
+ // Intercept piece moving: must remain in-between
+ (
+ m.end.y == colKing &&
+ m.end.x > kingPos1 &&
+ m.end.x < kingPos2
+ )
+ );
+ });
+ }
+ if (this.kingPos['w'][0] == this.kingPos['b'][0]) {
+ const rowKing = this.kingPos['w'][0];
+ let intercept = 0; //count intercepting pieces
+ let [kingPos1, kingPos2] = [this.kingPos['w'][1], this.kingPos['b'][1]];
+ if (kingPos1 > kingPos2) [kingPos1, kingPos2] = [kingPos2, kingPos1];
+ for (let i = kingPos1 + 1; i < kingPos2; i++) {
+ if (this.board[rowKing][i] != V.EMPTY) intercept++;
+ }
+ if (intercept >= 2) return moves;
+ // intercept == 1 (0 is impossible):
+ // Any move not removing intercept is OK
+ return moves.filter(m => {
+ return (
+ // From another row?
+ m.start.x != rowKing ||
+ // From "behind" a king? (including kings themselves!)
+ m.start.y <= kingPos1 ||
+ m.start.y >= kingPos2 ||
+ // Intercept piece moving: must remain in-between
+ (
+ m.end.x == rowKing &&
+ m.end.y > kingPos1 &&
+ m.end.y < kingPos2
+ )
+ );
+ });
+ }
+ // piece == king: check only if move.end.y == enemy king column,
+ // or if move.end.x == enemy king rank.
+ const color = this.getColor(sq[0], sq[1]);
+ const oppCol = V.GetOppCol(color);
+ // check == -1 if (row, or col) unchecked, 1 if checked and occupied,
+ // 0 if checked and clear
+ let check = [-1, -1];
+ return moves.filter(m => {
+ if (
+ m.end.y != this.kingPos[oppCol][1] &&
+ m.end.x != this.kingPos[oppCol][0]
+ ) {
+ return true;
+ }
+ // TODO: factor two next "if"...
+ if (m.end.x == this.kingPos[oppCol][0]) {
+ if (check[0] < 0) {
+ // Do the check:
+ check[0] = 0;
+ let [kingPos1, kingPos2] =
+ [this.kingPos[color][1], this.kingPos[oppCol][1]];
+ if (kingPos1 > kingPos2) [kingPos1, kingPos2] = [kingPos2, kingPos1];
+ for (let i = kingPos1 + 1; i < kingPos2; i++) {
+ if (this.board[m.end.x][i] != V.EMPTY) {
+ check[0]++;
+ break;
+ }
+ }
+ return check[0] == 1;
+ }
+ // Check already done:
+ return check[0] == 1;
+ }
+ //if (m.end.y == this.kingPos[oppCol][1]) //true...
+ if (check[1] < 0) {
+ // Do the check:
+ check[1] = 0;
+ let [kingPos1, kingPos2] =
+ [this.kingPos[color][0], this.kingPos[oppCol][0]];
+ if (kingPos1 > kingPos2) [kingPos1, kingPos2] = [kingPos2, kingPos1];
+ for (let i = kingPos1 + 1; i < kingPos2; i++) {
+ if (this.board[i][m.end.y] != V.EMPTY) {
+ check[1]++;
+ break;
+ }
+ }
+ return check[1] == 1;
+ }
+ // Check already done:
+ return check[1] == 1;
+ });
+ }
+
+ getPotentialAdvisorMoves(sq) {
+ return super.getSlideNJumpMoves(
+ sq, V.steps[V.ROOK].concat(V.steps[V.BISHOP]), "oneStep");
+ }
+
+ getPotentialKingMoves([x, y]) {
+ if (this.getColor(x, y) == 'w') return super.getPotentialKingMoves([x, y]);
+ // Dynasty doesn't castle:
+ return super.getSlideNJumpMoves(
+ [x, y],
+ V.steps[V.ROOK].concat(V.steps[V.BISHOP]),
+ "oneStep"
+ );
+ }
+
+ getPotentialSoldierMoves([x, y]) {
+ const c = this.getColor(x, y);
+ const shiftX = (c == 'w' ? -1 : 1);
+ const lastRank = (c == 'w' && x == 0 || c == 'b' && x == 9);
+ let steps = [];
+ if (!lastRank) steps.push([shiftX, 0]);
+ if (y > 0) steps.push([0, -1]);
+ if (y < 9) steps.push([0, 1]);
+ return super.getSlideNJumpMoves([x, y], steps, "oneStep");
+ }
+
+ getPotentialElephantMoves([x, y]) {
+ return this.getSlideNJumpMoves([x, y], V.steps[V.ELEPHANT], "oneStep");
+ }
+
+ // NOTE: (mostly) duplicated from Shako (TODO?)
+ getPotentialCannonMoves([x, y]) {
+ const oppCol = V.GetOppCol(this.turn);
+ let moves = [];
+ // Look in every direction until an obstacle (to jump) is met
+ for (const step of V.steps[V.ROOK]) {
+ let i = x + step[0];
+ let j = y + step[1];
+ while (V.OnBoard(i, j) && this.board[i][j] == V.EMPTY) {
+ moves.push(this.getBasicMove([x, y], [i, j]));
+ i += step[0];
+ j += step[1];
+ }
+ // Then, search for an enemy (if jumped piece isn't a cannon)
+ if (V.OnBoard(i, j) && this.getPiece(i, j) != V.CANNON) {
+ i += step[0];
+ j += step[1];
+ while (V.OnBoard(i, j) && this.board[i][j] == V.EMPTY) {
+ i += step[0];
+ j += step[1];
+ }
+ if (V.OnBoard(i, j) && this.getColor(i, j) == oppCol)
+ moves.push(this.getBasicMove([x, y], [i, j]));
+ }
+ }
+ return moves;
+ }
+
+ isAttacked(sq, color) {
+ return (
+ super.isAttackedByRook(sq, color) ||
+ super.isAttackedByKnight(sq, color) ||
+ super.isAttackedByKing(sq, color) ||
+ (
+ color == 'w' &&
+ (
+ super.isAttackedByPawn(sq, color) ||
+ super.isAttackedByBishop(sq, color) ||
+ super.isAttackedByQueen(sq, color)
+ )
+ ) ||
+ (
+ color == 'b' &&
+ (
+ this.isAttackedByCannon(sq, color) ||
+ this.isAttackedBySoldier(sq, color) ||
+ this.isAttackedByAdvisor(sq, color) ||
+ this.isAttackedByElephant(sq, color)
+ )
+ )
+ );
+ }
+
+ // NOTE: (mostly) duplicated from Shako (TODO?)
+ isAttackedByCannon([x, y], color) {
+ // Reversed process: is there an obstacle in line,
+ // and a cannon next in the same line?
+ for (const step of V.steps[V.ROOK]) {
+ let [i, j] = [x+step[0], y+step[1]];
+ while (V.OnBoard(i, j) && this.board[i][j] == V.EMPTY) {
+ i += step[0];
+ j += step[1];
+ }
+ if (V.OnBoard(i, j) && this.getPiece(i, j) != V.CANNON) {
+ // Keep looking in this direction
+ i += step[0];
+ j += step[1];
+ while (V.OnBoard(i, j) && this.board[i][j] == V.EMPTY) {
+ i += step[0];
+ j += step[1];
+ }
+ if (
+ V.OnBoard(i, j) &&
+ this.getPiece(i, j) == V.CANNON &&
+ this.getColor(i, j) == color
+ ) {
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+
+ isAttackedByAdvisor(sq, color) {
+ return (
+ super.isAttackedBySlideNJump(
+ sq, color, V.ADVISOR,
+ V.steps[V.ROOK].concat(V.steps[V.BISHOP]), "oneStep"
+ )
+ );
+ }
+
+ isAttackedByElephant(sq, color) {
+ return (
+ this.isAttackedBySlideNJump(
+ sq, color, V.ELEPHANT, V.steps[V.ELEPHANT], "oneStep"
+ )
+ );
+ }
+
+ isAttackedBySoldier([x, y], color) {
+ const shiftX = (color == 'w' ? 1 : -1); //shift from king
+ return super.isAttackedBySlideNJump(
+ [x, y], color, V.SOLDIER, [[shiftX, 0], [0, 1], [0, -1]], "oneStep");
+ }
+
+ getAllValidMoves() {
+ let moves = super.getAllPotentialMoves();
+ const color = this.turn;
+ if (!!this.reserve && color == 'b')
+ moves = moves.concat(this.getReserveMoves(V.size.x + 1));
+ return this.filterValid(moves);
+ }
+
+ atLeastOneMove() {
+ if (!super.atLeastOneMove()) {
+ if (!!this.reserve && this.turn == 'b') {
+ let moves = this.filterValid(this.getReserveMoves(V.size.x + 1));
+ if (moves.length > 0) return true;
+ }
+ return false;
+ }
+ return true;
+ }
+
+ getCurrentScore() {
+ // Turn has changed:
+ const color = V.GetOppCol(this.turn);
+ const lastRank = (color == 'w' ? 0 : 7);
+ if (this.kingPos[color][0] == lastRank)
+ // The opposing edge is reached!
+ return color == "w" ? "1-0" : "0-1";
+ if (this.atLeastOneMove()) return "*";
+ // Game over
+ const oppCol = this.turn;
+ return (oppCol == "w" ? "0-1" : "1-0");
+ }
+
+ updateCastleFlags(move, piece) {
+ // Only white can castle:
+ const firstRank = 0;
+ if (piece == V.KING && move.appear[0].c == 'w')
+ this.castleFlags['w'] = [8, 8];
+ else if (
+ move.start.x == firstRank &&
+ this.castleFlags['w'].includes(move.start.y)
+ ) {
+ const flagIdx = (move.start.y == this.castleFlags['w'][0] ? 0 : 1);
+ this.castleFlags['w'][flagIdx] = 8;
+ }
+ else if (
+ move.end.x == firstRank &&
+ this.castleFlags['w'].includes(move.end.y)
+ ) {
+ const flagIdx = (move.end.y == this.castleFlags['w'][0] ? 0 : 1);
+ this.castleFlags['w'][flagIdx] = 8;
+ }
+ }
+
+ postPlay(move) {
+ super.postPlay(move);
+ // After black move, turn == 'w':
+ if (!!this.reserve && this.turn == 'w' && move.vanish.length == 0)
+ if (--this.reserve['b'][V.SOLDIER] == 0) this.reserve = null;
+ }
+
+ postUndo(move) {
+ super.postUndo(move);
+ if (this.turn == 'b' && move.vanish.length == 0) {
+ if (!this.reserve) this.reserve = { 'b': { [V.SOLDIER]: 1 } };
+ else this.reserve['b'][V.SOLDIER]++;
+ }
+ }
+
+ static get VALUES() {
+ return Object.assign(
+ {
+ s: 2,
+ a: 2.75,
+ e: 2.75,
+ c: 3
+ },
+ ChessRules.VALUES
+ );
+ }
+
+ static get SEARCH_DEPTH() {
+ return 2;
+ }
+
+ evalPosition() {
+ let evaluation = super.evalPosition();
+ if (this.turn == 'b')
+ // Add reserves:
+ evaluation += this.reserve['b'][V.SOLDIER] * V.VALUES[V.SOLDIER];
+ return evaluation;
+ }
};
('Doublemove2', 'Double moves (v2)'),
('Dynamo', 'Push and pull'),
('Eightpieces', 'Each piece is unique'),
+ ('Empire', 'Empire versus Kingdom'),
('Enpassant', 'Capture en passant'),
('Evolution', 'Faster development'),
('Extinction', 'Capture all of a kind'),
('Suction', 'Attract opposite king'),
('Swap', 'Dangerous captures'),
('Switching', 'Exchange pieces'' positions'),
+ ('Synochess', 'Dynasty versus Kingdom'),
('Takenmake', 'Prolongated captures'),
('Teleport', 'Reposition pieces'),
('Tencubed', 'Four new pieces'),