Add Hex: almost fine, still some issues with SVG + rescaling
authorBenjamin Auder <benjamin.auder@somewhere>
Wed, 1 Jun 2022 15:21:20 +0000 (17:21 +0200)
committerBenjamin Auder <benjamin.auder@somewhere>
Wed, 1 Jun 2022 15:21:20 +0000 (17:21 +0200)
25 files changed:
app.js
base_rules.js
common.css
variants.js
variants/Absorption/class.js
variants/Atomic/class.js
variants/Balanced/class.js
variants/Benedict/class.js
variants/Cannibal/class.js
variants/Capture/class.js
variants/Crazyhouse/class.js
variants/Cylinder/class.js
variants/Dark/class.js
variants/Doublemove/class.js
variants/Hex/Hex_board_centered.svg [deleted file]
variants/Hex/Regular_hexagon.svg [deleted file]
variants/Hex/class.js
variants/Hex/rules.html [new file with mode: 0644]
variants/Hex/style.css
variants/Madrasi/class.js
variants/Progressive/class.js
variants/Recycle/class.js
variants/Rifle/class.js
variants/Teleport/class.js
variants/Zen/class.js

diff --git a/app.js b/app.js
index 17fe770..c0c74c0 100644 (file)
--- a/app.js
+++ b/app.js
@@ -136,7 +136,7 @@ function prepareOptions() {
       <div class="option-select">
         <label for="var_${select.variable}">${select.label}</label>
         <div class="select">
-          <select id="var_${select.variable}" data-numeric="1">` +
+          <select id="var_${select.variable}">` +
           select.options.map(option => { return `
             <option
               value="${option.value}"
@@ -151,25 +151,16 @@ function prepareOptions() {
       </div>`;
     }).join("");
   }
