const move = moveOrSquare;
const s = move.start,
e = move.end;
- // NOTE: next conditions are first for Atomic, and last for Checkered
+ // NOTE: next conditions are first for Crazyhouse, and last for Checkered
+ // TODO: Checkered exceptions are too weird and should move in its own file.
if (
- move.appear.length > 0 &&
+ move.vanish.length > 0 &&
Math.abs(s.x - e.x) == 2 &&
s.y == e.y &&
- move.appear[0].p == V.PAWN &&
- ["w", "b"].includes(move.appear[0].c)
+ move.vanish[0].p == V.PAWN &&
+ ["w", "b"].includes(move.vanish[0].c)
) {
return {
x: (s.x + e.x) / 2,
/////////////
// FEN UTILS
- // Setup the initial random (assymetric) position
- static GenRandInitFen() {
+ // Setup the initial random (asymmetric) position
+ static GenRandInitFen(randomness) {
+ if (randomness == 0)
+ // Deterministic:
+ return "rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w 0 1111 -";
+
let pieces = { w: new Array(8), b: new Array(8) };
- // Shuffle pieces on first and last rank
+ // Shuffle pieces on first (and last rank if randomness == 2)
for (let c of ["w", "b"]) {
+ if (c == 'b' && randomness == 1) {
+ pieces['b'] = pieces['w'];
+ break;
+ }
+
let positions = ArrayFun.range(8);
// Get random squares for bishops
// Return current fen (game state)
getFen() {
return (
- this.getBaseFen() +
- " " +
- this.getTurnFen() +
- " " +
+ this.getBaseFen() + " " +
+ this.getTurnFen() + " " +
this.movesCount +
(V.HasFlags ? " " + this.getFlagsFen() : "") +
(V.HasEnpassant ? " " + this.getEnpassantFen() : "")
);
}
+ getFenForRepeat() {
+ // Omit movesCount, only variable allowed to differ
+ return (
+ this.getBaseFen() + "_" +
+ this.getTurnFen() +
+ (V.HasFlags ? "_" + this.getFlagsFen() : "") +
+ (V.HasEnpassant ? "_" + this.getEnpassantFen() : "")
+ );
+ }
+
// Position part of the FEN string
getBaseFen() {
let position = "";
//////////////////
// INITIALIZATION
- constructor(fen) {
- // In printDiagram() fen isn't supply because only getPpath() is used
- if (fen)
- this.re_init(fen);
- }
-
// Fen string fully describes the game state
- re_init(fen) {
+ constructor(fen) {
+ if (!fen)
+ // In printDiagram() fen isn't supply because only getPpath() is used
+ // TODO: find a better solution!
+ return;
const fenParsed = V.ParseFen(fen);
this.board = V.GetBoard(fenParsed.position);
this.turn = fenParsed.turn[0]; //[0] to work with MarseilleRules
return 3;
}
- // NOTE: works also for extinction chess because depth is 3...
getComputerMove() {
const maxeval = V.INFINITY;
const color = this.turn;
// Some variants may show a bigger moves list to the human (Switching),
// thus the argument "computer" below (which is generally ignored)
- let moves1 = this.getAllValidMoves("computer");
+ let moves1 = this.getAllValidMoves();
if (moves1.length == 0)
// TODO: this situation should not happen
return null;
- // Can I mate in 1 ? (for Magnetic & Extinction)
- for (let i of shuffle(ArrayFun.range(moves1.length))) {
- this.play(moves1[i]);
- let finish = Math.abs(this.evalPosition()) >= V.THRESHOLD_MATE;
- if (!finish) {
- const score = this.getCurrentScore();
- if (["1-0", "0-1"].includes(score)) finish = true;
- }
- this.undo(moves1[i]);
- if (finish) return moves1[i];
- }
-
// Rank moves using a min-max at depth 2
for (let i = 0; i < moves1.length; i++) {
// Initial self evaluation is very low: "I'm checkmated"
// Initial enemy evaluation is very low too, for him
eval2 = (color == "w" ? 1 : -1) * maxeval;
// Second half-move:
- let moves2 = this.getAllValidMoves("computer");
+ let moves2 = this.getAllValidMoves();
for (let j = 0; j < moves2.length; j++) {
this.play(moves2[j]);
const score2 = this.getCurrentScore();
moves1.sort((a, b) => {
return (color == "w" ? 1 : -1) * (b.eval - a.eval);
});
+// console.log(moves1.map(m => { return [this.getNotation(m), m.eval]; }));
let candidates = [0]; //indices of candidates moves
for (let j = 1; j < moves1.length && moves1[j].eval == moves1[0].eval; j++)
if (score != "*")
return score == "1/2" ? 0 : (score == "1-0" ? 1 : -1) * maxeval;
if (depth == 0) return this.evalPosition();
- const moves = this.getAllValidMoves("computer");
+ const moves = this.getAllValidMoves();
let v = color == "w" ? -maxeval : maxeval;
if (color == "w") {
for (let i = 0; i < moves.length; i++) {