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
{
9 select: C
.Options
.select
,
10 input: C
.Options
.input
,
12 "atomic", "cannibal", "capture", "cylinder",
13 "dark", "madrasi", "rifle", "teleport"
18 // Does not really seem necessary (although the author mention it)
19 // Instead, first move = pick a square for the king.
29 { 'u': {"class": "undefined"} },
30 super.pieces(color
, x
, y
)
35 return this.movesCount
<= 1;
38 // Initiate the game by choosing a square for the king:
40 const color
= this.turn
;
42 this.movesCount
<= 1 &&
44 (color
== 'w' && coords
.x
== this.size
.x
- 1) ||
45 (color
== 'b' && coords
.x
== 0)
49 appear: [ new PiPo({x: coords
.x
, y: coords
.y
, c: color
, p: 'k' }) ],
50 vanish: [ new PiPo({x: coords
.x
, y: coords
.y
, c: color
, p: 'u' }) ]
56 genRandInitBaseFen() {
58 fen: "uuuuuuuu/pppppppp/8/8/8/8/PPPPPPPP/UUUUUUUU",
66 captureUndef: (o
.init
|| !this.captureUndef
)
68 : C
.CoordsToSquare(this.captureUndef
)
78 ["w","b"].map(c
=> Object
.values(this.reserve
[c
]).join("")).join("")
82 initReserves(reserveStr
) {
83 super.initReserves(reserveStr
, ['r', 'n', 'b', 'q']);
86 setOtherVariables(fenParsed
) {
87 super.setOtherVariables(fenParsed
);
88 this.captureUndef
= fenParsed
.captureUndef
== '-'
90 C
.SquareToCoords(fenParsed
.captureUndef
);
91 this.definition
= null;
94 canDrop([c
, p
], [i
, j
]) {
95 switch (this.subTurn
) {
97 return i
== this.captureUndef
.x
&& j
== this.captureUndef
.y
;
99 return this.getPiece(i
, j
) == 'u' && c
== this.getColor(i
, j
);
101 return false; //never reached
104 getPotentialMovesFrom([x
, y
]) {
105 if (this.movesCount
<= 1)
108 switch (this.subTurn
) {
110 if (typeof x
== "string")
111 moves
= this.getDropMovesFrom([x
, y
]);
112 // Empty move: just start + end
113 moves
.forEach(m
=> {m
.vanish
.pop(); m
.appear
.pop();});
116 // Both normal move (from defined piece) and definition allowed
117 if (typeof x
== "string")
118 moves
= this.getDropMovesFrom([x
, y
]);
119 else if (this.getPiece(x
, y
) != 'u')
120 moves
= super.getPotentialMovesFrom([x
, y
]);
123 // We can only move the just-defined piece
124 if (x
== this.definition
.x
&& y
== this.definition
.y
)
125 moves
= super.getPotentialMovesFrom([x
, y
]);
132 if (this.movesCount
<= 1 || this.subTurn
== 0)
134 let filterLater
= [];
135 if (this.subTurn
== 1) {
136 // Remove defining moves with un-movable def piece,
137 // and separate compatible definitions.
138 moves
= moves
.filter(m
=> {
139 if (m
.vanish
.length
>= 2 || m
.vanish
[0].p
!= 'u')
142 const canMove
= super.filterValid(
143 super.getPotentialMovesFrom([m
.end
.x
, m
.end
.y
])).length
>= 1;
150 return super.filterValid(moves
).concat(filterLater
);
153 atLeastOneMove(color
) {
154 if (this.subTurn
!= 1)
156 return super.atLeastOneMove(color
);
159 underCheck(square_s
, oppCol
) {
160 if (super.underCheck(square_s
, oppCol
))
162 // Check potential specializations of undefined using reserve:
163 const inReserve
= Object
.keys(this.reserve
[oppCol
])
164 .filter(k
=> this.reserve
[oppCol
][k
] >= 1);
165 const allAttacks
= Array
.prototype.concat
.apply(
166 inReserve
.map(p
=> this.pieces()[p
].both
[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
|| move.next
) {
205 this.tryChangeTurn();
208 if (this.subTurn
== 0)
209 this.captureUndef
= null; //already used
210 const captureUndef
= (
211 move.vanish
.length
== 2 && //exclude subTurn == 0
212 move.vanish
[1].c
!= color
&&
213 move.vanish
[1].p
== 'u'
215 if (typeof move.start
.x
== "number" && !captureUndef
)
216 // Normal move (including Teleport)
217 super.postPlay(move);
218 else if (typeof move.start
.x
== "string") {
220 color
, move.start
.y
, this.reserve
[color
][move.start
.y
] - 1);
221 if (move.vanish
.length
== 1 && move.vanish
[0].p
== 'u')
222 this.definition
= move.end
;
227 this.captureUndef
= move.end
;
228 this.tryChangeTurn(null, captureUndef
);
232 // NOTE: not "trying", the turn always change here (TODO?)
233 tryChangeTurn(move, captureUndef
) {
234 this.definition
= null;
235 this.subTurn
= captureUndef
? 0 : 1;
236 this.turn
= C
.GetOppTurn(this.turn
);
240 computeNextMove(move) {
242 !this.definition
|| this.playerColor
!= this.turn
||
243 this.board
.some(row
=> row
.some(cell
=>
244 cell
.charAt(0) == this.turn
&& cell
.charAt(1) == 'u'))
248 const variety
= (c
) => {
251 Array
.prototype.concat
.apply([],
252 this.board
.map(row
=>
254 cell
.charAt(0) == c
&& !['p', 'k'].includes(cell
.charAt(1))
255 ).map(cell
=> cell
.charAt(1))
261 let next
= {start: move.end
, end: move.end
, vanish: [], appear: []};
262 this.playOnBoard(move);
263 const twoOrMorePieces
= {w: variety('w'), b: variety('b')};
265 Object
.keys(twoOrMorePieces
).filter(k
=> twoOrMorePieces
[k
]);
266 if (resetCols
.length
>= 1) {
267 for (let i
=0; i
<this.size
.x
; i
++) {
268 for (let j
=0; j
<this.size
.y
; j
++) {
269 const colIJ
= this.getColor(i
, j
);
270 const pieceIJ
= this.getPiece(i
, j
);
272 resetCols
.includes(colIJ
) &&
273 this.board
[i
][j
] != "" &&
274 !['p', 'k', 'u'].includes(pieceIJ
)
276 // NOTE: could also use a "flip" strategy similar to Benedict
277 next
.vanish
.push(new PiPo({c: colIJ
, p: pieceIJ
, x: i
, y: j
}));
278 next
.appear
.push(new PiPo({c: colIJ
, p: 'u', x: i
, y: j
}));
279 this.reserve
[colIJ
][pieceIJ
]++;
283 super.re_drawReserve(resetCols
);
285 this.undoOnBoard(move);
286 if (next
.vanish
.length
>= 1) {
293 return true; //called only on normal moves (not Teleport)
296 getCurrentScore(move_s
) {
297 return (this.movesCount
<= 2 ? "*" : super.getCurrentScore(move_s
));