import { randInt } from "@/utils/alea";
export class ApocalypseRules extends ChessRules {
+
static get PawnSpecs() {
return Object.assign(
{},
);
}
+ static get SomeHiddenMoves() {
+ return true;
+ }
+
static get HasCastle() {
return false;
}
if (['P','p'].includes(row[i])) pawns[row[i]]++;
if (V.PIECES.includes(row[i].toLowerCase())) sumElts++;
else {
- const num = parseInt(row[i]);
+ const num = parseInt(row[i], 10);
if (isNaN(num)) return false;
sumElts += num;
}
// 4) Check whiteMove
if (
(
- fenParsed.turn == "w" &&
+ fenParsed.turn == "b" &&
// NOTE: do not check really JSON stringified move...
(!fenParsed.whiteMove || fenParsed.whiteMove == "-")
)
||
- (fenParsed.turn == "b" && fenParsed.whiteMove != "-")
+ (fenParsed.turn == "w" && fenParsed.whiteMove != "-")
) {
return false;
}
setFlags(fenflags) {
this.penaltyFlags = {
- 'w': parseInt(fenflags[0]),
- 'b': parseInt(fenflags[1])
+ 'w': parseInt(fenflags[0], 10),
+ 'b': parseInt(fenflags[1], 10)
};
}
start: this.whiteMove.start,
end: this.whiteMove.end,
appear: this.whiteMove.appear,
- vanish: this.whiteMove.vanish,
- illegal: this.whiteMove.illegal
+ vanish: this.whiteMove.vanish
});
}
const mHash = "m" + vm.start.x + vm.start.y + vm.end.x + vm.end.y;
if (!moveSet[mHash]) {
moveSet[mHash] = true;
- vm.illegal = true; //potentially illegal!
+ vm.end.illegal = true; //potentially illegal!
speculations.push(vm);
}
});
return (
(
m.vanish[0].p == V.KNIGHT &&
- (m.vanish.length == 1 || m.vanish[1].c != m.vanish[0].c)
- )
- ||
- (
- // Promotion attempt
- m.end.x == (m.vanish[0].c == "w" ? 0 : V.size.x - 1) &&
- other.vanish.length == 2 &&
- other.vanish[1].p == V.KNIGHT &&
- other.vanish[1].c == m.vanish[0].c
- )
- ||
- (
- // Moving attempt
- !movingLikeCapture(m) &&
- other.start.x == m.end.x &&
- other.start.y == m.end.y
+ (
+ m.vanish.length == 1 ||
+ m.vanish[1].c != m.vanish[0].c ||
+ // Self-capture attempt
+ (
+ !other.end.illegal &&
+ other.end.x == m.end.x &&
+ other.end.y == m.end.y
+ )
+ )
)
||
(
- // Capture attempt
- movingLikeCapture(m) &&
- other.end.x == m.end.x &&
- other.end.y == m.end.y
+ m.vanish[0].p == V.PAWN &&
+ !other.end.illegal &&
+ (
+ (
+ // Promotion attempt
+ m.end.x == (m.vanish[0].c == "w" ? 0 : V.size.x - 1) &&
+ other.vanish.length == 2 &&
+ other.vanish[1].p == V.KNIGHT &&
+ other.vanish[1].c == m.vanish[0].c
+ )
+ ||
+ (
+ // Moving attempt
+ !movingLikeCapture(m) &&
+ other.start.x == m.end.x &&
+ other.start.y == m.end.y
+ )
+ ||
+ (
+ // Capture attempt
+ movingLikeCapture(m) &&
+ other.end.x == m.end.x &&
+ other.end.y == m.end.y
+ )
+ )
)
);
};
- if (!!m1.illegal && !isPossible(m1, m2)) {
+ if (!!m1.end.illegal && !isPossible(m1, m2)) {
// Either an anticipated capture of something which didn't move
// (or not to the right square), or a push through blocus.
// ==> Just discard the move, and add a penalty point
this.penaltyFlags[m1.vanish[0].c]++;
m1.isNull = true;
}
- if (!!m2.illegal && !isPossible(m2, m1)) {
+ if (!!m2.end.illegal && !isPossible(m2, m1)) {
this.penaltyFlags[m2.vanish[0].c]++;
m2.isNull = true;
}
vanish: []
};
if (!m1 && !m2) return smove;
- // Both move are now legal:
+ // Both moves are now legal or at least possible:
smove.vanish.push(m1.vanish[0]);
smove.vanish.push(m2.vanish[0]);
if ((m1.end.x != m2.end.x) || (m1.end.y != m2.end.y)) {
let remain = null;
const p1 = m1.vanish[0].p;
const p2 = m2.vanish[0].p;
- if (!!m1.illegal && !m2.illegal) remain = { c: 'w', p: p1 };
- else if (!!m2.illegal && !m1.illegal) remain = { c: 'b', p: p2 };
+ if (!!m1.end.illegal && !m2.end.illegal) remain = { c: 'w', p: p1 };
+ else if (!!m2.end.illegal && !m1.end.illegal) remain = { c: 'b', p: p2 };
if (!remain) {
// Either both are illegal or both are legal
if (p1 == V.KNIGHT && p2 == V.PAWN) remain = { c: 'w', p: p1 };
}
play(move) {
- if (!this.states) this.states = [];
- const stateFen = this.getFen();
- this.states.push(stateFen);
-
// Do not play on board (would reveal the move...)
move.flags = JSON.stringify(this.aggregateFlags());
this.turn = V.GetOppCol(this.turn);
this.turn = V.GetOppCol(this.turn);
this.movesCount--;
this.postUndo(move);
-
- const stateFen = this.getFen();
- if (stateFen != this.states[this.states.length-1]) debugger;
- this.states.pop();
}
postUndo(move) {
else this.whiteMove = move.whiteMove;
}
- getCheckSquares(color) {
+ getCheckSquares() {
return [];
}
// TODO: this situation should not happen
return null;
- if (Math.random() < 0.5)
- // Return a random move
- return moves[randInt(moves.length)];
-
// Rank moves at depth 1:
- // try to capture something (not re-capturing)
+ let validMoves = [];
+ let illegalMoves = [];
moves.forEach(m => {
- V.PlayOnBoard(this.board, m);
- m.eval = this.evalPosition();
- V.UndoOnBoard(this.board, m);
+ // Warning: m might be illegal!
+ if (!m.end.illegal) {
+ V.PlayOnBoard(this.board, m);
+ m.eval = this.evalPosition();
+ V.UndoOnBoard(this.board, m);
+ validMoves.push(m);
+ } else illegalMoves.push(m);
});
- moves.sort((a, b) => {
+
+ const illegalRatio = illegalMoves.length / moves.length;
+ if (Math.random() < illegalRatio)
+ // Return a random illegal move
+ return illegalMoves[randInt(illegalMoves.length)];
+
+ validMoves.sort((a, b) => {
return (color == "w" ? 1 : -1) * (b.eval - a.eval);
});
let candidates = [0];
- for (let i = 1; i < moves.length && moves[i].eval == moves[0].eval; i++)
+ for (
+ let i = 1;
+ i < validMoves.length && validMoves[i].eval == moves[0].eval;
+ i++
+ ) {
candidates.push(i);
- return moves[candidates[randInt(candidates.length)]];
+ }
+ return validMoves[candidates[randInt(candidates.length)]];
}
getNotation(move) {
// Basic system: piece + init + dest square
return (
- move.vanish[0].p.toUpperCase() +
+ (move.vanish[0].p == V.KNIGHT ? "N" : "") +
V.CoordsToSquare(move.start) +
V.CoordsToSquare(move.end)
);
}
+
};