Few fixes + improve 8-pieces; last TODOs main
authorBenjamin Auder <benjamin.auder@somewhere>
Thu, 7 May 2026 01:03:34 +0000 (03:03 +0200)
committerBenjamin Auder <benjamin.auder@somewhere>
Thu, 7 May 2026 01:03:34 +0000 (03:03 +0200)
css/common.css
js/app.js
js/base_rules.js
variants/Eightpieces/class.js

index eabf641..38d0f95 100644 (file)
@@ -305,7 +305,7 @@ piece.mark.transparent {
 }
 .option-input {
   display: inline-block;
 }
 .option-input {
   display: inline-block;
-  margin-right: 10px;
+  margin-right: 15px;
 }
 .option-input input[type=number] {
   width: 64px;
 }
 .option-input input[type=number] {
   width: 64px;
@@ -546,11 +546,14 @@ select:focus + .focus {
   width: 100%;
 }
 
   width: 100%;
 }
 
+label.input-checkbox {
+  cursor: pointer;
+}
 /* https://dev.to/kallmanation/styling-a-checkbox-with-only-css-3o3p */
 /* https://dev.to/kallmanation/styling-a-checkbox-with-only-css-3o3p */
-label.checkbox > input[type="checkbox"] {
+label.input-checkbox > input[type="checkbox"] {
   display: none;
 }
   display: none;
 }
-label.checkbox > input[type="checkbox"] + *::before {
+label.input-checkbox > input[type="checkbox"] + *::before {
   content: "";
   display: inline-block;
   vertical-align: bottom;
   content: "";
   display: inline-block;
   vertical-align: bottom;
@@ -562,22 +565,24 @@ label.checkbox > input[type="checkbox"] + *::before {
   border-width: 0.1rem;
   border-color: gray;
 }
   border-width: 0.1rem;
   border-color: gray;
 }
-label.checkbox > input[type="checkbox"]:checked + *::before {
+label.input-checkbox > input[type="checkbox"]:checked + *::before {
   content: "✓";
   font-size: 1.1rem;
   content: "✓";
   font-size: 1.1rem;
-  /*padding:10px;*/
   color: white;
   text-align: center;
   background: teal;
   border-color: teal;
 }
   color: white;
   text-align: center;
   background: teal;
   border-color: teal;
 }
-label.checkbox > input[type="checkbox"]:checked + * {
+label.input-checkbox > input[type="checkbox"]:checked + * {
   color: teal;
 }
   color: teal;
 }
-label.checkbox > span.spacer {
+label.input-checkbox > span.spacer {
   width: 10px;
   content: " ";
 }
   width: 10px;
   content: " ";
 }
+label.input-checkbox > span.after-spacer {
+  padding-left: 5px;
+}
 
 /* https://theanam.github.io/css-only-loaders/ ("hour-glass") */
 :root{
 
 /* https://theanam.github.io/css-only-loaders/ ("hour-glass") */
 :root{
index 7d30a32..016a1c3 100644 (file)
--- a/js/app.js
+++ b/js/app.js
@@ -211,10 +211,10 @@ function prepareOptions() {
         inputAttrs.value = input.defaut;
       container.append(
         h('div', { class: 'option-input' }, [
         inputAttrs.value = input.defaut;
       container.append(
         h('div', { class: 'option-input' }, [
-          h('label', { class: 'input' }, [
+          h('label', { class: "input-" + input.type }, [
             h('input', inputAttrs),
             h('span', { class: 'spacer' }),
             h('input', inputAttrs),
             h('span', { class: 'spacer' }),
-            h('span', { textContent: input.label })
+            h('span', { class: 'after-spacer', textContent: input.label })
           ])
         ])
       );
           ])
         ])
       );
@@ -315,7 +315,7 @@ async function fillGameInfos(gameInfos, oppIndex) {
   // Final assembling
   container.append(
     playerDiv,
   // Final assembling
   container.append(
     playerDiv,
-    //activeOptions.length > 0 ? optionsInfos : null,
+    optionsInfos,
     rulesDiv,
     btnWrap
   );
     rulesDiv,
     btnWrap
   );
index 84cf1ea..4fc46ac 100644 (file)
@@ -1470,6 +1470,7 @@ export default class ChessRules {
     return false;
   }
 
     return false;
   }
 
+  // Check if it's possible to go from x1,y1 to x2,y2 with 'range' steps
   compatibleStep([x1, y1], [x2, y2], step, range) {
     const epsilon = 1e-7; //arbitrary small value
     let shifts = [0];
   compatibleStep([x1, y1], [x2, y2], step, range) {
     const epsilon = 1e-7; //arbitrary small value
     let shifts = [0];
index 676ae90..62e718f 100644 (file)
@@ -13,6 +13,10 @@ export default class EightpiecesRules extends ChessRules {
     };
   }
 
     };
   }
 
+  static get LANCERS() {
+    return ['c', 'd', 'e', 'f', 'g', 'h', 'm', 'o'];
+  }
+
   getLancerOptions(x, y) {
     let options = [];
     if (y > 0)
   getLancerOptions(x, y) {
     let options = [];
     if (y > 0)
@@ -63,10 +67,6 @@ export default class EightpiecesRules extends ChessRules {
     };
   }
 
     };
   }
 
-  static get LANCERS() {
-    return ['c', 'd', 'e', 'f', 'g', 'h', 'm', 'o'];
-  }
-
   // obj == "-", {-1,-1} or ["]{x,y}["]
   static convertPush(obj) {
     if (typeof obj === "string")
   // obj == "-", {-1,-1} or ["]{x,y}["]
   static convertPush(obj) {
     if (typeof obj === "string")
@@ -159,11 +159,6 @@ export default class EightpiecesRules extends ChessRules {
     }, super.pieces(color, x, y));
   }
 
     }, super.pieces(color, x, y));
   }
 
