X-Git-Url: https://git.auder.net/?a=blobdiff_plain;f=variants%2FWeiqi%2Fclass.js;h=ca13fe10fda62a663746e546d336d0e2aec00bf8;hb=c9a20f4f198e1877bd260a610b1692b3d65d0eba;hp=e528719e684c1d38976ed5b75a6715f8761d40b2;hpb=3cc4a84559092337d916c83367a6b457d6ca2b02;p=xogo.git diff --git a/variants/Weiqi/class.js b/variants/Weiqi/class.js index e528719..ca13fe1 100644 --- a/variants/Weiqi/class.js +++ b/variants/Weiqi/class.js @@ -1,8 +1,3 @@ -//TODO: -// - pass btn on top + message if opponent just passed -// - do not count points: rely on players' ability to do that -// - implement Ko rule (need something in fen: lastMove) - import ChessRules from "/base_rules.js"; import Move from "/utils/Move.js"; import PiPo from "/utils/PiPo.js"; @@ -10,7 +5,6 @@ import {ArrayFun} from "/utils/array.js"; export default class WeiqiRules extends ChessRules { - // TODO: option oneColor (just alter pieces class of white stones) static get Options() { return { input: [ @@ -19,6 +13,12 @@ export default class WeiqiRules extends ChessRules { variable: "bsize", type: "number", defaut: 9 + }, + { + label: "One color", + variable: "onecolor", + type: "checkbox", + defaut: false } ] }; @@ -82,15 +82,51 @@ export default class WeiqiRules extends ChessRules { genRandInitBaseFen() { const fenLine = C.FenEmptySquares(this.size.y); return { - fen: (fenLine + '/').repeat(this.size.x - 1) + fenLine + " w 0", + fen: (fenLine + '/').repeat(this.size.x - 1) + fenLine, o: {} }; } + constructor(o) { + super(o); + if (!o.diagram) { + 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"); + passBtn.innerHTML = "pass"; + passBtn.addEventListener("click", this.passListener); + let container = document.getElementById(this.containerId); + container.appendChild(passBtn); + } + } + + removeListeners() { + super.removeListeners(); + let passBtn_arr = document.getElementsByClassName("pass-btn"); + if (passBtn_arr.length >= 1) + passBtn_arr[0].removeEventListener("click", this.passListener); + } + pieces(color, x, y) { + let classe_s = ["stone"]; + if (this.options["onecolor"] && color == 'w') + classe_s.push("one-color"); return { 's': { - "class": "stone", + "class": classe_s, moves: [] } }; @@ -98,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; + } } } } @@ -139,27 +170,41 @@ 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); + this.turn = C.GetOppCol(this.turn); + } + else + super.play(move); } filterValid(moves) {