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
,
93 this.passListener
= () => {
94 if (this.turn
== this.playerColor
) {
96 // Need artificial start/end for animate (TODO?)
97 start: {x: -1, y: -1},
103 this.buildMoveStack(mv
);
107 let passBtn
= document
.createElement("button");
108 C
.AddClass_es(passBtn
, "pass-btn");
109 passBtn
.innerHTML
= "pass";
110 passBtn
.addEventListener("click", this.passListener
);
111 let container
= document
.getElementById(this.containerId
);
112 container
.appendChild(passBtn
);
117 super.removeListeners();
118 let passBtn_arr
= document
.getElementsByClassName("pass-btn");
119 if (passBtn_arr
.length
>= 1)
120 passBtn_arr
[0].removeEventListener("click", this.passListener
);
123 pieces(color
, x
, y
) {
124 let classe_s
= ["stone"];
125 if (this.options
["onecolor"] && color
== 'w')
126 classe_s
.push("one-color");
136 const [x
, y
] = [coords
.x
, coords
.y
];
137 if (this.board
[x
][y
] != "" || this.turn
!= this.playerColor
)
139 const color
= this.turn
;
140 const oppCol
= C
.GetOppCol(color
);
141 let move = new Move({
142 appear: [new PiPo({x: x
, y: y
, c: color
, p: 's'})],
146 this.playOnBoard(move); //put the stone
149 let explored
= ArrayFun
.init(this.size
.x
, this.size
.y
, false);
150 const suicide
= !this.searchForEmptySpace([x
, y
], color
, explored
);
151 for (let s
of [[0, 1], [1, 0], [0, -1], [-1, 0]]) {
152 const [i
, j
] = [x
+ s
[0], y
+ s
[1]];
153 if (this.onBoard(i
, j
) && !inCaptures
[i
+ "." + j
]) {
154 if (this.getColor(i
, j
) == oppCol
) {
155 // Free space for opponent => not a capture
156 let oppExplored
= ArrayFun
.init(this.size
.x
, this.size
.y
, false);
157 const captureSomething
=
158 !this.searchForEmptySpace([i
, j
], oppCol
, oppExplored
);
159 if (captureSomething
) {
160 for (let ii
= 0; ii
< this.size
.x
; ii
++) {
161 for (let jj
= 0; jj
< this.size
.y
; jj
++) {
162 if (oppExplored
[ii
][jj
]) {
163 captures
.push(new PiPo({x: ii
, y: jj
, c: oppCol
, p: 's'}));
164 inCaptures
[ii
+ "." + jj
] = true;
172 this.undoOnBoard(move); //remove the stone
173 if (suicide
&& captures
.length
== 0)
175 Array
.prototype.push
.apply(move.vanish
, captures
);
179 searchForEmptySpace([x
, y
], color
, explored
) {
180 explored
[x
][y
] = true;
181 for (let s
of [[1, 0], [0, 1], [-1, 0], [0, -1]]) {
182 const [i
, j
] = [x
+ s
[0], y
+ s
[1]];
184 this.onBoard(i
, j
) &&
187 this.board
[i
][j
] == "" ||
189 this.getColor(i
, j
) == color
&&
190 this.searchForEmptySpace([i
, j
], color
, explored
)
202 if (this.turn
!= this.playerColor
)
203 super.displayMessage(null, "pass", "pass-text", 2000);
204 this.turn
= C
.GetOppCol(this.turn
);
211 // Suicide check not here, because side-computation of captures
216 return "*"; //Go game is a little special...