6a44834a7623b3c58e90131c173edb24a8fb8695
1 import ChessRules
from "/base_rules.js";
2 import PiPo
from "/utils/PiPo.js";
3 import Move
from "/utils/Move.js";
5 export default class BarioRules
extends ChessRules
{
11 "atomic", "cannibal", "capture", "cylinder",
12 "dark", "madrasi", "rifle", "teleport"
17 // Does not really seem necessary (although the author mention it)
18 // Instead, first move = pick a square for the king.
34 super.pieces(color
, x
, y
)
39 return this.movesCount
<= 1;
42 // Initiate the game by choosing a square for the king:
44 const color
= this.turn
;
46 this.movesCount
<= 1 &&
48 (color
== 'w' && coords
.x
== this.size
.x
- 1) ||
49 (color
== 'b' && coords
.x
== 0)
53 appear: [ new PiPo({x: coords
.x
, y: coords
.y
, c: color
, p: 'k' }) ],
54 vanish: [ new PiPo({x: coords
.x
, y: coords
.y
, c: color
, p: 'u' }) ]
60 genRandInitBaseFen() {
62 fen: "uuuuuuuu/pppppppp/8/8/8/8/PPPPPPPP/UUUUUUUU",
70 captureUndef: (o
.init
|| !this.captureUndef
)
72 : C
.CoordsToSquare(this.captureUndef
)
82 ["w","b"].map(c
=> Object
.values(this.reserve
[c
]).join("")).join("")
86 initReserves(reserveStr
) {
87 super.initReserves(reserveStr
, ['r', 'n', 'b', 'q']);
90 setOtherVariables(fenParsed
) {
91 super.setOtherVariables(fenParsed
);
92 this.captureUndef
= fenParsed
.captureUndef
== '-'
94 C
.SquareToCoords(fenParsed
.captureUndef
);
95 this.definition
= null;
98 canDrop([c
, p
], [i
, j
]) {
99 switch (this.subTurn
) {
101 return i
== this.captureUndef
.x
&& j
== this.captureUndef
.y
;
103 return this.getPiece(i
, j
) == 'u' && c
== this.getColor(i
, j
);
105 return false; //never reached
108 getPotentialMovesFrom([x
, y
]) {
109 if (this.movesCount
<= 1)
112 switch (this.subTurn
) {
114 if (typeof x
== "string")
115 moves
= this.getDropMovesFrom([x
, y
]);
118 // Both normal move (from defined piece) and definition allowed
119 if (typeof x
== "string")
120 moves
= this.getDropMovesFrom([x
, y
]);
121 else if (this.getPiece(x
, y
) != 'u')
122 moves
= super.getPotentialMovesFrom([x
, y
]);
125 // We can only move the just-defined piece
126 if (x
== this.definition
.x
&& y
== this.definition
.y
)
127 moves
= super.getPotentialMovesFrom([x
, y
]);
134 if (this.movesCount
<= 1 || this.subTurn
== 0)
136 let filterLater
= [];
137 if (this.subTurn
== 1) {
138 // Remove defining moves with un-movable def piece,
139 // and separate compatible definitions.
140 moves
= moves
.filter(m
=> {
141 if (m
.vanish
.length
>= 2 || m
.vanish
[0].p
!= 'u')
144 const canMove
= super.filterValid(
145 super.getPotentialMovesFrom([m
.end
.x
, m
.end
.y
])).length
>= 1;
152 return super.filterValid(moves
).concat(filterLater
);
155 atLeastOneMove(color
) {
156 if (this.subTurn
!= 1)
158 return super.atLeastOneMove(color
);
161 underCheck(square_s
, oppCol
) {
162 if (super.underCheck(square_s
, oppCol
))
164 // Check potential specializations of undefined using reserve:
165 const allAttacks
= Array
.prototype.concat
.apply(
166 ['r', 'n', 'b', 'q'].map(p
=> this.pieces()[p
].moves
[0]));
167 const [x
, y
] = square_s
[0];
168 for (let i
=0; i
<this.size
.x
; i
++) {
169 for (let j
=0; j
<this.size
.y
; j
++) {
171 this.board
[i
][j
] != "" &&
172 this.getColor(i
, j
) == oppCol
&&
173 this.getPiece(i
, j
) == 'u'
175 for (let stepDef
of allAttacks
) {
176 for (let s
of stepDef
.steps
) {
177 if (!super.compatibleStep([i
, j
], [x
, y
], s
, stepDef
.range
))
180 super.findDestSquares(
183 captureTarget: [x
, y
],
184 captureSteps: [{steps: [s
], range: stepDef
.range
}],
202 const color
= this.turn
;
203 if (this.movesCount
<= 1 || move.reset
) {
204 this.tryChangeTurn();
207 if (this.subTurn
== 0)
208 this.captureUndef
= null; //already used
209 const captureUndef
= (
210 move.vanish
.length
== 2 && //exclude subTurn == 0
211 move.vanish
[1].c
!= color
&&
212 move.vanish
[1].p
== 'u'
214 if (typeof move.start
.x
== "number" && !captureUndef
)
215 // Normal move (including Teleport)
216 super.postPlay(move);
217 else if (typeof move.start
.x
== "string") {
219 color
, move.appear
[0].p
, this.reserve
[color
][move.appear
[0].p
] - 1);
220 if (move.vanish
.length
== 1 && move.vanish
[0].p
== 'u')
221 this.definition
= move.end
;
226 this.captureUndef
= move.end
;
227 this.tryChangeTurn(move, captureUndef
);
231 // NOTE: not "try" here, we know the turn changes (TODO?)
232 tryChangeTurn(move, captureUndef
) {
233 this.definition
= null;
234 this.subTurn
= captureUndef
? 0 : 1;
235 this.turn
= C
.GetOppCol(this.turn
);
239 computeNextMove(move) {
241 !this.definition
|| this.playerColor
!= this.turn
||
242 this.board
.some(row
=> row
.some(cell
=>
243 cell
.charAt(0) == this.turn
&& cell
.charAt(1) == 'u'))
247 const variety
= (c
) => {
250 Array
.prototype.concat
.apply([],
251 this.board
.map(row
=>
253 cell
.charAt(0) == c
&& !['p', 'k'].includes(cell
.charAt(1))
254 ).map(cell
=> cell
.charAt(1))
260 this.playOnBoard(move);
261 let next
= {start: move.end
, end: move.end
, vanish: [], appear: []};
262 for (let c
of ['w', 'b']) {
264 for (let i
=0; i
<this.size
.x
; i
++) {
265 for (let j
=0; j
<this.size
.y
; j
++) {
266 const pieceIJ
= this.getPiece(i
, j
);
268 this.board
[i
][j
] != "" &&
269 !['p', 'k', 'u'].includes(pieceIJ
)
271 // NOTE: could also use a "flip" strategy similar to Benedict
272 next
.vanish
.push(new PiPo({c: c
, p: pieceIJ
, x: i
, y: j
}));
273 next
.appear
.push(new PiPo({c: c
, p: 'u', x: i
, y: j
}));
274 this.reserve
[c
][pieceIJ
]++;
278 super.re_drawReserve([c
]);
281 this.undoOnBoard(move);
282 if (next
.vanish
.length
>= 1) {
289 return true; //called only on normal moves (not Teleport)
292 getCurrentScore(move_s
) {
293 return (this.movesCount
<= 2 ? "*" : super.getCurrentScore(move_s
));