-  if (V.Options.check) {
-    optHtml += V.Options.check.map(check => { return `
-      <div class="option-check">
-        <label class="checkbox">
-          <input id="var_${check.variable}"
-                 type="checkbox"${check.defaut ? " checked" : ""}/>
-          <span class="spacer"></span>
-          <span>${check.label}</span>
-        </label>
-      </div>`;
-    }).join("");
-  }
   if (V.Options.input) {
     optHtml += V.Options.input.map(input => { return `
       <div class="option-input">
         <label class="input">
           <input id="var_${input.variable}"
                  type="${input.type}"
-                 content="${input.defaut}"/>
+                 ${input.type == "checkbox" && input.defaut
+                   ? "checked"
+                   : 'value="' + input.defaut + '"'}
+          />
           <span class="spacer"></span>
           <span>${input.label}</span>
         </label>
@@ -200,15 +191,15 @@ function getGameLink() {
   const vname = $.getElementById("selectVariant").value;
   const color = $.getElementById("selectColor").value;
   for (const select of $.querySelectorAll("#gameOptions select")) {
-    let value = select.value;
-    if (select.attributes["data-numeric"])
-      value = parseInt(value, 10);
-    if (value)
-      options[ select.id.split("_")[1] ] = value;
+    const value = parseInt(select.value, 10) || select.value;
+    options[ select.id.split("_")[1] ] = value;
   }
-  for (const check of $.querySelectorAll("#gameOptions input")) {
-    if (check.checked)
-      options[ check.id.split("_")[1] ] = check.checked;
+  for (const input of $.querySelectorAll("#gameOptions input")) {
+    const variable = input.id.split("_")[1];
+    if (input.type == "number")
+      options[variable] = parseInt(input.value, 10); //TODO: real numbers?
+    else if (input.type == "checkbox")
+      options[variable] = input.checked;
   }
   send("creategame", {
     vname: vname,
index 20ff25e..33411f0 100644 (file)
@@ -372,6 +372,11 @@ export default class ChessRules {
 
   constructor(o) {
     this.options = o.options;
+    // Fill missing options (always the case if random challenge)
+    (V.Options.select || []).concat(V.Options.input || []).forEach(opt => {
+      if (this.options[opt.variable] === undefined)
+        this.options[opt.variable] = opt.defaut;
+    });
     this.playerColor = o.color;
     this.afterPlay = o.afterPlay; //trigger some actions after playing a move
 
@@ -528,7 +533,8 @@ export default class ChessRules {
     this.initMouseEvents();
     const chessboard =
       document.getElementById(this.containerId).querySelector(".chessboard");
-    new ResizeObserver(this.rescale).observe(chessboard);
+    // TODO: calling with "this" seems required by Hex. Understand why...
+    new ResizeObserver(() => this.rescale(this)).observe(chessboard);
   }
 
   re_drawBoardElements() {
@@ -583,8 +589,7 @@ export default class ChessRules {
     let board = `
       <svg
         viewBox="0 0 80 80"
-        class="chessboard_SVG">
-      <g>`;
+        class="chessboard_SVG">`;
     for (let i=0; i < this.size.x; i++) {
       for (let j=0; j < this.size.y; j++) {
         const ii = (flipped ? this.size.x - 1 - i : i);
@@ -593,16 +598,18 @@ export default class ChessRules {
         if (this.enlightened && !this.enlightened[ii][jj])
           classes += " in-shadow";
         // NOTE: x / y reversed because coordinates system is reversed.
-        board += `<rect
-          class="${classes}"
-          id="${this.coordsToId({x: ii, y: jj})}"
-          width="10"
-          height="10"
-          x="${10*j}"
-          y="${10*i}" />`;
+        board += `
+          <rect
+            class="${classes}"
+            id="${this.coordsToId({x: ii, y: jj})}"
+            width="10"
+            height="10"
+            x="${10*j}"
+            y="${10*i}"
+          />`;
       }
     }
-    board += "</g></svg>";
+    board += "</svg>";
     return board;
   }
 
@@ -767,48 +774,50 @@ export default class ChessRules {
   }
 
   // After resize event: no need to destroy/recreate pieces
-  rescale() {
-    const container = document.getElementById(this.containerId);
+  rescale(self) {
+    const container = document.getElementById(self.containerId);
     if (!container)
       return; //useful at initial loading
     let chessboard = container.querySelector(".chessboard");
-    const r = chessboard.getBoundingClientRect();
-    const newRatio = r.width / r.height;
-    let newWidth = r.width,
-        newHeight = r.height;
-    if (newRatio > this.size.ratio) {
-      newWidth = r.height * this.size.ratio;
-      chessboard.style.width = newWidth + "px";
-    }
-    else if (newRatio < this.size.ratio) {
-      newHeight = r.width / this.size.ratio;
-      chessboard.style.height = newHeight + "px";
-    }
+    let r = chessboard.getBoundingClientRect();
+    let [newWidth, newHeight] = [r.width, r.height];
+    // Stay in window:
+    if (newWidth > window.innerWidth)
+      newWidth = window.innerWidth;
+    if (newHeight > window.innerHeight)
+      newHeight = window.innerHeight;
+    const newRatio = newWidth / newHeight;
+    if (newRatio > self.size.ratio)
+      newWidth = newHeight * self.size.ratio;
+    else if (newRatio < self.size.ratio)
+      newHeight = newWidth / self.size.ratio;
+    chessboard.style.width = newWidth + "px";
+    chessboard.style.height = newHeight + "px";
     const newX = (window.innerWidth - newWidth) / 2;
     chessboard.style.left = newX + "px";
     const newY = (window.innerHeight - newHeight) / 2;
     chessboard.style.top = newY + "px";
     const newR = {x: newX, y: newY, width: newWidth, height: newHeight};
-    const pieceWidth = this.getPieceWidth(newWidth);
+    const pieceWidth = self.getPieceWidth(newWidth);
     // NOTE: next "if" for variants which use squares filling
     // instead of "physical", moving pieces
     if (this.g_pieces) {
-      for (let i=0; i < this.size.x; i++) {
-        for (let j=0; j < this.size.y; j++) {
-          if (this.g_pieces[i][j]) {
+      for (let i=0; i < self.size.x; i++) {
+        for (let j=0; j < self.size.y; j++) {
+          if (self.g_pieces[i][j]) {
             // NOTE: could also use CSS transform "scale"
-            this.g_pieces[i][j].style.width = pieceWidth + "px";
-            this.g_pieces[i][j].style.height = pieceWidth + "px";
-            const [ip, jp] = this.getPixelPosition(i, j, newR);
+            self.g_pieces[i][j].style.width = pieceWidth + "px";
+            self.g_pieces[i][j].style.height = pieceWidth + "px";
+            const [ip, jp] = self.getPixelPosition(i, j, newR);
             // Translate coordinates to use chessboard as reference:
-            this.g_pieces[i][j].style.transform =
+            self.g_pieces[i][j].style.transform =
               `translate(${ip - newX}px,${jp - newY}px)`;
           }
         }
       }
     }
-    if (this.hasReserve)
-      this.rescaleReserve(newR);
+    if (self.hasReserve)
+      self.rescaleReserve(newR);
   }
 
   rescaleReserve(r) {
index 7096ff8..e359955 100644 (file)
@@ -231,15 +231,19 @@ button.cancel-something {
   text-align: center;
 }
 
-.option-select, .option-check {
+.option-select, .option-input {
   margin: 15px 0 0 0;
 }
 
-.option-check {
+.option-input {
   display: inline-block;
   margin-right: 10px;
 }
 
+.option-input input[type=number] {
+  width: 64px;
+}
+
 .btn-wrap {
   text-align: center;
 }
index f543d3f..3fced3d 100644 (file)
@@ -67,7 +67,7 @@ const variants = [
 //  {name: 'Grasshopper', desc: 'Long jumps over pieces'},
 //  {name: 'Gridolina', desc: 'Jump the borders'},
 //  {name: 'Hamilton', desc: 'Walk on a graph'},
-  {names: 'Hex', desc: 'Connect sides'},
+  {name: 'Hex', desc: 'Connect sides'},
 //  {name: 'Hidden', desc: 'Unidentified pieces', disp: 'Strate-Go'},
 //  {name: 'Hiddenqueen', desc: 'Queen disguised as a pawn', disp: 'Hidden Queen'},
 //  {name: 'Hoppelpoppel', desc: 'Knibis and Bisknis', disp: 'Hoppel-Poppel'},
index 9fe43aa..3e8d391 100644 (file)
@@ -5,7 +5,6 @@ export default class AbsorptionRules extends ChessRules {
   static get Options() {
     return {
       select: C.Options.select,
-      check: [],
       styles: [
         "balance",
         "capture",
index 924d222..cc339ff 100644 (file)
@@ -7,16 +7,18 @@ export default class AtomicRules extends ChessRules {
   static get Options() {
     return {
       select: C.Options.select,
-      check: [
+      input: [
         {
           label: "Balanced",
-          defaut: false,
-          variable: "rempawn"
+          variable: "rempawn",
+          type: "checkbox",
+          defaut: false
         },
         {
           label: "Falling pawn",
-          defaut: false,
-          variable: "pawnfall"
+          variable: "pawnfall",
+          type: "checkbox",
+          defaut: false
         }
       ],
       styles: C.Options.styles.filter(s => s != "atomic")
index 5550b0d..a8294bc 100644 (file)
@@ -5,7 +5,7 @@ export default class BalancedRules extends ChessRules {
   static get Options() {
     return {
       select: C.Options.select,
-      check: C.Options.check,
+      input: C.Options.input,
       styles: C.Options.styles.filter(s => s != "balance")
     };
   }
index 68667e1..bbaf8e9 100644 (file)
@@ -6,7 +6,6 @@ export default class BenedictRules extends ChessRules {
   static get Options() {
     return {
       select: C.Options.select,
-      check: [],
       styles: [
         "balance",
         "cylinder",
index e75aa20..8d8cef3 100644 (file)
@@ -5,7 +5,7 @@ export default class CannibalRules extends ChessRules {
   static get Options() {
     return {
       select: C.Options.select,
-      check: C.Options.check,
+      input: C.Options.input,
       styles: C.Options.styles.filter(s => s != "cannibal")
     };
   }
index 31264a1..3a0a22e 100644 (file)
@@ -5,7 +5,7 @@ export default class CaptureRules extends ChessRules {
   static get Options() {
     return {
       select: C.Options.select,
-      check: C.Options.check,
+      input: C.Options.input,
       styles: C.Options.styles.filter(s => s != "capture")
     };
   }
index f01bd0c..41503dd 100644 (file)
@@ -5,7 +5,7 @@ export default class CrazyhouseRules extends ChessRules {
   static get Options() {
     return {
       select: C.Options.select,
-      check: C.Options.check,
+      input: C.Options.input,
       styles: C.Options.styles.filter(s => s != "crazyhouse")
     };
   }
index c35c346..998453e 100644 (file)
@@ -5,7 +5,7 @@ export default class CylinderRules extends ChessRules {
   static get Options() {
     return {
       select: C.Options.select,
-      check: C.Options.check,
+      input: C.Options.input,
       styles: C.Options.styles.filter(s => s != "cylinder")
     };
   }
index ad23cbc..65679fe 100644 (file)
@@ -5,7 +5,7 @@ export default class DarkRules extends ChessRules {
   static get Options() {
     return {
       select: C.Options.select,
-      check: C.Options.check,
+      input: C.Options.input,
       styles: C.Options.styles.filter(s => s != "dark")
     };
   }
index 551ae09..2606d4f 100644 (file)
@@ -5,7 +5,7 @@ export default class DoublemoveRules extends ChessRules {
   static get Options() {
     return {
       select: C.Options.select,
-      check: C.Options.check,
+      input: C.Options.input,
       styles: C.Options.styles.filter(s => s != "doublemove")
     };
   }
diff --git a/variants/Hex/Hex_board_centered.svg b/variants/Hex/Hex_board_centered.svg
deleted file mode 100644 (file)
index ee5d40b..0000000
+++ /dev/null
@@ -1,28 +0,0 @@
-<?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"
-   viewBox="0 0 860 1340"
-   height="1340"
-   width="860"
-   xml:space="preserve"
-   version="1.1"
-   id="svg2"><metadata
-     id="metadata8"><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="defs6" /><g
-     transform="matrix(1.25,0,0,-1.25,0,1340)"
-     id="g10"><path
-       id="path12"
-       style="fill:none;stroke:#000000;stroke-width:0.72000003;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
-       d="m -42.969999,1134.05 773.939999,0 0,-1196.100005 -773.939998,0 0,1196.100005 z M 643.07,505.55 l -17.64,30.48 -35.16,0 -17.58,-30.48 17.58,-30.42 35.22,0 17.58,30.42 z m 0,60.96 -17.64,30.48 -35.16,0 -17.58,-30.48 17.58,-30.48 35.22,0 17.58,30.48 z m 0,60.96 -17.64,30.42 -35.16,0 -17.58,-30.48 17.58,-30.42 35.22,0 17.58,30.48 z m 0,60.9 -17.64,30.48 -35.16,0 -17.58,-30.48 17.58,-30.48 35.22,0 17.58,30.48 z m 0,60.96 -17.64,30.48 -35.16,-0.06 -17.58,-30.42 17.58,-30.48 35.22,0 17.58,30.48 z m 0,60.9 -17.64,30.48 -35.16,0 -17.58,-30.48 17.58,-30.48 35.22,0 17.58,30.48 z m 0,60.96 -17.64,30.48 -35.16,0 -17.58,-30.48 17.58,-30.48 35.22,0 17.58,30.48 z m 0,60.9 -17.64,30.48 -35.16,0 -17.58,-30.48 17.58,-30.42 35.22,0 17.58,30.42 z m 0,60.96 -17.64,30.48 -35.16,0 -17.58,-30.48 17.58,-30.48 35.22,0 17.58,30.48 z m -105.54,-548.4 -17.64,30.42 -35.16,0 -17.58,-30.48 17.58,-30.42 35.16,0 17.64,30.48 z m 0,60.9 -17.64,30.48 -35.16,0 -17.58,-30.48 17.58,-30.48 35.16,0 17.64,30.48 z m 0,60.96 -17.64,30.42 -35.16,0 -17.58,-30.42 17.58,-30.48 35.16,0 17.64,30.48 z m 0,60.9 -17.64,30.48 -35.16,0 -17.58,-30.48 17.58,-30.48 35.16,0 17.64,30.48 z m 0,60.96 -17.64,30.48 -35.16,0 -17.58,-30.48 17.58,-30.48 35.16,0 17.64,30.48 z m 0,60.9 -17.64,30.48 -35.16,0 -17.58,-30.48 17.58,-30.42 35.16,0 17.64,30.42 z m 0,60.96 -17.64,30.48 -35.16,0 -17.58,-30.48 17.58,-30.48 35.16,0 17.64,30.48 z m 0,60.96 -17.64,30.42 -35.16,0 -17.58,-30.48 17.58,-30.42 35.16,0 17.64,30.48 z m 0,60.9 -17.64,30.48 -35.16,0 -17.58,-30.48 17.58,-30.48 35.16,0 17.64,30.48 z m 52.74,-457.02 -17.58,30.48 -35.22,0 -17.58,-30.48 17.64,-30.42 35.16,0 17.58,30.42 z m 0,60.96 -17.58,30.48 -35.22,0 -17.58,-30.48 17.64,-30.48 35.16,0 17.58,30.48 z m 0,60.96 -17.58,30.42 -35.22,0 -17.58,-30.48 17.64,-30.42 35.16,0 17.58,30.48 z m 0,60.9 -17.58,30.48 -35.22,0 -17.58,-30.48 17.64,-30.48 35.16,0 17.58,30.48 z m 0,60.96 -17.58,30.48 -35.22,-0.06 -17.58,-30.42 17.64,-30.48 35.16,0 17.58,30.48 z m 0,60.9 -17.58,30.48 -35.22,0 -17.58,-30.48 17.64,-30.48 35.16,0 17.58,30.48 z m 0,60.96 -17.58,30.48 -35.22,0 -17.58,-30.48 17.64,-30.48 35.16,0 17.58,30.48 z m 0,60.9 -17.58,30.48 -35.22,0 -17.58,-30.48 17.64,-30.42 35.16,0 17.58,30.42 z m 0,60.96 -17.58,30.48 -35.22,0 -17.58,-30.48 17.64,-30.48 35.16,0 17.58,30.48 z m -158.34,-578.88 -17.58,30.48 -35.16,-0.06 -17.58,-30.42 17.58,-30.48 35.16,0 17.58,30.48 z m 0,60.9 -17.58,30.48 -35.16,0 -17.58,-30.48 17.58,-30.48 35.16,0 17.58,30.48 z m 0,60.96 -17.58,30.48 -35.16,0 -17.58,-30.48 17.58,-30.48 35.16,0 17.58,30.48 z m 0,60.9 -17.58,30.48 -35.16,0 -17.58,-30.48 17.58,-30.42 35.16,0 17.58,30.42 z m 0,60.96 -17.58,30.48 -35.16,0 -17.58,-30.48 17.58,-30.48 35.16,0 17.58,30.48 z m 0,60.96 -17.58,30.42 -35.16,0 -17.58,-30.48 17.58,-30.42 35.16,0 17.58,30.48 z m 0,60.9 -17.58,30.48 -35.16,0 -17.58,-30.48 17.58,-30.48 35.16,0 17.58,30.48 z m 0,60.96 -17.58,30.42 -35.16,0 -17.58,-30.42 17.58,-30.48 35.16,0 17.58,30.48 z m 0,60.9 -17.58,30.48 -35.16,0 -17.58,-30.48 17.58,-30.42 35.16,0 17.58,30.42 z m 52.8,-456.96 -17.58,30.42 -35.22,0 -17.58,-30.42 17.58,-30.48 35.22,0 17.58,30.48 z m 0,60.9 -17.58,30.48 -35.22,0 -17.58,-30.48 17.58,-30.48 35.22,0 17.58,30.48 z m 0,60.96 -17.58,30.42 -35.22,0 -17.58,-30.42 17.58,-30.48 35.22,0 17.58,30.48 z m 0,60.9 -17.58,30.48 -35.22,0 -17.58,-30.48 17.58,-30.48 35.22,0 17.58,30.48 z m 0,60.96 -17.58,30.48 -35.22,0 -17.58,-30.48 17.58,-30.48 35.22,0 17.58,30.48 z m 0,60.9 -17.58,30.48 -35.22,0 -17.58,-30.48 17.58,-30.42 35.22,0 17.58,30.42 z m 0,60.96 -17.58,30.48 -35.22,0 -17.58,-30.48 17.58,-30.48 35.22,0 17.58,30.48 z m 0,60.96 -17.58,30.42 -35.22,0 -17.58,-30.48 17.58,-30.42 35.22,0 17.58,30.48 z m 0,60.9 -17.58,30.48 -35.22,0 -17.58,-30.48 17.58,-30.48 35.22,0 17.58,30.48 z m -158.34,-578.88 -17.58,30.48 -35.16,0 -17.58,-30.48 17.58,-30.48 35.16,0 17.58,30.48 z m 0,60.9 -17.58,30.48 -35.16,0 -17.58,-30.48 17.58,-30.42 35.16,0 17.58,30.42 z m 0,60.96 -17.58,30.48 -35.16,0 -17.58,-30.48 17.58,-30.48 35.16,0 17.58,30.48 z m 0,60.96 -17.58,30.42 -35.16,0 -17.58,-30.48 17.58,-30.42 35.16,0 17.58,30.48 z m 0,60.9 -17.58,30.48 -35.16,0 -17.58,-30.48 17.58,-30.48 35.16,0 17.58,30.48 z m 0,60.96 -17.58,30.42 -35.16,0 -17.58,-30.42 17.58,-30.48 35.16,0 17.58,30.48 z m 0,60.9 -17.58,30.48 -35.16,0 -17.58,-30.48 17.58,-30.48 35.16,0 17.58,30.48 z m 0,60.96 -17.58,30.48 -35.16,0 -17.58,-30.48 17.58,-30.48 35.16,0 17.58,30.48 z m 0,60.96 -17.58,30.42 -35.16,0 -17.58,-30.48 17.58,-30.42 35.16,0 17.58,30.48 z m 52.8,-457.02 -17.58,30.48 -35.22,-0.06 -17.58,-30.42 17.58,-30.48 35.22,0 17.58,30.48 z m 0,60.9 -17.58,30.48 -35.22,0 -17.58,-30.48 17.58,-30.48 35.22,0 17.58,30.48 z m 0,60.96 -17.58,30.48 -35.22,0 -17.58,-30.48 17.58,-30.48 35.22,0 17.58,30.48 z m 0,60.9 -17.58,30.48 -35.22,0 -17.58,-30.48 17.58,-30.42 35.22,0 17.58,30.42 z m 0,60.96 -17.58,30.48 -35.22,0 -17.58,-30.48 17.58,-30.48 35.22,0 17.58,30.48 z m 0,60.96 -17.58,30.42 -35.22,0 -17.58,-30.48 17.58,-30.42 35.22,0 17.58,30.48 z m 0,60.9 -17.58,30.48 -35.22,0 -17.58,-30.48 17.58,-30.48 35.22,0 17.58,30.48 z m 0,60.96 -17.58,30.42 -35.22,0 -17.58,-30.42 17.58,-30.48 35.22,0 17.58,30.48 z m 0,60.9 -17.58,30.48 -35.22,0 -17.58,-30.48 17.58,-30.42 35.22,0 17.58,30.42 z m -158.34,-578.88 -17.58,30.48 -35.16,0 -17.58,-30.48 17.58,-30.48 35.16,0 17.58,30.48 z m 0,60.96 -17.58,30.42 -35.16,0 -17.58,-30.48 17.58,-30.42 35.16,0 17.58,30.48 z m 0,60.9 -17.58,30.48 -35.16,0 -17.58,-30.48 17.58,-30.48 35.16,0 17.58,30.48 z m 0,60.96 -17.58,30.42 -35.16,0 -17.58,-30.42 17.58,-30.48 35.16,0 17.58,30.48 z m 0,60.9 -17.58,30.48 -35.16,0 -17.58,-30.48 17.58,-30.48 35.16,0 17.58,30.48 z m 0,60.96 -17.58,30.48 -35.16,0 -17.58,-30.48 17.58,-30.48 35.16,0 17.58,30.48 z m 0,60.9 -17.58,30.48 -35.16,0 -17.58,-30.48 17.58,-30.42 35.16,0 17.58,30.42 z m 0,60.96 -17.58,30.48 -35.16,0 -17.58,-30.48 17.58,-30.48 35.16,0 17.58,30.48 z m 0,60.96 -17.58,30.42 -35.16,0 -17.58,-30.42 17.58,-30.48 35.16,0 17.58,30.48 z m 52.8,-457.02 -17.58,30.48 -35.22,0 -17.58,-30.48 17.58,-30.48 35.22,0 17.58,30.48 z m 0,60.9 -17.58,30.48 -35.22,0 -17.58,-30.48 17.58,-30.42 35.22,0 17.58,30.42 z m 0,60.96 -17.58,30.48 -35.22,0 -17.58,-30.48 17.58,-30.48 35.22,0 17.58,30.48 z m 0,60.96 -17.58,30.42 -35.22,0 -17.58,-30.48 17.58,-30.42 35.22,0 17.58,30.48 z m 0,60.9 -17.58,30.48 -35.22,0 -17.58,-30.48 17.58,-30.48 35.22,0 17.58,30.48 z m 0,60.96 -17.58,30.42 -35.22,0 -17.58,-30.42 17.58,-30.48 35.22,0 17.58,30.48 z m 0,60.9 -17.58,30.48 -35.22,0 -17.58,-30.48 17.58,-30.48 35.22,0 17.58,30.48 z m 0,60.96 -17.58,30.48 -35.22,0 -17.58,-30.48 17.58,-30.48 35.22,0 17.58,30.48 z m 0,60.96 -17.58,30.42 -35.22,0 -17.58,-30.48 17.58,-30.42 35.22,0 17.58,30.48 z m -158.34,-578.94 -17.579998,30.48 -35.16,0 -17.64,-30.48 17.64,-30.48 35.16,0 17.579998,30.48 z m 0,60.96 -17.579998,30.42 -35.16,0 -17.64,-30.42 17.64,-30.48 35.16,0 17.579998,30.48 z m 0,60.9 -17.579998,30.48 -35.16,0 -17.64,-30.48 17.64,-30.48 35.16,0 17.579998,30.48 z m 0,60.96 -17.579998,30.48 -35.16,0 -17.64,-30.48 17.64,-30.48 35.16,0 17.579998,30.48 z m 0,60.9 -17.579998,30.48 -35.16,0 -17.64,-30.48 17.64,-30.42 35.16,0 17.579998,30.42 z m 0,60.96 -17.579998,30.48 -35.16,0 -17.64,-30.48 17.64,-30.48 35.16,0 17.579998,30.48 z m 0,60.96 -17.579998,30.42 -35.16,0 -17.64,-30.48 17.64,-30.42 35.16,0 17.579998,30.48 z m 0,60.9 -17.579998,30.48 -35.16,0 -17.64,-30.48 17.64,-30.48 35.16,0 17.579998,30.48 z m 0,60.96 -17.579998,30.48 -35.16,0 -17.64,-30.48 17.64,-30.48 35.16,0 17.579998,30.48 z m 52.8,-457.02 -17.58,30.48 -35.22,0 -17.579998,-30.48 17.579998,-30.48 35.22,0 17.58,30.48 z m 0,60.96 -17.58,30.42 -35.22,0 -17.579998,-30.48 17.579998,-30.42 35.22,0 17.58,30.48 z m 0,60.9 -17.58,30.48 -35.22,0 -17.579998,-30.48 17.579998,-30.48 35.22,0 17.58,30.48 z m 0,60.96 -17.58,30.42 -35.22,0 -17.579998,-30.42 17.579998,-30.48 35.22,0 17.58,30.48 z m 0,60.9 -17.58,30.48 -35.22,0 -17.579998,-30.48 17.579998,-30.48 35.22,0 17.58,30.48 z m 0,60.96 -17.58,30.48 -35.22,0 -17.579998,-30.48 17.579998,-30.48 35.22,0 17.58,30.48 z m 0,60.9 -17.58,30.48 -35.22,0 -17.579998,-30.48 17.579998,-30.42 35.22,0 17.58,30.42 z m 0,60.96 -17.58,30.48 -35.22,0 -17.579998,-30.48 17.579998,-30.48 35.22,0 17.58,30.48 z m 0,60.96 -17.58,30.42 -35.22,0 -17.579998,-30.42 17.579998,-30.48 35.22,0 17.58,30.48 z m 474.96,-335.1 -17.58,30.48 -35.22,0 -17.58,-30.48 17.58,-30.48 35.22,0 17.58,30.48 z m 0,60.96 -17.58,30.48 -35.22,0 -17.58,-30.48 17.58,-30.48 35.22,0 17.58,30.48 z m -52.8,-91.44 -17.58,30.48 -35.16,0 -17.64,-30.48 17.64,-30.48 35.16,0 17.58,30.48 z m 0,60.96 -17.58,30.48 -35.16,0 -17.64,-30.48 17.64,-30.48 35.16,0 17.58,30.48 z m -52.74,-91.44 -17.64,30.48 -35.16,0 -17.58,-30.48 17.58,-30.48 35.16,0 17.64,30.48 z m 0,60.96 -17.64,30.48 -35.16,0 -17.58,-30.48 17.58,-30.48 35.16,0 17.64,30.48 z m -52.8,-91.44 -17.58,30.48 -35.22,0 -17.58,-30.48 17.64,-30.42 35.16,0 17.58,30.42 z m 0,60.96 -17.58,30.48 -35.22,0 -17.58,-30.48 17.64,-30.48 35.16,0 17.58,30.48 z m -52.8,-91.44 -17.58,30.48 -35.16,0 -17.58,-30.48 17.58,-30.42 35.16,0 17.58,30.42 z m 0,60.96 -17.58,30.48 -35.16,0 -17.58,-30.48 17.58,-30.48 35.16,0 17.58,30.48 z m -52.74,-91.38 -17.58,30.42 -35.22,0 -17.58,-30.48 17.58,-30.42 35.22,0 17.58,30.48 z m 0,60.9 -17.58,30.48 -35.22,0 -17.58,-30.48 17.58,-30.48 35.22,0 17.58,30.48 z m -52.8,-91.38 -17.58,30.42 -35.16,0 -17.58,-30.48 17.58,-30.42 35.16,0 17.58,30.48 z m 0,60.9 -17.58,30.48 -35.16,0 -17.58,-30.48 17.58,-30.48 35.16,0 17.58,30.48 z m -52.74,-91.38 -17.58,30.42 -35.22,0 -17.58,-30.42 17.58,-30.48 35.22,0 17.58,30.48 z m 0,60.9 -17.58,30.48 -35.22,0 -17.58,-30.48 17.58,-30.48 35.22,0 17.58,30.48 z m -52.8,-91.38 -17.58,30.42 -35.16,0 -17.58,-30.42 17.58,-30.48 35.16,0 17.58,30.48 z m 0,60.9 -17.58,30.48 -35.16,0 -17.58,-30.48 17.58,-30.48 35.16,0 17.58,30.48 z m -52.74,-91.38 -17.58,30.48 -35.22,0 L 97.730001,109.43 115.31,78.949995 l 35.22,0 17.58,30.480005 z m 0,60.9 -17.58,30.48 -35.22,0 -17.579999,-30.48 17.579999,-30.42 35.22,0 17.58,30.42 z M 115.31,78.949995 97.730001,109.43 l -35.16,0 -17.58,-30.480005 17.58,-30.48 35.16,0 17.579999,30.48 z m 0,60.960005 -17.579999,30.42 -35.16,0 -17.58,-30.48 17.58,-30.42 35.16,0 17.579999,30.48 z" /><path
-       id="path14"
-       style="fill:none;stroke:#003fff;stroke-width:5.63999987;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
-       d="m 625.43,1023.53 -35.16,0 -17.58,-30.48 -35.22,0 -17.58,-30.48 -35.16,0 -17.58,-30.48 -35.22,0 -17.58,-30.48 -35.16,0 -17.58,-30.48 -35.22,0 -17.58,-30.48 -35.16,0 -17.58,-30.48 -35.22,0 -17.58,-30.48 -35.16,0 -17.58,-30.42 -35.22,-0.06 -17.579998,-30.42 -35.16,0 M 625.49,353.21 l -35.22,0 -17.58,-30.48 -35.16,0 -17.64,-30.48 -35.16,0 -17.58,-30.42 -35.22,-0.06 -17.58,-30.42 -35.16,0 -17.58,-30.48 -35.22,0 -17.58,-30.48 -35.16,0 -17.58,-30.48 -35.22,0 -17.58,-30.48 -35.16,0 -17.58,-30.480005 -35.22,0 -17.579998,-30.480001 -35.16,0" /><path
-       id="path16"
-       style="fill:none;stroke:#dd0000;stroke-width:5.63999987;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
-       d="m 625.43,1023.53 17.64,-30.48 -17.58,-30.48 17.58,-30.48 -17.58,-30.42 17.58,-30.48 -17.64,-30.48 17.64,-30.48 -17.58,-30.48 17.58,-30.42 -17.58,-30.48 17.58,-30.48 -17.64,-30.48 17.64,-30.42 -17.58,-30.48 17.58,-30.48 -17.58,-30.48 17.58,-30.48 -17.58,-30.42 17.58,-30.48 -17.64,-30.48 17.64,-30.48 -17.64,-30.48 m -562.859999,365.58 -17.64,-30.48 17.64,-30.48 -17.64,-30.48 17.64,-30.48 -17.64,-30.48 17.64,-30.42 -17.64,-30.48 17.64,-30.48 -17.64,-30.48 17.64,-30.42 -17.64,-30.48 17.64,-30.48 -17.64,-30.48 17.64,-30.48 -17.64,-30.42 17.64,-30.48 -17.64,-30.48 17.64,-30.48 -17.58,-30.48 17.58,-30.42 -17.58,-30.480006 17.58,-30.48" /></g></svg>
diff --git a/variants/Hex/Regular_hexagon.svg b/variants/Hex/Regular_hexagon.svg
deleted file mode 100644 (file)
index fc47b04..0000000
+++ /dev/null
@@ -1,9 +0,0 @@
-<svg width="173.2px" height="400.0px" viewBox="-86.6 -100.0 173.2 400.0">
-  <defs>
-    <g id="hexa">
-      <polygon style="fill:none;stroke:#000000;stroke-width:1px" points="0,-100.0 86.6,-50.0 86.6,50.0 0,100.0 -86.6,50.0 -86.6,-50.0"/>
-    </g>
-  </defs>
-  <use href="#hexa" x="0" y="0"/>
-  <use href="#hexa" x="0" y="200"/>
-</svg>
index ec14a06..37bd53c 100644 (file)
@@ -1,4 +1,7 @@
-// https://www.boardspace.net/hex/english/Rules%20-%20HexWiki.htm
+import ChessRules from "/base_rules.js";
+import PiPo from "/utils/PiPo.js";
+import Move from "/utils/Move.js";
+
 export default class HexRules extends ChessRules {
 
   static get Options() {
@@ -6,21 +9,26 @@ export default class HexRules extends ChessRules {
       input: [
         {
           label: "Board size",
+          variable: "bsize",
           type: "number",
-          defaut: 11,
-          variable: "bsize"
-        }
-      ],
-      check: [
+          defaut: 11
+        },
         {
           label: "Swap",
-          defaut: true,
-          variable: "swap"
+          variable: "swap",
+          type: "checkbox",
+          defaut: true
         }
       ]
     };
   }
 
+  get hasFlags() {
+    return false;
+  }
+  get hasEnpassant() {
+    return false;
+  }
   get hasReserve() {
     return false;
   }
@@ -31,8 +39,11 @@ export default class HexRules extends ChessRules {
 
   doClick(coords) {
     if (
-      this.board[coords.x][coords.y] != "" &&
-      (!this.swap || this.movesCount >= 2)
+      this.playerColor != this.turn ||
+      (
+        this.board[coords.x][coords.y] != "" &&
+        (!this.options["swap"] || this.movesCount >= 2)
+      )
     ) {
       return null;
     }
@@ -63,58 +74,89 @@ export default class HexRules extends ChessRules {
 
   genRandInitFen() {
     // NOTE: size.x == size.y (square boards)
-    const emptyCount = C.FenEmptySquares(this.size.x.repeat);
-    return (emptyCount + "/").repeat(this.size.x).slice(0, -1);
+    const emptyCount = C.FenEmptySquares(this.size.x);
+    return (emptyCount + "/").repeat(this.size.x).slice(0, -1) + " w 0";
   }
 
-  getPieceWidth(rwidth) {
-    return (rwidth / this.size.y); //TODO
-  }
-
-  // TODO
+  // TODO: re-enable rotation
   getSvgChessboard() {
+    // NOTE: with small margin seems nicer
+    let width = 173.2 * this.size.y + 173.2 * (this.size.y-1) / 2 + 30,
+        height = 50 + Math.floor(150 * this.size.x) + 30,
+        min_x = -86.6 - 15,
+        min_y = -100 - 15;
+//    if (this.size.rotate) {
+//      [width, height] = [height, width];
+//      [min_x, min_y] = [min_y, min_x];
+//    }
     let board = `
       <svg
-        width="2771.2px" height="1700px"
-        class="chessboard_SVG">
+        viewBox="${min_x} ${min_y} ${width} ${height}"
+        class="chessboard_SVG"`;
+//    if (this.size.rotate)
+//      board += ` transform="rotate(90 ${min_x} ${min_y})"`
+    board += `>
       <defs>
         <g id="hexa">
           <polygon
-            style="fill:none;stroke:#000000;stroke-width:1px"
+            style="stroke:#000000;stroke-width:1"
             points="0,-100.0 86.6,-50.0 86.6,50.0 0,100.0 -86.6,50.0 -86.6,-50.0"
           />
         </g>
       </defs>`;
+    board += "<g>";
     for (let i=0; i < this.size.x; i++) {
       for (let j=0; j < this.size.y; j++) {
-        let classes = this.getSquareColorClass(i, j);
-        board += `<rect
-          class="neutral-square"
-          id="${this.coordsToId([i, j])}"
-          width="10"
-          height="10"
-          x="${10*j}" ///////////// + resize ! ratio
-          y="${10*i}" />`;
+        board += `
+          <use
+            href="#hexa"
+            class="neutral-square"
+            id="${this.coordsToId({x: i, y: j})}"
+            x="${173.2*j + 86.6*i}"
+            y="${150*i}"
+          />`;
       }
     }
-    board += "</g></svg>";
+    board += `</g><g style="fill:none;stroke-width:10">`;
+    // Goals: up/down/left/right
+    board += `<polyline style="stroke:red" points="`
+    for (let i=0; i<=2*this.size.y; i++)
+      board += ((i-1)*86.6) + ',' + (i % 2 == 0 ? -50 : -100) + ' ';
+    board += `"/><polyline style="stroke:red" points="`;
+    for (let i=1; i<=2*this.size.y; i++) {
+      const jShift = 200 * Math.floor((this.size.y+1)/2) +
+                     100 * (Math.floor(this.size.y/2) - 1) +
+                     (i % 2 == 0 ? -50 : 0) +
+                     (this.size.y % 2 == 0 ? 50 : 0);
+      board += ((i+this.size.y-2)*86.6) + ',' + jShift + ' ';
+    }
+    board += `"/><polyline style="stroke:blue" points="`;
+    let sumY = -100;
+    for (let i=0; i<=2*this.size.x; i++) {
+      board += ((Math.floor(i/2)-1) * 86.6) + ',' +
+               (sumY += (i % 2 == 0 ? 50 : 100)) + ' ';
+    }
+    board += `"/><polyline style="stroke:blue" points="`;
+    sumY = -100;
+    for (let i=0; i<2*this.size.x; i++) {
+      board += (173.2*this.size.x + (Math.floor(i/2)-1) * 86.6) + ',' +
+               (sumY += (i % 2 == 0 ? 50 : 100)) + ' ';
+    }
+    board += `"/></g></svg>`;
     return board;
   }
 
   setupPieces() {
-    // TODO: just scan board and get IDs, and addClass "bg-white" or "bg-black"
-  }
-
-  // TODO (NOTE: no flip here, always same view)
-  getPixelPosition(i, j, r) {
-    if (i < 0 || j < 0)
-      return [0, 0]; //piece vanishes
-    let x, y;
-    const sqSize = r.width / this.size.y;
-    const flipped = (this.playerColor == 'b');
-    const x = (flipped ? this.size.y - 1 - j : j) * sqSize,
-          y = (flipped ? this.size.x - 1 - i : i) * sqSize;
-    return [r.x + x, r.y + y];
+    for (let i=0; i<this.size.x; i++) {
+      for (let j=0; j<this.size.y; j++) {
+        if (this.board[i][j] != "") {
+          const sqColor = (this.getColor(i, j) == 'w' ? "white" : "black");
+          const elt = document.getElementById(this.coordsToId({x: i, y: j}));
+          elt.classList.remove("neutral-square");
+          elt.classList.add("bg-" + sqColor);
+        }
+      }
+    }
   }
 
   initMouseEvents() {
@@ -136,46 +178,74 @@ export default class HexRules extends ChessRules {
   }
 
   get size() {
+    const baseRatio = 1.619191; // 2801.2 / 1730, "widescreen"
+    const rotate = window.innerWidth < window.innerHeight; //"vertical screen"
     return {
-      x: this.bsize,
-      y: this.bsize,
-      ratio: 1.630118
-    };
-  }
-
-  pieces() {
-    return {
-      'p': {
-        "class": "pawn",
-      }
+      x: this.options["bsize"],
+      y: this.options["bsize"],
+      ratio: rotate ? 1 / baseRatio : baseRatio,
+      rotate: rotate
     };
   }
 
   play(move) {
-    super.playOnBoard(move);
+    this.playOnBoard(move);
+    this.movesCount++;
+    this.turn = C.GetOppCol(this.turn);
   }
 
-  // TODO:
   getCurrentScore(move) {
     const oppCol = C.GetOppCol(this.turn);
-    // Search for connecting path of opp color: TODO
-    // ...
-    if (path found)
-      return (oppCol == "w" ? "1-0" : "0-1");
+    // Search for connecting path of opp color:
+    let explored = {}, component;
+    let min, max;
+    const getIndex = (x, y) => x + "." + y;
+    // Explore one connected component:
+    const neighborsSearch = ([x, y], index) => {
+      // Let's say "white" connects on x and "black" on y
+      const z = (oppCol == 'w' ? x : y);
+      if (z < min)
+        min = z;
+      if (z > max)
+        max = z;
+      explored[index] = true;
+      component[index] = true;
+      for (let [dx, dy] of super.pieces()['k'].moves[0].steps) {
+        const [nx, ny] = [x + dx, y + dy];
+        const nidx = getIndex(nx, ny);
+        if (
+          this.onBoard(nx, ny) &&
+          this.getColor(nx, ny) == oppCol &&
+          !component[nidx]
+        ) {
+          neighborsSearch([nx, ny], nidx);
+        }
+      }
+    };
+    // Explore all components:
+    for (let i=0; i<this.size.x; i++) {
+      for (let j=0; j<this.size.y; j++) {
+        const index = getIndex(i, j);
+        if (this.getColor(i, j) == oppCol && !explored[index]) {
+          component = {};
+          [min, max] = [this.size.x, 0];
+          neighborsSearch([i, j], index);
+          if (max - min == this.size.x - 1)
+            return (oppCol == "w" ? "1-0" : "0-1");
+        }
+      }
+    }
     return "*";
   }
 
   playVisual(move) {
     move.vanish.forEach(v => {
-// TODO: just get ID, and remClass "bg-white" or "bg-black" (in CSS: TODO)
+      let elt = document.getElementById(this.coordsToId({x: v.x, y: v.y}));
+      elt.classList.remove("bg-" + (v.c == 'w' ? "white" : "black"));
     });
     move.appear.forEach(a => {
-// TODO: just get ID, and addClass "bg-white" or "bg-black" (in CSS: TODO)
-//      this.g_pieces[a.x][a.y] = document.createElement("piece");
-//      this.g_pieces[a.x][a.y].classList.add(this.pieces()[a.p]["class"]);
-//      this.g_pieces[a.x][a.y].classList.add(a.c == "w" ? "white" : "black");
-//      this.g_pieces[a.x][a.y].style.width = pieceWidth + "px";
-//      this.g_pieces[a.x][a.y].style.height = pieceWidth + "px";
+      let elt = document.getElementById(this.coordsToId({x: a.x, y: a.y}));
+      elt.classList.add("bg-" + (a.c == 'w' ? "white" : "black"));
     });
   }
 
diff --git a/variants/Hex/rules.html b/variants/Hex/rules.html
new file mode 100644 (file)
index 0000000..33be5a2
--- /dev/null
@@ -0,0 +1,5 @@
+<p>Win by connecting both edges of your color.</p>
+
+<a href="https://www.maths.ed.ac.uk/~csangwin/hex/index.html">Detailed rules.</a>
+
+<p class="author">Piet Hein (1942).</p>
index 91ea8fd..a1c41b4 100644 (file)
@@ -1,3 +1,10 @@
 .neutral-square {
   fill: #eaeded;
 }
+
+.bg-white {
+  fill: red;
+}
+.bg-black {
+  fill: blue;
+}
index eaabf07..bbec80a 100644 (file)
@@ -5,13 +5,14 @@ export default class MadrasiRules extends ChessRules {
   static get Options() {
     return {
       select: C.Options.select,
-      check: [
+      input: [
         {
           label: "Rex Incl.",
-          defaut: false,
-          variable: "rexincl"
+          variable: "rexincl",
+          type: "checkbox",
+          defaut: false
         }
-      ].concat(C.Options.check),
+      ].concat(C.Options.input),
       styles: C.Options.styles.filter(s => s != "madrasi")
     };
   }
index c209821..90bb998 100644 (file)
@@ -5,13 +5,14 @@ export default class ProgressiveRules extends ChessRules {
   static get Options() {
     return {
       select: C.Options.select,
-      check: [
+      input: [
         {
           label: "Logical",
-          defaut: false,
-          variable: "logical"
+          variable: "logical",
+          type: "checkbox",
+          defaut: false
         }
-      ].concat(C.Options.check),
+      ].concat(C.Options.input),
       styles: C.Options.styles.filter(s => s != "progressive")
     };
   }
index 82458a9..d8c78e9 100644 (file)
@@ -5,16 +5,18 @@ export default class RecycleRules extends ChessRules {
   static get Options() {
     return {
       select: C.Options.select,
-      check: [
+      input: [
         {
           label: "Capture king",
-          defaut: false,
-          variable: "taking"
+          variable: "taking",
+          type: "checkbox",
+          defaut: false
         },
         {
           label: "Falling pawn",
-          defaut: true,
-          variable: "pawnfall"
+          variable: "pawnfall",
+          type: "checkbox",
+          defaut: true
         }
       ],
       styles: C.Options.styles.filter(s => s != "recycle")
index 01b4d00..58b3d23 100644 (file)
@@ -5,7 +5,7 @@ export default class RifleRules extends ChessRules {
   static get Options() {
     return {
       select: C.Options.select,
-      check: C.Options.check,
+      input: C.Options.input,
       styles: C.Options.styles.filter(s => s != "rifle")
     };
   }
index 5e52252..2698eaf 100644 (file)
@@ -6,7 +6,7 @@ export default class TeleportRules extends ChessRules {
     return {
       select: C.Options.select,
       // TODO? option "teleport king"?
-      check: C.Options.check,
+      input: C.Options.input,
       styles: C.Options.styles.filter(s => s != "teleport")
     };
   }
index 424452d..5bb8c52 100644 (file)
@@ -5,7 +5,7 @@ export default class ZenRules extends ChessRules {
   static get Options() {
     return {
       select: C.Options.select,
-      check: C.Options.check,
+      input: C.Options.input,
       styles: C.Options.styles.filter(s => s != "zen")
     };
   }