-  canStepOver(i, j, p, c) {
-    const colIJ = this.getColor(i, j);
-    return this.board[i][j] == "" || (V.LANCERS.includes(p) && c == colIJ);
-  }
-
   canIplay(x, y) {
     if (
       this.pushFrom.x == x && this.pushFrom.y == y &&
   canIplay(x, y) {
     if (
       this.pushFrom.x == x && this.pushFrom.y == y &&
@@ -174,6 +169,11 @@ export default class EightpiecesRules extends ChessRules {
     return super.canIplay(x, y);
   }
 
     return super.canIplay(x, y);
   }
 
+  canStepOver(i, j, p, c) {
+    const colIJ = this.getColor(i, j);
+    return this.board[i][j] == "" || (V.LANCERS.includes(p) && c == colIJ);
+  }
+
   isImmobilized([x, y]) {
     const color = this.getColor(x, y);
     const oppCol = C.GetOppTurn(color);
   isImmobilized([x, y]) {
     const color = this.getColor(x, y);
     const oppCol = C.GetOppTurn(color);
@@ -215,18 +215,33 @@ export default class EightpiecesRules extends ChessRules {
     return res;
   }
 
     return res;
   }
 
+// TODO: sentry nudge
+
+  // after pushedTo, if lancer : allow reorient + move, or just reorient (move to king) if stuck
+
+  // later, if stuck, allow reorient only (just click)
+ // doClick(coords) { TODO
+
   getPotentialMovesFrom([x, y], color) {
     if (this.pushFrom.x < 0 || this.pushedTo.x >= 0) {
       let smoves = super.getPotentialMovesFrom([x, y], color);
       // Forbid direction x,y --> pushFrom if x,y == pushedTo
       if (x == this.pushedTo.x && y == this.pushedTo.y) {
         smoves = smoves.filter(m => {
   getPotentialMovesFrom([x, y], color) {
     if (this.pushFrom.x < 0 || this.pushedTo.x >= 0) {
       let smoves = super.getPotentialMovesFrom([x, y], color);
       // Forbid direction x,y --> pushFrom if x,y == pushedTo
       if (x == this.pushedTo.x && y == this.pushedTo.y) {
         smoves = smoves.filter(m => {
+          let sx = this.pushFrom.x - x,
+              sy = this.pushFrom.y - y;
+          let divideBy = sx != 0 && sy != 0 && Math.abs(sx) != Math.abs(sy)
+            ? 1
+            : Math.max(sx, sy);
           return ( !super.compatibleStep(
             [x, y], [m.end.x, m.end.y],
           return ( !super.compatibleStep(
             [x, y], [m.end.x, m.end.y],
-            [this.pushFrom.x - x, this.pushFrom.y - y]
+            [sx / divideBy, sy / divideBy]
           ) );
         });
       }
           ) );
         });
       }
+
+      // TODO: lancer special case, move as a queen after push
+
       return smoves.concat(this.getPassMoves(x, y));
     }
     // pushFrom.x >= 0 && pushedTo.x < 0
       return smoves.concat(this.getPassMoves(x, y));
     }
     // pushFrom.x >= 0 && pushedTo.x < 0
@@ -242,39 +257,7 @@ export default class EightpiecesRules extends ChessRules {
       m.appear[0].c = m.vanish[0].c = oppCol;
       m.appear.push( new PiPo({x:x, y:y, p:'s', c:this.turn}) );
     });
       m.appear[0].c = m.vanish[0].c = oppCol;
       m.appear.push( new PiPo({x:x, y:y, p:'s', c:this.turn}) );
     });
-    
-console.log(pmoves);
-
     return pmoves;
     return pmoves;
-
-
-
-  }
-
-  postPlay(move) {
-    if (
-      move.vanish.length > 0 &&
-      move.vanish[0].p == 's' &&
-      move.appear[0].c != move.vanish[0].c
-    ) {
-      // Sentry push ("capturing" part)
-      this.pushFrom = {x: move.end.x, y: move.end.y};
-      this.pushedTo = {x: -1, y: -1};
-    }
-    else if (move.vanish.length > 0 && move.vanish[0].c != this.turn)
-      this.pushedTo = {x: move.end.x, y: move.end.y};
-    else {
-      // All other cases: just reset both push variables
-      this.pushFrom = {x: -1, y: -1};
-      this.pushedTo = {x: -1, y: -1};
-    }
-    super.postPlay(move);
-  }
-
-  isLastMove(move) {
-    if (move.vanish[0].p == 's' && move.appear[0].c != move.vanish[0].c)
-      return false;
-    return super.isLastMove(move);
   }
 
   postProcessPotentialMoves(moves) {
   }
 
   postProcessPotentialMoves(moves) {
@@ -287,7 +270,7 @@ console.log(pmoves);
         (
           (m.vanish.length > 0 && V.LANCERS.includes(m.vanish[0].p)) &&
           // Next line test checks that the lancer wasn't just pushed away
         (
           (m.vanish.length > 0 && V.LANCERS.includes(m.vanish[0].p)) &&
           // Next line test checks that the lancer wasn't just pushed away
-          (m.start.x != this.pushFrom.x || m.start.y != this.pushFrom.y)
+          (m.start.x != this.pushedTo.x || m.start.y != this.pushedTo.y)
         )
       ) {
         this.getLancerOptions(m.end.x, m.end.y).forEach(o => {
         )
       ) {
         this.getLancerOptions(m.end.x, m.end.y).forEach(o => {
@@ -297,25 +280,68 @@ console.log(pmoves);
           }) );
         });
       }
           }) );
         });
       }
