01cb3d7f8ed33f44c54047ad76893a19b5a15eab
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.
35 super.pieces(color
, x
, y
)
40 return this.movesCount
<= 1;
43 // Initiate the game by choosing a square for the king:
45 const color
= this.turn
;
47 this.movesCount
<= 1 &&
49 (color
== 'w' && coords
.x
== this.size
.x
- 1) ||
50 (color
== 'b' && coords
.x
== 0)
54 appear: [ new PiPo({x: coords
.x
, y: coords
.y
, c: color
, p: 'k' }) ],
55 vanish: [ new PiPo({x: coords
.x
, y: coords
.y
, c: color
, p: 'u' }) ]
61 genRandInitBaseFen() {
63 fen: "uuuuuuuu/pppppppp/8/8/8/8/PPPPPPPP/UUUUUUUU",
71 captureUndef: (o
.init
|| !this.captureUndef
)
73 : C
.CoordsToSquare(this.captureUndef
)
83 ["w","b"].map(c
=> Object
.values(this.reserve
[c
]).join("")).join("")
87 initReserves(reserveStr
) {
88 super.initReserves(reserveStr
, ['r', 'n', 'b', 'q']);
91 setOtherVariables(fenParsed
) {
92 super.setOtherVariables(fenParsed
);
93 this.captureUndef
= fenParsed
.captureUndef
== '-'
95 C
.SquareToCoords(fenParsed
.captureUndef
);
96 this.definition
= null;
99 canDrop([c
, p
], [i
, j
]) {
100 switch (this.subTurn
) {
102 return i
== this.captureUndef
.x
&& j
== this.captureUndef
.y
;
104 return this.getPiece(i
, j
) == 'u' && c
== this.getColor(i
, j
);
106 return false; //never reached
109 getPotentialMovesFrom([x
, y
]) {
110 if (this.movesCount
<= 1)
113 switch (this.subTurn
) {
115 if (typeof x
== "string")
116 moves
= this.getDropMovesFrom([x
, y
]);
117 // Empty move: just start + end
118 moves
.forEach(m
=> {m
.vanish
.pop(); m
.appear
.pop();});
121 // Both normal move (from defined piece) and definition allowed
122 if (typeof x
== "string")
123 moves
= this.getDropMovesFrom([x
, y
]);
124 else if (this.getPiece(x
, y
) != 'u')
125 moves
= super.getPotentialMovesFrom([x
, y
]);
128 // We can only move the just-defined piece
129 if (x
== this.definition
.x
&& y
== this.definition
.y
)
130 moves
= super.getPotentialMovesFrom([x
, y
]);
137 if (this.movesCount
<= 1 || this.subTurn
== 0)
139 let filterLater
= [];
140 if (this.subTurn
== 1) {
141 // Remove defining moves with un-movable def piece,
142 // and separate compatible definitions.
143 moves
= moves
.filter(m
=> {
144 if (m
.vanish
.length
>= 2 || m
.vanish
[0].p
!= 'u')
147 const canMove
= super.filterValid(
148 super.getPotentialMovesFrom([m
.end
.x
, m
.end
.y
])).length
>= 1;
155 return super.filterValid(moves
).concat(filterLater
);
158 atLeastOneMove(color
) {
159 if (this.subTurn
!= 1)
161 return super.atLeastOneMove(color
);
164 underCheck(square_s
, oppCol
) {
165 if (super.underCheck(square_s
, oppCol
))
167 // Check potential specializations of undefined using reserve:
168 const allAttacks
= Array
.prototype.concat
.apply(
169 ['r', 'n', 'b', 'q'].map(p
=> this.pieces()[p
].moves
[0]));
170 const [x
, y
] = square_s
[0];
171 for (let i
=0; i
<this.size
.x
; i
++) {
172 for (let j
=0; j
<this.size
.y
; j
++) {
174 this.board
[i
][j
] != "" &&
175 this.getColor(i
, j
) == oppCol
&&
176 this.getPiece(i
, j
) == 'u'
178 for (let stepDef
of allAttacks
) {
179 for (let s
of stepDef
.steps
) {
180 if (!super.compatibleStep([i
, j
], [x
, y
], s
, stepDef
.range
))
183 super.findDestSquares(
186 captureTarget: [x
, y
],
187 captureSteps: [{steps: [s
], range: stepDef
.range
}],
205 const color
= this.turn
;
206 if (this.movesCount
<= 1 || move.reset
|| move.next
) {
208 this.tryChangeTurn();
211 if (this.subTurn
== 0)
212 this.captureUndef
= null; //already used
213 const captureUndef
= (
214 move.vanish
.length
== 2 && //exclude subTurn == 0
215 move.vanish
[1].c
!= color
&&
216 move.vanish
[1].p
== 'u'
218 if (typeof move.start
.x
== "number" && !captureUndef
)
219 // Normal move (including Teleport)
220 super.postPlay(move);
221 else if (typeof move.start
.x
== "string") {
223 color
, move.start
.y
, this.reserve
[color
][move.start
.y
] - 1);
224 if (move.vanish
.length
== 1 && move.vanish
[0].p
== 'u')
225 this.definition
= move.end
;
230 this.captureUndef
= move.end
;
231 this.tryChangeTurn(null, captureUndef
);
235 // NOTE: not "trying", the turn always change here (TODO?)
236 tryChangeTurn(move, captureUndef
) {
237 this.definition
= null;
238 this.subTurn
= captureUndef
? 0 : 1;
239 this.turn
= C
.GetOppCol(this.turn
);
243 computeNextMove(move) {
245 !this.definition
|| this.playerColor
!= this.turn
||
246 this.board
.some(row
=> row
.some(cell
=>
247 cell
.charAt(0) == this.turn
&& cell
.charAt(1) == 'u'))
251 const variety
= (c
) => {
254 Array
.prototype.concat
.apply([],
255 this.board
.map(row
=>
257 cell
.charAt(0) == c
&& !['p', 'k'].includes(cell
.charAt(1))
258 ).map(cell
=> cell
.charAt(1))
264 let next
= {start: move.end
, end: move.end
, vanish: [], appear: []};
265 this.playOnBoard(move);
266 const twoOrMorePieces
= {w: variety('w'), b: variety('b')};
268 Object
.keys(twoOrMorePieces
).filter(k
=> twoOrMorePieces
[k
]);
269 if (resetCols
.length
>= 1) {
270 for (let i
=0; i
<this.size
.x
; i
++) {
271 for (let j
=0; j
<this.size
.y
; j
++) {
272 const colIJ
= this.getColor(i
, j
);
273 const pieceIJ
= this.getPiece(i
, j
);
275 resetCols
.includes(colIJ
) &&
276 this.board
[i
][j
] != "" &&
277 !['p', 'k', 'u'].includes(pieceIJ
)
279 // NOTE: could also use a "flip" strategy similar to Benedict
280 next
.vanish
.push(new PiPo({c: colIJ
, p: pieceIJ
, x: i
, y: j
}));
281 next
.appear
.push(new PiPo({c: colIJ
, p: 'u', x: i
, y: j
}));
282 this.reserve
[colIJ
][pieceIJ
]++;
286 super.re_drawReserve(resetCols
);
288 this.undoOnBoard(move);
289 if (next
.vanish
.length
>= 1) {
296 return true; //called only on normal moves (not Teleport)
299 getCurrentScore(move_s
) {
300 return (this.movesCount
<= 2 ? "*" : super.getCurrentScore(move_s
));