From 727f2e558776b14a29cb1552a05a88cc9a4b0297 Mon Sep 17 00:00:00 2001
From: Benjamin Auder <benjamin.auder@somewhere>
Date: Mon, 30 Jan 2023 09:23:50 +0100
Subject: [PATCH] Various bug fixes

---
 base_rules.js                      |  9 ++++++--
 variants.js                        |  2 +-
 variants/Allmate/class.js          |  4 ++--
 variants/Antiking1/class.js        |  2 +-
 variants/Benedict/class.js         |  5 ++---
 variants/Berolina/class.js         |  3 ++-
 variants/Berolina/rules.html       |  4 +++-
 variants/Bicolour/class.js         | 33 +++++++++++++++++++++++++-----
 variants/Bicolour/rules.html       |  8 +++++++-
 variants/Chakart/class.js          |  4 ++++
 variants/_Antiking/class.js        |  4 ++--
 variants/_Berolina/pawnSpec.js     |  4 ++--
 variants/_SpecialCaptures/class.js | 14 ++++++-------
 13 files changed, 67 insertions(+), 29 deletions(-)

diff --git a/base_rules.js b/base_rules.js
index 85666e2..e127b74 100644
--- a/base_rules.js
+++ b/base_rules.js
@@ -1321,6 +1321,11 @@ export default class ChessRules {
     return this.getColor(x1, y1) !== this.getColor(x2, y2);
   }
 