-      else if (m.vanish.length == m.appear.length || m.vanish[0].p != 's')
-        finalMoves.push(m);
-      else {
+      else if (m.vanish.length == 2 && m.vanish[0].p == 's') {
         // Sentry "capture" --> remove sentry from final square (TODO: blink?)
         // Sentry "capture" --> remove sentry from final square (TODO: blink?)
-        const [x, y] = [m.end.x, m.end.y]
-        const p = this.getPiece(x, y);
-        const c = this.getColor(x, y);
         finalMoves.push( new Move({
         finalMoves.push( new Move({
-          appear: [new PiPo({x:m.end.x,y:m.end.y,c:c,p:p})],
-          vanish: [ m.vanish[0] ]
+          appear: [],
+          vanish: [ m.vanish[0] ],
+          end: m.end
         }) );
       }
         }) );
       }
+      else
+        finalMoves.push(m);
     }
     return finalMoves;
   }
 
     }
     return finalMoves;
   }
 
+  postPlay(move) {
+    if (
+      move.appear.length == 0 &&
+      move.vanish.length > 0 &&
+      move.vanish[0].p == 's'
+    ) {
+      // Sentry push ("capturing" part)
+      this.pushFrom = {x: move.end.x, y: move.end.y};
+      this.pushedTo = {x: -1, y: -1};
+    }
+    else if (move.vanish.length > 0 && move.vanish[0].c != this.turn)
+      this.pushedTo = {x: move.end.x, y: move.end.y};
+    else {
+      // All other cases: just reset both push variables
+      this.pushFrom = {x: -1, y: -1};
+      this.pushedTo = {x: -1, y: -1};
+    }
+    super.postPlay(move);
+  }
+
+  isLastMove(move) {
+    if (move.appear.length == 0) //move.vanish[0].p == 's'
+      return false;
+    return super.isLastMove(move);
+  }
+
   underAttack([x, y], oppCols) {
   underAttack([x, y], oppCols) {
+    if (super.underAttack([x, y], oppCols))
+      return true;
     // TODO: check enemy sentry(ies), for each, check all of our own pieces which attack the square (if belonging to opponent!). Then, call :
     // TODO: check enemy sentry(ies), for each, check all of our own pieces which attack the square (if belonging to opponent!). Then, call :
-    return super.underAttack([x, y], oppCols);
+    const oppCol = oppCols[0];
+    for (let i=0; i < this.size.x; i++) {
+      for (let j=0; j < this.size.y; j++) {
+        if (
+          this.board[i][j] != "" &&
+          this.getPiece(i, j) == 's' &&
+          this.getColor(i, j) == oppCol
+        ) {
+          this.pieces()['s'].both[0].steps.forEach(s => {
+            let ii = i + s[0];
+            // TODO.........
+            if (true)
+              return true;
+          });
+        }
+      }
+    }
+    return false;
   }
 
   // Lazy sentry attacks check: after push move
   }
 
   // Lazy sentry attacks check: after push move
@@ -334,7 +360,7 @@ console.log(pmoves);
   updateReserve(color, piece, count) {
     if (V.LANCERS.includes(piece))
       // Show only one lancer orientation, and reorient when drop:
   updateReserve(color, piece, count) {
     if (V.LANCERS.includes(piece))
       // Show only one lancer orientation, and reorient when drop:
-      piece = color == 'w' ? 'c' : 'g';
+      piece = (color == 'w' ? 'c' : 'g');
     super.updateReserve(color, piece, count);
   }
 
     super.updateReserve(color, piece, count);
   }