From 4fd396b4d42189eae78583f332d845db9111a0fb Mon Sep 17 00:00:00 2001
From: Benjamin Auder <benjamin.auder@somewhere>
Date: Mon, 4 Jul 2022 16:08:01 +0200
Subject: [PATCH] Add AbstractClickFillRules for games filling squares (no
 pieces)

---
 variants/Arena/rules.html     | 20 ++++++++-
 variants/Hex/class.js         | 28 +-----------
 variants/_ClickFill/class.js  | 80 +++++++++++++++++++++++++++++++++++
 variants/_ClickFill/style.css |  1 +
 4 files changed, 102 insertions(+), 27 deletions(-)
 create mode 100644 variants/_ClickFill/class.js
 create mode 100644 variants/_ClickFill/style.css

diff --git a/variants/Arena/rules.html b/variants/Arena/rules.html
index fca97fe..5aa8716 100644
--- a/variants/Arena/rules.html
+++ b/variants/Arena/rules.html
@@ -1,3 +1,21 @@
-<p>TODO</p>
+<p>
+  Only moves ending in the Arena zone (where no piece stand initially)
+  are allowed. If starting from inside the Arena, then a move must capture
+  something.
+</p>
+
+<ul>
+  <li>King and queen move like a queen restricted to 3 squares.</li>
+  <li>Pawns can capture backwards.</li>
+</ul>
+
+<p>
+  The first player who cannot make a move loses.
+  A player who lose both king and queen also lose the game.
+</p>
+
+<a href="https://www.chessvariants.com/32turn.dir/arenachess.html">
+  chessvariants page.
+</a>
 
 <p class="author">Jeff Kiska (2000).</p>
diff --git a/variants/Hex/class.js b/variants/Hex/class.js
index 0797c91..1919bc8 100644
--- a/variants/Hex/class.js
+++ b/variants/Hex/class.js
@@ -1,8 +1,8 @@
-import ChessRules from "/base_rules.js";
+import AbstractClickFillRules from "/variants/_ClickFill/class.js";
 import PiPo from "/utils/PiPo.js";
 import Move from "/utils/Move.js";
 
-export default class HexRules extends ChessRules {
+export default class HexRules extends AbstractClickFillRules {
 
   static get Options() {
     return {
@@ -153,19 +153,6 @@ export default class HexRules extends ChessRules {
     return board;
   }
 
-  setupPieces() {
-    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);
-        }
-      }
-    }
-  }
-
   get size() {
     const baseRatio = 1.6191907514450865; //2801.2 / 1730, "widescreen"
     const rc =
@@ -228,15 +215,4 @@ export default class HexRules extends ChessRules {
     return "*";
   }
 
-  playVisual(move) {
-    move.vanish.forEach(v => {
-      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 => {
-      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/_ClickFill/class.js b/variants/_ClickFill/class.js
new file mode 100644
index 0000000..b16b221
--- /dev/null
+++ b/variants/_ClickFill/class.js
@@ -0,0 +1,80 @@
+import ChessRules from "/base_rules.js";
+
+export default class AbstractClickFillRules extends ChessRules {
+
+  static get Aliases() {
+    return Object.assign({'A': AbstractClickFillRules}, ChessRules.Aliases);
+  }
+
+  static get Options() {
+    return {}
+  }
+
+  setupPieces() {
+    for (let i=0; i<this.size.x; i++) {
+      for (let j=0; j<this.size.y; j++) {
+        const markHere =
+          !!this.marks && this.marks.some(m => m[0] == i && m[1] == j);
+        if (this.board[i][j] != "" || markHere) {
+          let elt = document.getElementById(this.coordsToId({x: i, y: j}));
+          elt.classList.remove("neutral-square");
+          if (markHere)
+            elt.classList.add("bg-mark");
+          else {
+            const sqColor = (this.getColor(i, j) == 'w' ? "white" : "black");
+            elt.classList.add("bg-" + sqColor);
+          }
+        }
+      }
+    }
+  }
+
+  playVisual(move) {
+    move.vanish.forEach(v => {
+      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 => {
+      let elt = document.getElementById(this.coordsToId({x: a.x, y: a.y}));
+      elt.classList.add("bg-" + (a.c == 'w' ? "white" : "black"));
+    });
+  }
+
+  animateFading(arr, cb) {
+    const animLength = 350; //TODO: 350ms? More? Less?
+    arr.forEach(e => {
+      let fadingSquare =
+        document.getElementById(this.coordsToId({x: e.x, y: e.y}));
+      fadingSquare.style.transitionDuration = (animLength / 1000) + "s";
+      //fadingSquare.style.backgroundColor = "0"; //TODO: type in or out
+      if (this.board[e.x][e.y] != "") {
+        // TODO: fade out curCol --> neutral
+      }
+      else {
+        // TODO: fade in neutral --> this.getColor(e.x, e.y)
+      }
+    });
+    setTimeout(cb, animLength);
+  }
+
+  animate(move, callback) {
+    // No movement, but use fading effects: TODO
+    // https://stackoverflow.com/questions/14350126/transition-color-fade-on-hover
+    // https://stackoverflow.com/questions/22581789/fade-in-fade-out-background-color-of-an-html-element-with-javascript-or-jquer
+    if (true || this.noAnimate || move.noAnimate) {
+      callback();
+      return;
+    }
+    let targetObj = new TargetObj(callback);
+    const allChanges = move.appear.concat(move.vanish);
+    if (allChanges.length > 0) {
+      targetObj.target++;
+      this.animateFading(allChanges, () => targetObj.increment());
+    }
+    targetObj.target +=
+      this.customAnimate(move, segments, () => targetObj.increment());
+    if (targetObj.target == 0)
+      callback();
+  }
+
+};
diff --git a/variants/_ClickFill/style.css b/variants/_ClickFill/style.css
new file mode 100644
index 0000000..8f414f5
--- /dev/null
+++ b/variants/_ClickFill/style.css
@@ -0,0 +1 @@
+/* TODO */
-- 
2.44.0