+  // TODO: currently unused, but makes sense?
+  canSelfTake([x1, y1], [x2, y2]) {
+    return true;
+  }
+
   canStepOver(i, j, p) {
     // In some variants, objects on boards don't stop movement (Chakart)
     return this.board[i][j] == "";
@@ -1724,7 +1729,7 @@ export default class ChessRules {
     }
     return squares.map(s => {
       let mv = this.getBasicMove([x, y], s.sq);
-      if (this.options["cylinder"] && s.segments.length >= 2)
+      if (this.options["cylinder"] && !!s.segments && s.segments.length >= 2)
         mv.segments = s.segments;
       return mv;
     });
@@ -1742,7 +1747,7 @@ export default class ChessRules {
     const addSquare = ([i, j]) => {
       let elt = {sq: [i, j]};
       if (o.segments)
-        elt.segments = this.getSegments(segments, segStart, end);
+        elt.segments = this.getSegments(segments, segStart, [i, j]);
       res.push(elt);
     };
     const exploreSteps = (stepArray, mode) => {
diff --git a/variants.js b/variants.js
index 73af2c7..db500f5 100644
--- a/variants.js
+++ b/variants.js
@@ -116,9 +116,9 @@ const variants = [
 //  {name: 'Racingkings', desc: 'Kings cross the 8x8 board', disp: 'Racing Kings'},
 //  {name: 'Rampage', desc: 'Move under cover'},
 //  {name: 'Relayup', desc: 'Upgrade pieces', disp: 'Relay-up'},
-  {name: 'Rifle', desc: 'Shoot pieces'},
   {name: 'Recycle', desc: 'Reuse pieces'},
   {name: 'Refusal', desc: 'Do not play that!'},
+  {name: 'Rifle', desc: 'Shoot pieces'},
 //  {name: 'Rollerball', desc: 'As in the movie'},
 //  {name: 'Rococo', desc: 'Capture on the edge'},
 //  {name: 'Royalrace', desc: 'Kings cross the 11x11 board', disp: 'Royal Race'},
diff --git a/variants/Allmate/class.js b/variants/Allmate/class.js
index e491e6d..9493e6c 100644
--- a/variants/Allmate/class.js
+++ b/variants/Allmate/class.js
@@ -59,7 +59,7 @@ export default class AllmateRules extends ChessRules {
   // is piece on square x,y mated by color?
   isMated(x, y, color) {
     const myColor = C.GetOppTurn(color);
-    if (!super.underAttack([x, y], color))
+    if (!super.underAttack([x, y], [color]))
       return false;
     for (let i=0; i<this.size.x; i++) {
       for (let j=0; j<this.size.y; j++) {
@@ -71,7 +71,7 @@ export default class AllmateRules extends ChessRules {
             if (i == x && j == y) {
               // The mated-candidate has moved itself
               testSquare = [move.end.x, move.end.y]; }
-            const res = this.underAttack(testSquare, color);
+            const res = this.underAttack(testSquare, [color]);
             this.undoOnBoard(move);
             if (!res)
               return false;
diff --git a/variants/Antiking1/class.js b/variants/Antiking1/class.js
index d536680..c625e89 100644
--- a/variants/Antiking1/class.js
+++ b/variants/Antiking1/class.js
@@ -13,7 +13,7 @@ export default class Antiking1Rules extends AbstractAntikingRules {
 
   pieces(color, x, y) {
     let res = super.pieces(color, x, y);
-    res['p'] = BerolinaPawnSpec(color);
+    res['p'] = BerolinaPawnSpec(color); //no 2-squares moves
     return res;
   }
 
diff --git a/variants/Benedict/class.js b/variants/Benedict/class.js
index 0fda796..25e1ef8 100644
--- a/variants/Benedict/class.js
+++ b/variants/Benedict/class.js
@@ -49,7 +49,7 @@ export default class BenedictRules extends AbstractFlipRules {
           },
           ([i1, j1], [i2, j2]) => {
             return (
-              super.canTake([i1, j1], [i2, j2]) &&
+              this.getColor(i2, j2) == oppCol &&
               (!this.options["zen"] || this.getPiece(i2, j2) == 'k')
             );
           }
@@ -61,8 +61,7 @@ export default class BenedictRules extends AbstractFlipRules {
               byCol: [oppCol],
               segments: this.options["cylinder"]
             },
-            ([i1, j1], [i2, j2]) =>
-              this.getPiece(i1, j1) != 'k' && super.canTake([i2, j2], [i1, j1])
+            ([i1, j1], [i2, j2]) => this.getPiece(i1, j1) != 'k'
           );
           Array.prototype.push.apply(attacks, zenAttacks);
         }
diff --git a/variants/Berolina/class.js b/variants/Berolina/class.js
index ef0ba89..18057f2 100644
--- a/variants/Berolina/class.js
+++ b/variants/Berolina/class.js
@@ -5,7 +5,8 @@ export default class BerolinaRules extends ChessRules {
 
   pieces(color, x, y) {
     let res = super.pieces(color, x, y);
-    res['p'] = BerolinaPawnSpec(color);
+    const initRank = ((color == 'w' && x == 6) || (color == 'b' && x == 1));
+    res['p'] = BerolinaPawnSpec(color, initRank);
     return res;
   }
 
diff --git a/variants/Berolina/rules.html b/variants/Berolina/rules.html
index c65158e..bfa1cca 100644
--- a/variants/Berolina/rules.html
+++ b/variants/Berolina/rules.html
@@ -1 +1,3 @@
-<p>TODO</p>
+<p>Pawns movements are reversed: they capture forward, and move diagonally. From the initial rank they can move two squares in diagonal. <a href="https://www.chessvariants.com/piececlopedia.dir/berolina.html">See also</a>.</p>
+
+<p class="author">Edmund Nebermann (1926).</p>
diff --git a/variants/Bicolour/class.js b/variants/Bicolour/class.js
index 3812d4c..e049e0c 100644
--- a/variants/Bicolour/class.js
+++ b/variants/Bicolour/class.js
@@ -4,12 +4,38 @@ import {ArrayFun} from "/utils/array.js";
 
 export default class BicolourRules extends ChessRules {
 
+  static get Options() {
+    return {
+      select: C.Options.select,
+      input: [
+        {
+          label: "King takes all",
+          variable: "takeboth",
+          type: "checkbox",
+          defaut: true
+        },
+        {
+          label: "Capture king",
+          variable: "taking",
+          type: "checkbox",
+          defaut: false
+        }
+      ],
+      styles: ["balance", "capture", "cylinder", "dark",
+               "doublemove", "madrasi", "progressive", "zen"]
+    };
+  }
+
   get hasFlags() {
     return false;
   }
 
   canTake([x1, y1], [x2, y2]) {
-    return (this.getPiece(x2, y2) == 'k' || super.canTake([x1, y1], [x2, y2]));
+    return (
+      this.getPiece(x2, y2) == 'k' ||
+      (this.getPiece(x1, y1) == 'k' && this.options["takeboth"]) ||
+      super.canTake([x1, y1], [x2, y2])
+    );
   }
 
   genRandInitBaseFen() {
@@ -102,10 +128,7 @@ export default class BicolourRules extends ChessRules {
   }
 
   underCheck(square_s) {
-    return (
-      this.underAttack(square_s[0], 'w') ||
-      this.underAttack(square_s[0], 'b')
-    );
+    return super.underCheck(square_s, ['w', 'b']);
   }
 
 };
diff --git a/variants/Bicolour/rules.html b/variants/Bicolour/rules.html
index c65158e..b4400a9 100644
--- a/variants/Bicolour/rules.html
+++ b/variants/Bicolour/rules.html
@@ -1 +1,7 @@
-<p>TODO</p>
+<p>
+  Kings are attacked by all pieces (enemy or friendly),
+  and can capture any of them - by default.
+  You can remove this last option in a customized game.
+</p>
+
+<p class="author">Gabriel Authier and Roméo Bédoni (1958).</p>
diff --git a/variants/Chakart/class.js b/variants/Chakart/class.js
index 6ddc37c..2b502b6 100644
--- a/variants/Chakart/class.js
+++ b/variants/Chakart/class.js
@@ -594,6 +594,10 @@ export default class ChakartRules extends ChessRules {
         const coords = getRandomPiece(oldColor);
         if (coords) {
           const piece = this.getPiece(coords[0], coords[1]);
+          if (coords[0] == move.start.x && coords[1] == move.start.y) {
+            // Moving piece change color: fix coords
+            coords = [move.end.x, move.end.y];
+          }
           em = new Move({
             appear: [
               new PiPo({x: coords[0], y: coords[1], c: newColor, p: piece})
diff --git a/variants/_Antiking/class.js b/variants/_Antiking/class.js
index 5838ed6..2797cad 100644
--- a/variants/_Antiking/class.js
+++ b/variants/_Antiking/class.js
@@ -60,10 +60,10 @@ export default class AbstractAntikingRules extends ChessRules {
     square_s.forEach(sq => {
       switch (this.getPiece(sq[0], sq[1])) {
         case 'k':
-          res ||= super.underAttack(sq, color);
+          res ||= super.underAttack(sq, [color]);
           break;
         case 'a':
-          res ||= !super.underAttack(sq, color);
+          res ||= !super.underAttack(sq, [color]);
           break;
       }
     });
diff --git a/variants/_Berolina/pawnSpec.js b/variants/_Berolina/pawnSpec.js
index 7cfc7be..e3d0330 100644
--- a/variants/_Berolina/pawnSpec.js
+++ b/variants/_Berolina/pawnSpec.js
@@ -1,4 +1,4 @@
-export default function (color) {
+export default function (color, initRank) {
 
   const pawnShift = (color == "w" ? -1 : 1);
   return {
@@ -6,7 +6,7 @@ export default function (color) {
     moves: [
       {
         steps: [[pawnShift, 1], [pawnShift, -1]],
-        range: 1
+        range: (initRank ? 2 : 1)
       }
     ],
     attack: [
diff --git a/variants/_SpecialCaptures/class.js b/variants/_SpecialCaptures/class.js
index 0c2a300..7d9f786 100644
--- a/variants/_SpecialCaptures/class.js
+++ b/variants/_SpecialCaptures/class.js
@@ -22,7 +22,7 @@ export default class AbstractSpecialCaptureRules extends ChessRules {
   // Modify capturing moves among listed pincer moves
   addPincerCaptures(moves, byChameleon) {
     const steps = this.pieces()['p'].moves[0].steps;
-    const color = this.turn;
+    const color = moves[0].vanish[0].c;
     const oppCol = C.GetOppTurn(color);
     moves.forEach(m => {
       if (byChameleon && m.start.x != m.end.x && m.start.y != m.end.y)
@@ -60,7 +60,7 @@ export default class AbstractSpecialCaptureRules extends ChessRules {
   }
 
   addCoordinatorCaptures(moves, byChameleon) {
-    const color = this.turn;
+    const color = moves[0].vanish[0].c;
     const oppCol = V.GetOppTurn(color);
     const kp = this.searchKingPos(color)[0];
     moves.forEach(m => {
@@ -90,7 +90,7 @@ export default class AbstractSpecialCaptureRules extends ChessRules {
   getLeaperCaptures([x, y], byChameleon, onlyOne) {
     // Look in every direction for captures
     const steps = this.pieces()['r'].moves[0].steps;
-    const color = this.turn;
+    const color = this.getColor(x, y);
     const oppCol = C.GetOppTurn(color);
     let moves = [];
     outerLoop: for (let step of steps) {
@@ -154,12 +154,10 @@ export default class AbstractSpecialCaptureRules extends ChessRules {
 
   // type: nothing (freely, capture all), or pull or push, or "exclusive"
   addPushmePullyouCaptures(moves, byChameleon, type) {
-    if (moves.length == 0)
-      return;
     const [sx, sy] = [moves[0].start.x, moves[0].start.y];
     const adjacentSteps = this.pieces()['r'].moves[0].steps;
     let capturingPullDir = {};
-    const color = this.turn;
+    const color = moves[0].vanish[0].c;
     const oppCol = C.GetOppTurn(color);
     if (type != "push") {
       adjacentSteps.forEach(step => {
@@ -216,14 +214,14 @@ export default class AbstractSpecialCaptureRules extends ChessRules {
     });
   }
 
-  underAttack([x, y], oppCol) {
+  underAttack([x, y], oppCols) {
     // Generate all potential opponent moves, check if king captured.
     // TODO: do it more efficiently.
     const color = this.getColor(x, y);
     for (let i = 0; i < this.size.x; i++) {
       for (let j = 0; j < this.size.y; j++) {
         if (
-          this.board[i][j] != "" && this.getColor(i, j) == oppCol &&
+          this.board[i][j] != "" && oppCols.includes(this.getColor(i, j)) &&
           this.getPotentialMovesFrom([i, j]).some(m => {
             return (
               m.vanish.length >= 2 &&
-- 
2.44.0