import {Random} from "/utils/alea.js";
import {ArrayFun} from "/utils/array.js";
+import {FenUtil} from "/utils/setupPieces.js";
import PiPo from "/utils/PiPo.js";
import Move from "/utils/Move.js";
// Setup the initial random-or-not (asymmetric-or-not) position
genRandInitBaseFen() {
- let fen, flags = "0707";
- if (!this.options.randomness)
- // Deterministic:
- fen = "rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR";
-
- else {
- // Randomize
- let pieces = {w: new Array(8), b: new Array(8)};
- flags = "";
- // Shuffle pieces on first (and last rank if randomness == 2)
- for (let c of ["w", "b"]) {
- if (c == 'b' && this.options.randomness == 1) {
- pieces['b'] = pieces['w'];
- flags += flags;
- break;
- }
- let positions = ArrayFun.range(8);
- // Get random squares for bishops
- let randIndex = 2 * Random.randInt(4);
- const bishop1Pos = positions[randIndex];
- // The second bishop must be on a square of different color
- let randIndex_tmp = 2 * Random.randInt(4) + 1;
- const bishop2Pos = positions[randIndex_tmp];
- // Remove chosen squares
- positions.splice(Math.max(randIndex, randIndex_tmp), 1);
- positions.splice(Math.min(randIndex, randIndex_tmp), 1);
- // Get random squares for knights
- randIndex = Random.randInt(6);
- const knight1Pos = positions[randIndex];
- positions.splice(randIndex, 1);
- randIndex = Random.randInt(5);
- const knight2Pos = positions[randIndex];
- positions.splice(randIndex, 1);
- // Get random square for queen
- randIndex = Random.randInt(4);
- const queenPos = positions[randIndex];
- positions.splice(randIndex, 1);
- // Rooks and king positions are now fixed,
- // because of the ordering rook-king-rook
- const rook1Pos = positions[0];
- const kingPos = positions[1];
- const rook2Pos = positions[2];
- // Finally put the shuffled pieces in the board array
- pieces[c][rook1Pos] = "r";
- pieces[c][knight1Pos] = "n";
- pieces[c][bishop1Pos] = "b";
- pieces[c][queenPos] = "q";
- pieces[c][kingPos] = "k";
- pieces[c][bishop2Pos] = "b";
- pieces[c][knight2Pos] = "n";
- pieces[c][rook2Pos] = "r";
- flags += rook1Pos.toString() + rook2Pos.toString();
+ const s = FenUtil.setupPieces(
+ ['r', 'n', 'b', 'q', 'k', 'b', 'n', 'r'],
+ {
+ between: {p1: 'k', p2: 'r'},
+ diffCol: ['b'],
+ flags: ['r']
}
- fen = (
- pieces["b"].join("") +
- "/pppppppp/8/8/8/8/PPPPPPPP/" +
- pieces["w"].join("").toUpperCase()
- );
- }
- return { fen: fen, o: {flags: flags} };
+ );
+ return {
+ fen: s.b.join("") + "/pppppppp/8/8/8/8/PPPPPPPP/" +
+ s.w.join("").toUpperCase(),
+ o: {flags: s.flags}
+ };
}
// "Parse" FEN: just return untransformed string data
if (this.options[opt.variable] === undefined)
this.options[opt.variable] = opt.defaut;
});
- if (o.genFenOnly)
- // This object will be used only for initial FEN generation
- return;
// Some variables
this.playerColor = o.color;
// TODO: onpointerdown/move/up ? See reveal.js /controllers/touch.js
}
+ // NOTE: not called if isDiagram
removeListeners() {
let container = document.getElementById(this.containerId);
this.windowResizeObs.unobserve(container);
- if (this.isDiagram)
- return; //no listeners in this case
if ('onmousedown' in window) {
this.mouseListeners.forEach(ml => {
document.removeEventListener(ml.type, ml.listener);
},
'r': {
"class": "rook",
- moves: [
+ both: [
{steps: [[0, 1], [0, -1], [1, 0], [-1, 0]]}
]
},
'n': {
"class": "knight",
- moves: [
+ both: [
{
steps: [
[1, 2], [1, -2], [-1, 2], [-1, -2],
},
'b': {
"class": "bishop",
- moves: [
+ both: [
{steps: [[1, 1], [1, -1], [-1, 1], [-1, -1]]}
]
},
'q': {
"class": "queen",
- moves: [
+ both: [
{
steps: [
[0, 1], [0, -1], [1, 0], [-1, 0],
},
'k': {
"class": "king",
- moves: [
+ both: [
{
steps: [
[0, 1], [0, -1], [1, 0], [-1, 0],
}
getStepSpec(color, x, y, piece) {
- return this.pieces(color, x, y)[piece || this.getPieceType(x, y)];
+ let pieceType = piece;
+ let allSpecs = this.pieces(color, x, y);
+ if (!piece)
+ pieceType = this.getPieceType(x, y);
+ else if (allSpecs[piece].moveas)
+ pieceType = allSpecs[piece].moveas;
+ let res = allSpecs[pieceType];
+ if (!res["both"])
+ res.both = [];
+ if (!res["moves"])
+ res.moves = [];
+ if (!res["attack"])
+ res.attack = [];
+ return res;
}
// Can thing on square1 capture thing on square2?
const oppCol = C.GetOppCol(color);
const piece = this.getPieceType(x, y);
const stepSpec = this.getStepSpec(color, x, y, piece);
- const attacks = stepSpec.attack || stepSpec.moves;
+ const attacks = stepSpec.both.concat(stepSpec.attack);
for (let a of attacks) {
outerLoop: for (let step of a.steps) {
let [i, j] = [x + step[0], y + step[1]];
elt.segments = this.getSegments(segments, segStart, end);
res.push(elt);
};
- const exploreSteps = (stepArray) => {
+ const exploreSteps = (stepArray, mode) => {
for (let s of stepArray) {
outerLoop: for (let step of s.steps) {
if (o.segments) {
!o.captureTarget ||
(o.captureTarget[0] == i && o.captureTarget[1] == j)
) {
- if (o.one && !o.attackOnly)
+ if (o.one && mode != "attack")
return true;
- if (!o.attackOnly)
+ if (mode != "attack")
addSquare(!o.captureTarget ? [i, j] : [x, y]);
if (o.captureTarget)
return res[0];
if (!explored[i + "." + j]) {
explored[i + "." + j] = true;
if (allowed([x, y], [i, j])) {
- if (o.one && !o.moveOnly)
+ if (o.one && mode != "moves")
return true;
- if (!o.moveOnly)
+ if (mode != "moves")
addSquare(!o.captureTarget ? [i, j] : [x, y]);
if (
o.captureTarget &&
return undefined; //default, but let's explicit it
};
if (o.captureTarget)
- return exploreSteps(o.captureSteps)
+ return exploreSteps(o.captureSteps, "attack");
else {
const stepSpec =
o.stepSpec || this.getStepSpec(this.getColor(x, y), x, y);
let outOne = false;
- if (!o.attackOnly || !stepSpec.attack)
- outOne = exploreSteps(stepSpec.moves);
- if (!outOne && !o.moveOnly && !!stepSpec.attack) {
- o.attackOnly = true; //ok because o is always a temporary object
- outOne = exploreSteps(stepSpec.attack);
- }
+ if (!o.attackOnly)
+ outOne = exploreSteps(stepSpec.both.concat(stepSpec.moves), "moves");
+ if (!outOne && !o.moveOnly)
+ outOne = exploreSteps(stepSpec.both.concat(stepSpec.attack), "attack");
return (o.one ? outOne : res);
}
}
if (this.canStepOver(x, y, apparentPiece))
continue;
const stepSpec = this.getStepSpec(colIJ, i, j);
- const attacks = stepSpec.attack || stepSpec.moves;
+ const attacks = stepSpec.attack.concat(stepSpec.both);
for (let a of attacks) {
for (let s of a.steps) {
// Quick check: if step isn't compatible, don't even try
// will be executed in filterValid() later.
(
i != finalSquares[castleSide][0] &&
- this.underCheck([x, i], oppCol)
+ this.underCheck([[x, i]], oppCol)
)
||
(
underCheck(square_s, oppCol) {
if (this.options["taking"] || this.options["dark"])
return false;
- if (!Array.isArray(square_s[0]))
- square_s = [square_s];
return square_s.some(sq => this.underAttack(sq, oppCol));
}
}
postPlay(move) {
- const color = this.turn;
if (this.options["dark"])
this.updateEnlightened();
if (this.options["teleport"]) {
if (
this.subTurnTeleport == 1 &&
move.vanish.length > move.appear.length &&
- move.vanish[1].c == color
+ move.vanish[1].c == this.turn
) {
const v = move.vanish[move.vanish.length - 1];
this.captured = {x: v.x, y: v.y, c: v.c, p: v.p};
tryChangeTurn(move) {
if (this.isLastMove(move)) {
- this.turn = C.GetOppCol(color);
+ this.turn = C.GetOppCol(this.turn);
this.movesCount++;
this.subTurn = 1;
}
let container = document.getElementById(this.containerId);
if (document.hidden) {
document.onvisibilitychange = () => {
+ // TODO here: page reload ?! (some issues if tab changed...)
document.onvisibilitychange = undefined;
checkDisplayThenAnimate(700);
};