if (!V.IsGoodPosition(fenParsed.position))
return false;
// 2) Check turn
- if (!fenParsed.turn || !["w","b"].includes(fenParsed.turn))
+ if (!fenParsed.turn || !V.IsGoodTurn(fenParsed.turn))
return false;
// 3) Check flags
if (V.HasFlags && (!fenParsed.flags || !V.IsGoodFlags(fenParsed.flags)))
return false;
// 4) Check enpassant
- if (V.HasEnpassant)
+ if (V.HasEnpassant &&
+ (!fenParsed.enpassant || !V.IsGoodEnpassant(fenParsed.enpassant)))
{
- if (!fenParsed.enpassant)
- return false;
- if (fenParsed.enpassant != "-")
- {
- const ep = V.SquareToCoords(fenParsed.enpassant);
- if (isNaN(ep.x) || !V.OnBoard(ep))
- return false;
- }
+ return false;
}
return true;
}
return true;
}
+ // For FEN checking
+ static IsGoodTurn(turn)
+ {
+ return ["w","b"].includes(turn);
+ }
+
// For FEN checking
static IsGoodFlags(flags)
{
return !!flags.match(/^[01]{4,4}$/);
}
+ static IsGoodEnpassant(enpassant)
+ {
+ if (enpassant != "-")
+ {
+ const ep = V.SquareToCoords(fenParsed.enpassant);
+ if (isNaN(ep.x) || !V.OnBoard(ep))
+ return false;
+ }
+ return true;
+ }
+
// 3 --> d (column number to letter)
static CoordToColumn(colnum)
{
}
// d --> 3 (column letter to number)
- static ColumnToCoord(colnum)
+ static ColumnToCoord(column)
{
- return String.fromCharCode(97 + colnum);
+ return column.charCodeAt(0) - 97;
}
// a4 --> {x:3,y:0}
// Return current fen (game state)
getFen()
{
- return this.getBaseFen() + " " + this.turn +
+ return this.getBaseFen() + " " + this.getTurnFen() +
(V.HasFlags ? (" " + this.getFlagsFen()) : "") +
(V.HasEnpassant ? (" " + this.getEnpassantFen()) : "");
}
return position;
}
+ getTurnFen()
+ {
+ return this.turn;
+ }
+
// Flags part of the FEN string
getFlagsFen()
{
this.moves = moves;
const fenParsed = V.ParseFen(fen);
this.board = V.GetBoard(fenParsed.position);
- this.turn = (fenParsed.turn || "w");
+ this.turn = fenParsed.turn[0]; //[0] to work with MarseilleRules
this.setOtherVariables(fen);
}
const lastRank = (color == "w" ? 0 : sizeX-1);
const pawnColor = this.getColor(x,y); //can be different for checkered
- if (x+shiftX >= 0 && x+shiftX < sizeX) //TODO: always true
+ // NOTE: next condition is generally true (no pawn on last rank)
+ if (x+shiftX >= 0 && x+shiftX < sizeX)
{
const finalPieces = x + shiftX == lastRank
? [V.ROOK,V.KNIGHT,V.BISHOP,V.QUEEN]
board[psq.x][psq.y] = psq.c + psq.p;
}
- // Before move is played, update variables + flags
+ // After move is played, update variables + flags
updateVariables(move)
{
- const piece = move.vanish[0].p;
- const c = move.vanish[0].c;
+ let piece = undefined;
+ let c = undefined;
+ if (move.vanish.length >= 1)
+ {
+ // Usual case, something is moved
+ piece = move.vanish[0].p;
+ c = move.vanish[0].c;
+ }
+ else
+ {
+ // Crazyhouse-like variants
+ piece = move.appear[0].p;
+ c = move.appear[0].c;
+ }
+ if (c == "c") //if (!["w","b"].includes(c))
+ {
+ // 'c = move.vanish[0].c' doesn't work for Checkered
+ c = this.getOppCol(this.turn);
+ }
const firstRank = (c == "w" ? V.size.x-1 : 0);
// Update king position + flags
{
this.kingPos[c][0] = move.appear[0].x;
this.kingPos[c][1] = move.appear[0].y;
- this.castleFlags[c] = [false,false];
+ if (V.HasFlags)
+ this.castleFlags[c] = [false,false];
return;
}
- const oppCol = this.getOppCol(c);
- const oppFirstRank = (V.size.x-1) - firstRank;
- if (move.start.x == firstRank //our rook moves?
- && this.INIT_COL_ROOK[c].includes(move.start.y))
- {
- const flagIdx = (move.start.y == this.INIT_COL_ROOK[c][0] ? 0 : 1);
- this.castleFlags[c][flagIdx] = false;
- }
- else if (move.end.x == oppFirstRank //we took opponent rook?
- && this.INIT_COL_ROOK[oppCol].includes(move.end.y))
+ if (V.HasFlags)
{
- const flagIdx = (move.end.y == this.INIT_COL_ROOK[oppCol][0] ? 0 : 1);
- this.castleFlags[oppCol][flagIdx] = false;
+ // Update castling flags if rooks are moved
+ const oppCol = this.getOppCol(c);
+ const oppFirstRank = (V.size.x-1) - firstRank;
+ if (move.start.x == firstRank //our rook moves?
+ && this.INIT_COL_ROOK[c].includes(move.start.y))
+ {
+ const flagIdx = (move.start.y == this.INIT_COL_ROOK[c][0] ? 0 : 1);
+ this.castleFlags[c][flagIdx] = false;
+ }
+ else if (move.end.x == oppFirstRank //we took opponent rook?
+ && this.INIT_COL_ROOK[oppCol].includes(move.end.y))
+ {
+ const flagIdx = (move.end.y == this.INIT_COL_ROOK[oppCol][0] ? 0 : 1);
+ this.castleFlags[oppCol][flagIdx] = false;
+ }
}
}
if (!this.isAttacked(this.kingPos[color], [this.getOppCol(color)]))
return "1/2";
// OK, checkmate
- return color == "w" ? "0-1" : "1-0";
+ return (color == "w" ? "0-1" : "1-0");
}
///////////////
}
else
return currentBest;
- //console.log(moves1.map(m => { return [this.getNotation(m), m.eval]; }));
+// console.log(moves1.map(m => { return [this.getNotation(m), m.eval]; }));
candidates = [0];
for (let j=1; j<moves1.length && moves1[j].eval == moves1[0].eval; j++)