X-Git-Url: https://git.auder.net/assets/icon_infos.svg?a=blobdiff_plain;f=public%2Fjavascripts%2Fbase_rules.js;h=2a962a964c726181c2a480a86cdad7a969137cb4;hb=8ddc00a072c5a4aa679e5a420a7f9664d18e03f3;hp=51c9dda87966492acf10b645d90b539b85446a6a;hpb=0b7d99ecbb5dedc02cd96c457b5fc2962db9b297;p=vchess.git diff --git a/public/javascripts/base_rules.js b/public/javascripts/base_rules.js index 51c9dda8..2a962a96 100644 --- a/public/javascripts/base_rules.js +++ b/public/javascripts/base_rules.js @@ -50,16 +50,19 @@ class ChessRules ///////////////// // INITIALIZATION - // fen == "position flags" + // fen == "position [flags [turn]]" constructor(fen, moves) { this.moves = moves; - // Use fen string to initialize variables, flags and board - this.board = V.GetBoard(fen); - this.setFlags(fen); + // Use fen string to initialize variables, flags, turn and board + const fenParts = fen.split(" "); + this.board = V.GetBoard(fenParts[0]); + this.setFlags(fenParts[1]); //NOTE: fenParts[1] might be undefined + this.setTurn(fenParts[2]); //Same note this.initVariables(fen); } + // Some additional variables from FEN (variant dependant) initVariables(fen) { this.INIT_COL_KING = {'w':-1, 'b':-1}; @@ -95,29 +98,78 @@ class ChessRules this.INIT_COL_ROOK['w'][1] = k; break; default: - let num = parseInt(position[i].charAt(j)); + const num = parseInt(position[i].charAt(j)); if (!isNaN(num)) k += (num-1); } k++; } } - const epSq = (this.moves.length > 0 ? this.getEpSquare(this.lastMove) : undefined); - this.epSquares = [ epSq ]; + this.epSquares = [ this.getEpSquare(this.lastMove || fenParts[3]) ]; + } + + // Check if FEN describe a position + static IsGoodFen(fen) + { + const fenParts = fen.split(" "); + if (fenParts.length== 0) + return false; + // 1) Check position + const position = fenParts[0]; + const rows = position.split("/"); + if (rows.length != V.size.x) + return false; + for (let row of rows) + { + let sumElts = 0; + for (let i=0; i= 2) + { + if (!V.IsGoodFlags(fenParts[1])) + return false; + } + // 3) Check turn (if present) + if (fenParts.length >= 3) + { + if (!["w","b"].includes(fenParts[2])) + return false; + } + return true; + } + + // For FEN checking + static IsGoodFlags(flags) + { + return !!flags.match(/^[01]{4,4}$/); } // Turn diagram fen into double array ["wb","wp","bk",...] static GetBoard(fen) { - let rows = fen.split(" ")[0].split("/"); + const rows = fen.split(" ")[0].split("/"); let board = doubleArray(V.size.x, V.size.y, ""); for (let i=0; i0 ? this.moves[L-1] : null); } - get turn() { - return (this.moves.length%2==0 ? 'w' : 'b'); - } - // Pieces codes static get PAWN() { return 'p'; } static get ROOK() { return 'r'; } @@ -166,6 +221,11 @@ class ChessRules static get QUEEN() { return 'q'; } static get KING() { return 'k'; } + // For FEN checking: + static get PIECES() { + return [V.PAWN,V.ROOK,V.KNIGHT,V.BISHOP,V.QUEEN,V.KING]; + } + // Empty square static get EMPTY() { return ''; } @@ -190,8 +250,20 @@ class ChessRules } // En-passant square, if any - getEpSquare(move) + getEpSquare(moveOrSquare) { + if (typeof moveOrSquare === "string") + { + const square = moveOrSquare; + if (square == "-") + return undefined; + return { + x: square[0].charCodeAt()-97, + y: V.size.x-parseInt(square[1]) + }; + } + // Argument is a move: + const move = moveOrSquare; const [sx,sy,ex] = [move.start.x,move.start.y,move.end.x]; if (this.getPiece(sx,sy) == V.PAWN && Math.abs(sx - ex) == 2) { @@ -483,9 +555,7 @@ class ChessRules canIplay(side, [x,y]) { - return ((side=='w' && this.moves.length%2==0) - || (side=='b' && this.moves.length%2==1)) - && this.getColor(x,y) == side; + return (this.turn == side && this.getColor(x,y) == side); } getPossibleMovesFrom(sq) @@ -717,7 +787,7 @@ class ChessRules // Hash of position+flags+turn after a move is played (to detect repetitions) getHashState() { - return hex_md5(this.getFen() + " " + this.turn); + return hex_md5(this.getFen()); } play(move, ingame) @@ -733,6 +803,7 @@ class ChessRules this.updateVariables(move); this.moves.push(move); this.epSquares.push( this.getEpSquare(move) ); + this.turn = this.getOppCol(this.turn); V.PlayOnBoard(this.board, move); if (!!ingame) @@ -742,6 +813,7 @@ class ChessRules undo(move) { V.UndoOnBoard(this.board, move); + this.turn = this.getOppCol(this.turn); this.epSquares.pop(); this.moves.pop(); this.unupdateVariables(move); @@ -1048,13 +1120,13 @@ class ChessRules return pieces["b"].join("") + "/pppppppp/8/8/8/8/PPPPPPPP/" + pieces["w"].join("").toUpperCase() + - " 1111"; //add flags + " 1111 w"; //add flags + turn } // Return current fen according to pieces+colors state getFen() { - return this.getBaseFen() + " " + this.getFlagsFen(); + return this.getBaseFen() + " " + this.getFlagsFen() + " " + this.turn; } // Position part of the FEN string @@ -1150,14 +1222,11 @@ class ChessRules // The score is already computed when calling this function getPGN(mycolor, score, fenStart, mode) { - const zeroPad = x => { return (x<10 ? "0" : "") + x; }; let pgn = ""; pgn += '[Site "vchess.club"]
'; - const d = new Date(); const opponent = mode=="human" ? "Anonymous" : "Computer"; pgn += '[Variant "' + variant + '"]
'; - pgn += '[Date "' + d.getFullYear() + '-' + (d.getMonth()+1) + - '-' + zeroPad(d.getDate()) + '"]
'; + pgn += '[Date "' + getDate(new Date()) + '"]
'; pgn += '[White "' + (mycolor=='w'?'Myself':opponent) + '"]
'; pgn += '[Black "' + (mycolor=='b'?'Myself':opponent) + '"]
'; pgn += '[FenStart "' + fenStart + '"]
';