1 import ChessRules
from "/base_rules.js";
2 import Move
from "/utils/Move.js";
3 import PiPo
from "/utils/PiPo.js";
4 import {ArrayFun
} from "/utils/array.js";
6 export default class WeiqiRules
extends ChessRules
{
38 const flipped
= (this.playerColor
== 'b');
41 viewBox="0 0 ${10*(this.size.y)} ${10*(this.size.x)}"
42 class="chessboard_SVG">`;
43 for (let i
=0; i
< this.size
.x
; i
++) {
44 for (let j
=0; j
< this.size
.y
; j
++) {
45 const ii
= (flipped
? this.size
.x
- 1 - i : i
);
46 const jj
= (flipped
? this.size
.y
- 1 - j : j
);
49 id="${this.coordsToId({x: ii, y: jj})}"
58 // Add lines to delimitate "squares"
59 for (let i
= 0; i
< this.size
.x
; i
++) {
60 const y
= i
* 10 + 5, maxX
= this.size
.y
* 10 - 5;
62 <line x1="5" y1="${y}" x2="${maxX}" y2="${y}"
63 stroke="black" stroke-width="0.2"/>`;
65 for (let i
= 0; i
< this.size
.x
; i
++) {
66 const x
= i
* 10 + 5, maxY
= this.size
.x
* 10 - 5;
68 <line x1="${x}" y1="5" x2="${x}" y2="${maxY}"
69 stroke="black" stroke-width="0.2"/>`;
77 x: this.options
["bsize"],
78 y: this.options
["bsize"],
82 genRandInitBaseFen() {
83 const fenLine
= C
.FenEmptySquares(this.size
.y
);
85 fen: (fenLine
+ '/').repeat(this.size
.x
- 1) + fenLine
,
92 if (!o
.genFenOnly
&& !o
.diagram
) {
94 this.passListener
= () => this.play({pass: true}); //TODO: wrong, need to use buildMoveStack (warning empty move...)
97 let passBtn
= document
.createElement("button");
98 C
.AddClass_es(passBtn
, "pass-btn");
99 passBtn
.innerHTML
= "pass";
100 passBtn
.addEventListener("click", this.passListener
);
101 let container
= document
.getElementById(this.containerId
);
102 container
.appendChild(passBtn
);
107 super.removeListeners();
108 let passBtn
= document
.getElementsByClassName("pass-btn")[0];
109 passBtn
.removeEventListener("click", this.passListener
);
112 pieces(color
, x
, y
) {
113 let classe_s
= ["stone"];
114 if (this.options
["onecolor"] && color
== 'w')
115 classe_s
.push("one-color");
125 const [x
, y
] = [coords
.x
, coords
.y
];
126 if (this.board
[x
][y
] != "")
128 const color
= this.turn
;
129 const oppCol
= C
.GetOppCol(color
);
130 let move = new Move({
131 appear: [ new PiPo({ x: x
, y: y
, c: color
, p: 's' }) ],
135 this.playOnBoard(move); //put the stone
136 let noSuicide
= false;
138 for (let s
of [[0, 1], [1, 0], [0, -1], [-1, 0]]) {
139 const [i
, j
] = [x
+ s
[0], y
+ s
[1]];
140 if (this.onBoard(i
, j
)) {
141 if (this.board
[i
][j
] == "")
142 noSuicide
= true; //clearly
143 else if (this.getColor(i
, j
) == color
) {
144 // Free space for us = not a suicide
146 let explored
= ArrayFun
.init(this.size
.x
, this.size
.y
, false);
147 noSuicide
= this.searchForEmptySpace([i
, j
], color
, explored
);
151 // Free space for opponent = not a capture
152 let explored
= ArrayFun
.init(this.size
.x
, this.size
.y
, false);
153 const captureSomething
=
154 !this.searchForEmptySpace([i
, j
], oppCol
, explored
);
155 if (captureSomething
) {
156 for (let ii
= 0; ii
< this.size
.x
; ii
++) {
157 for (let jj
= 0; jj
< this.size
.y
; jj
++) {
158 if (explored
[ii
][jj
])
159 captures
.push(new PiPo({ x: ii
, y: jj
, c: oppCol
, p: 's' }));
166 this.undoOnBoard(move); //remove the stone
167 if (!noSuicide
&& captures
.length
== 0)
169 Array
.prototype.push
.apply(move.vanish
, captures
);
173 searchForEmptySpace([x
, y
], color
, explored
) {
175 return false; //didn't find empty space
176 explored
[x
][y
] = true;
178 for (let s
of [[1, 0], [0, 1], [-1, 0], [0, -1]]) {
179 const [i
, j
] = [x
+ s
[0], y
+ s
[1]];
180 if (this.onBoard(i
, j
)) {
181 if (this.board
[i
][j
] == "")
183 else if (this.getColor(i
, j
) == color
)
184 res
= this.searchForEmptySpace([i
, j
], color
, explored
) || res
;
192 if (this.turn
!= this.playerColor
)
193 super.displayMessage(null, "pass", "pass-text", 2000);
195 this.turn
= C
.GetOppCol(this.turn
);
202 // Suicide check not here, because side-computation of captures
207 return "*"; //Go game is a little special...