From 7bd7cba41f9c2222a29c62ddf8d83fbb46646a1d Mon Sep 17 00:00:00 2001
From: Benjamin Auder <benjamin.auder@somewhere>
Date: Mon, 25 Jul 2022 16:11:58 +0200
Subject: [PATCH] Fix Weiqi

---
 variants/Weiqi/class.js | 81 +++++++++++++++++++++++------------------
 1 file changed, 45 insertions(+), 36 deletions(-)

diff --git a/variants/Weiqi/class.js b/variants/Weiqi/class.js
index ce8531f..714ada8 100644
--- a/variants/Weiqi/class.js
+++ b/variants/Weiqi/class.js
@@ -90,9 +90,19 @@ export default class WeiqiRules extends ChessRules {
   constructor(o) {
     super(o);
     if (!o.genFenOnly && !o.diagram) {
-      
-      this.passListener = () => this.play({pass: true}); //TODO: wrong, need to use buildMoveStack (warning empty move...)
-
+      this.passListener = () => {
+        if (this.turn == this.playerColor) {
+          let mv = {
+            // Need artificial start/end for animate (TODO?)
+            start: {x: -1, y: -1},
+            end: {x: -1, y: -1},
+            appear: [],
+            vanish: [],
+            pass: true
+          };
+          this.buildMoveStack(mv);
+        }
+      };
       // Show pass btn
       let passBtn = document.createElement("button");
       C.AddClass_es(passBtn, "pass-btn");
@@ -105,8 +115,9 @@ export default class WeiqiRules extends ChessRules {
 
   removeListeners() {
     super.removeListeners();
-    let passBtn = document.getElementsByClassName("pass-btn")[0];
-    passBtn.removeEventListener("click", this.passListener);
+    let passBtn_arr = document.getElementsByClassName("pass-btn");
+    if (passBtn_arr.length >= 1)
+      passBtn_arr[0].removeEventListener("click", this.passListener);
   }
 
   pieces(color, x, y) {
@@ -123,40 +134,35 @@ export default class WeiqiRules extends ChessRules {
 
   doClick(coords) {
     const [x, y] = [coords.x, coords.y];
-    if (this.board[x][y] != "")
+    if (this.board[x][y] != "" || this.turn != this.playerColor)
       return null;
     const color = this.turn;
     const oppCol = C.GetOppCol(color);
     let move = new Move({
-      appear: [ new PiPo({ x: x, y: y, c: color, p: 's' }) ],
+      appear: [new PiPo({x: x, y: y, c: color, p: 's'})],
       vanish: [],
       start: {x: x, y: y}
     });
     this.playOnBoard(move); //put the stone
-    let noSuicide = false;
     let captures = [];
+    let inCaptures = {};
+    let explored = ArrayFun.init(this.size.x, this.size.y, false);
+    const suicide = !this.searchForEmptySpace([x, y], color, explored);
     for (let s of [[0, 1], [1, 0], [0, -1], [-1, 0]]) {
       const [i, j] = [x + s[0], y + s[1]];
-      if (this.onBoard(i, j)) {
-        if (this.board[i][j] == "")
-          noSuicide = true; //clearly
-        else if (this.getColor(i, j) == color) {
-          // Free space for us = not a suicide
-          if (!noSuicide) {
-            let explored = ArrayFun.init(this.size.x, this.size.y, false);
-            noSuicide = this.searchForEmptySpace([i, j], color, explored);
-          }
-        }
-        else {
-          // Free space for opponent = not a capture
-          let explored = ArrayFun.init(this.size.x, this.size.y, false);
+      if (this.onBoard(i, j) && !inCaptures[i + "." + j]) {
+        if (this.getColor(i, j) == oppCol) {
+          // Free space for opponent => not a capture
+          let oppExplored = ArrayFun.init(this.size.x, this.size.y, false);
           const captureSomething =
-            !this.searchForEmptySpace([i, j], oppCol, explored);
+            !this.searchForEmptySpace([i, j], oppCol, oppExplored);
           if (captureSomething) {
             for (let ii = 0; ii < this.size.x; ii++) {
               for (let jj = 0; jj < this.size.y; jj++) {
-                if (explored[ii][jj])
-                  captures.push(new PiPo({ x: ii, y: jj, c: oppCol, p: 's' }));
+                if (oppExplored[ii][jj]) {
+                  captures.push(new PiPo({x: ii, y: jj, c: oppCol, p: 's'}));
+                  inCaptures[ii + "." + jj] = true;
+                }
               }
             }
           }
@@ -164,35 +170,38 @@ export default class WeiqiRules extends ChessRules {
       }
     }
     this.undoOnBoard(move); //remove the stone
-    if (!noSuicide && captures.length == 0)
+    if (suicide && captures.length == 0)
       return null;
     Array.prototype.push.apply(move.vanish, captures);
     return move;
   }
 
   searchForEmptySpace([x, y], color, explored) {
-    if (explored[x][y])
-      return false; //didn't find empty space
     explored[x][y] = true;
-    let res = false;
     for (let s of [[1, 0], [0, 1], [-1, 0], [0, -1]]) {
       const [i, j] = [x + s[0], y + s[1]];
-      if (this.onBoard(i, j)) {
-        if (this.board[i][j] == "")
-          res = true;
-        else if (this.getColor(i, j) == color)
-          res = this.searchForEmptySpace([i, j], color, explored) || res;
+      if (
+        this.onBoard(i, j) &&
+        !explored[i][j] &&
+        (
+          this.board[i][j] == "" ||
+          (
+            this.getColor(i, j) == color &&
+            this.searchForEmptySpace([i, j], color, explored)
+          )
+        )
+      ) {
+        return true;
       }
     }
-    return res;
+    return false;
   }
 
   play(move) {
     if (move.pass) {
       if (this.turn != this.playerColor)
         super.displayMessage(null, "pass", "pass-text", 2000);
-      else
-        this.turn = C.GetOppCol(this.turn);
+      this.turn = C.GetOppCol(this.turn);
     }
     else
       super.play(move);
-- 
2.44.0