603adedf188eec1b32e1bdd933b18cafef04aa23
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
]);
116 // Empty move: just start + end
117 moves
.forEach(m
=> {m
.vanish
.pop(); m
.appear
.pop();});
120 // Both normal move (from defined piece) and definition allowed
121 if (typeof x
== "string")
122 moves
= this.getDropMovesFrom([x
, y
]);
123 else if (this.getPiece(x
, y
) != 'u')
124 moves
= super.getPotentialMovesFrom([x
, y
]);
127 // We can only move the just-defined piece
128 if (x
== this.definition
.x
&& y
== this.definition
.y
)
129 moves
= super.getPotentialMovesFrom([x
, y
]);
136 if (this.movesCount
<= 1 || this.subTurn
== 0)
138 let filterLater
= [];
139 if (this.subTurn
== 1) {
140 // Remove defining moves with un-movable def piece,
141 // and separate compatible definitions.
142 moves
= moves
.filter(m
=> {
143 if (m
.vanish
.length
>= 2 || m
.vanish
[0].p
!= 'u')
146 const canMove
= super.filterValid(
147 super.getPotentialMovesFrom([m
.end
.x
, m
.end
.y
])).length
>= 1;
154 return super.filterValid(moves
).concat(filterLater
);
157 atLeastOneMove(color
) {
158 if (this.subTurn
!= 1)
160 return super.atLeastOneMove(color
);
163 underCheck(square_s
, oppCol
) {
164 if (super.underCheck(square_s
, oppCol
))
166 // Check potential specializations of undefined using reserve:
167 const allAttacks
= Array
.prototype.concat
.apply(
168 ['r', 'n', 'b', 'q'].map(p
=> this.pieces()[p
].moves
[0]));
169 const [x
, y
] = square_s
[0];
170 for (let i
=0; i
<this.size
.x
; i
++) {
171 for (let j
=0; j
<this.size
.y
; j
++) {
173 this.board
[i
][j
] != "" &&
174 this.getColor(i
, j
) == oppCol
&&
175 this.getPiece(i
, j
) == 'u'
177 for (let stepDef
of allAttacks
) {
178 for (let s
of stepDef
.steps
) {
179 if (!super.compatibleStep([i
, j
], [x
, y
], s
, stepDef
.range
))
182 super.findDestSquares(
185 captureTarget: [x
, y
],
186 captureSteps: [{steps: [s
], range: stepDef
.range
}],
204 const color
= this.turn
;
205 if (this.movesCount
<= 1 || move.reset
|| move.next
) {
207 this.tryChangeTurn();
210 if (this.subTurn
== 0)
211 this.captureUndef
= null; //already used
212 const captureUndef
= (
213 move.vanish
.length
== 2 && //exclude subTurn == 0
214 move.vanish
[1].c
!= color
&&
215 move.vanish
[1].p
== 'u'
217 if (typeof move.start
.x
== "number" && !captureUndef
)
218 // Normal move (including Teleport)
219 super.postPlay(move);
220 else if (typeof move.start
.x
== "string") {
222 color
, move.start
.y
, this.reserve
[color
][move.start
.y
] - 1);
223 if (move.vanish
.length
== 1 && move.vanish
[0].p
== 'u')
224 this.definition
= move.end
;
229 this.captureUndef
= move.end
;
230 this.tryChangeTurn(null, captureUndef
);
234 // NOTE: not "trying", the turn always change here (TODO?)
235 tryChangeTurn(move, captureUndef
) {
236 this.definition
= null;
237 this.subTurn
= captureUndef
? 0 : 1;
238 this.turn
= C
.GetOppCol(this.turn
);
242 computeNextMove(move) {
244 !this.definition
|| this.playerColor
!= this.turn
||
245 this.board
.some(row
=> row
.some(cell
=>
246 cell
.charAt(0) == this.turn
&& cell
.charAt(1) == 'u'))
250 const variety
= (c
) => {
253 Array
.prototype.concat
.apply([],
254 this.board
.map(row
=>
256 cell
.charAt(0) == c
&& !['p', 'k'].includes(cell
.charAt(1))
257 ).map(cell
=> cell
.charAt(1))
263 let next
= {start: move.end
, end: move.end
, vanish: [], appear: []};
264 this.playOnBoard(move);
265 const twoOrMorePieces
= {w: variety('w'), b: variety('b')};
267 Object
.keys(twoOrMorePieces
).filter(k
=> twoOrMorePieces
[k
]);
268 if (resetCols
.length
>= 1) {
269 for (let i
=0; i
<this.size
.x
; i
++) {
270 for (let j
=0; j
<this.size
.y
; j
++) {
271 const colIJ
= this.getColor(i
, j
);
272 const pieceIJ
= this.getPiece(i
, j
);
274 resetCols
.includes(colIJ
) &&
275 this.board
[i
][j
] != "" &&
276 !['p', 'k', 'u'].includes(pieceIJ
)
278 // NOTE: could also use a "flip" strategy similar to Benedict
279 next
.vanish
.push(new PiPo({c: colIJ
, p: pieceIJ
, x: i
, y: j
}));
280 next
.appear
.push(new PiPo({c: colIJ
, p: 'u', x: i
, y: j
}));
281 this.reserve
[colIJ
][pieceIJ
]++;
285 super.re_drawReserve(resetCols
);
287 this.undoOnBoard(move);
288 if (next
.vanish
.length
>= 1) {
295 return true; //called only on normal moves (not Teleport)
298 getCurrentScore(move_s
) {
299 return (this.movesCount
<= 2 ? "*" : super.getCurrentScore(move_s
));