-import { Random } from "/utils/alea.js";
-import { ArrayFun } from "/utils/array.js";
+import {Random} from "/utils/alea.js";
+import {ArrayFun} from "/utils/array.js";
import PiPo from "/utils/PiPo.js";
import Move from "/utils/Move.js";
baseFen.o = Object.assign({init: true}, baseFen.o);
const parts = this.getPartFen(baseFen.o);
return (
- baseFen.fen +
+ baseFen.fen + " w 0" +
(Object.keys(parts).length > 0 ? (" " + JSON.stringify(parts)) : "")
);
}
let fen, flags = "0707";
if (!this.options.randomness)
// Deterministic:
- fen = "rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w 0";
+ fen = "rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR";
else {
// Randomize
fen = (
pieces["b"].join("") +
"/pppppppp/8/8/8/8/PPPPPPPP/" +
- pieces["w"].join("").toUpperCase() +
- " w 0"
+ pieces["w"].join("").toUpperCase()
);
}
return { fen: fen, o: {flags: flags} };
}
// ordering as in pieces() p,r,n,b,q,k
- initReserves(reserveStr) {
+ initReserves(reserveStr, pieceArray) {
+ if (!pieceArray)
+ pieceArray = ['p', 'r', 'n', 'b', 'q', 'k'];
const counts = reserveStr.split("").map(c => parseInt(c, 36));
- this.reserve = { w: {}, b: {} };
- const pieceName = ['p', 'r', 'n', 'b', 'q', 'k'];
- const L = pieceName.length;
- for (let i of ArrayFun.range(2 * L)) {
- if (i < L)
- this.reserve['w'][pieceName[i]] = counts[i];
- else
- this.reserve['b'][pieceName[i-L]] = counts[i];
- }
+ const L = pieceArray.length;
+ this.reserve = {
+ w: ArrayFun.toObject(pieceArray, counts.slice(0, L)),
+ b: ArrayFun.toObject(pieceArray, counts.slice(L, 2 * L))
+ };
}
initIspawn(ispawnStr) {
(oldV,newV) => oldV + (this.reserve[c][newV] > 0 ? 1 : 0), 0);
}
- static AddClass_es(piece, class_es) {
+ static AddClass_es(elt, class_es) {
if (!Array.isArray(class_es))
class_es = [class_es];
- class_es.forEach(cl => {
- piece.classList.add(cl);
- });
+ class_es.forEach(cl => elt.classList.add(cl));
}
- static RemoveClass_es(piece, class_es) {
+ static RemoveClass_es(elt, class_es) {
if (!Array.isArray(class_es))
class_es = [class_es];
- class_es.forEach(cl => {
- piece.classList.remove(cl);
- });
+ class_es.forEach(cl => elt.classList.remove(cl));
}
// Generally light square bottom-right
class="chessboard_SVG">`;
for (let i=0; i < this.size.x; i++) {
for (let j=0; j < this.size.y; j++) {
+ if (!this.onBoard(i, j))
+ continue;
const ii = (flipped ? this.size.x - 1 - i : i);
const jj = (flipped ? this.size.y - 1 - j : j);
let classes = this.getSquareColorClass(ii, jj);
piece = "k"; //capturing cannibal king: back to king form
const oldCount = this.reserve[color][piece];
this.reserve[color][piece] = count;
- // Redrawing is much easier if count==0
- if ([oldCount, count].includes(0))
+ // Redrawing is much easier if count==0 (or undefined)
+ if ([oldCount, count].some(item => !item))
this.re_drawReserve([color]);
else {
const numId = this.getReserveNumId(color, piece);
let moves = [];
for (let i=0; i<this.size.x; i++) {
for (let j=0; j<this.size.y; j++) {
- if (this.canDrop([c, p], [i, j])) {
+ if (this.onBoard(i, j) && this.canDrop([c, p], [i, j])) {
let mv = new Move({
start: {x: c, y: p},
end: {x: i, y: j},
this.subTurnTeleport = 1;
this.captured = null;
}
+ this.tryChangeTurn(move);
+ }
+
+ tryChangeTurn(move) {
if (this.isLastMove(move)) {
this.turn = C.GetOppCol(color);
this.movesCount++;
}
// What is the score ? (Interesting if game is over)
- getCurrentScore(move) {
+ getCurrentScore(move_s) {
+ const move = move_s[move_s.length - 1];
+ // Shortcut in case the score was computed before:
+ if (move.result)
+ return move.result;
const color = this.turn;
const oppCol = C.GetOppCol(color);
const kingPos = {
buildMoveStack(move, r) {
this.moveStack.push(move);
this.computeNextMove(move);
- this.play(move);
- const newTurn = this.turn;
- if (this.moveStack.length == 1 && !this.hideMoves)
- this.playVisual(move, r);
- if (move.next) {
- this.gameState = {
- fen: this.getFen(),
- board: JSON.parse(JSON.stringify(this.board)) //easier
- };
- this.buildMoveStack(move.next, r);
- }
- else {
- if (this.moveStack.length == 1) {
- // Usual case (one normal move)
- this.afterPlay(this.moveStack, newTurn, {send: true, res: true});
- this.moveStack = []
+ const then = () => {
+ const newTurn = this.turn;
+ if (this.moveStack.length == 1 && !this.hideMoves)
+ this.playVisual(move, r);
+ if (move.next) {
+ this.gameState = {
+ fen: this.getFen(),
+ board: JSON.parse(JSON.stringify(this.board)) //easier
+ };
+ this.buildMoveStack(move.next, r);
}
else {
- this.afterPlay(this.moveStack, newTurn, {send: true, res: false});
- this.re_initFromFen(this.gameState.fen, this.gameState.board);
- this.playReceivedMove(this.moveStack.slice(1), () => {
- this.afterPlay(this.moveStack, newTurn, {send: false, res: true});
- this.moveStack = []
- });
+ if (this.moveStack.length == 1) {
+ // Usual case (one normal move)
+ this.afterPlay(this.moveStack, newTurn, {send: true, res: true});
+ this.moveStack = [];
+ }
+ else {
+ this.afterPlay(this.moveStack, newTurn, {send: true, res: false});
+ this.re_initFromFen(this.gameState.fen, this.gameState.board);
+ this.playReceivedMove(this.moveStack.slice(1), () => {
+ this.afterPlay(this.moveStack, newTurn, {send: false, res: true});
+ this.moveStack = [];
+ });
+ }
}
- }
+ };
+ // If hiding moves, then they are revealed in play() with callback
+ this.play(move, this.hideMoves ? then : null);
+ if (!this.hideMoves)
+ then();
}
// Implemented in variants using (automatic) moveStack
launchAnimation(moves, container, callback) {
if (this.hideMoves) {
- moves.forEach(m => this.play(m));
- callback();
+ for (let i=0; i<moves.length; i++)
+ // If hiding moves, they are revealed into play():
+ this.play(moves[i], i == moves.length - 1 ? callback : () => {});
return;
}
const r = container.querySelector(".chessboard").getBoundingClientRect();