X-Git-Url: https://git.auder.net/?a=blobdiff_plain;f=public%2Fjavascripts%2Fbase_rules.js;h=860495a4236c3109bf77874172f353b7b878be2b;hb=098e8468ae7a52a55850c09f90506f52b8133567;hp=6bc3591cfc601c3604a4f7c7f7f0619db8c5b553;hpb=8a60cacd26d8c47f52ecac26091d6a6f65e6bbc5;p=vchess.git diff --git a/public/javascripts/base_rules.js b/public/javascripts/base_rules.js index 6bc3591c..860495a4 100644 --- a/public/javascripts/base_rules.js +++ b/public/javascripts/base_rules.js @@ -10,6 +10,7 @@ class PiPo //Piece+Position } } +// TODO: for animation, moves should contains "moving" and "fading" maybe... class Move { // o: {appear, vanish, [start,] [end,]} @@ -124,7 +125,7 @@ class ChessRules return board; } - // Overridable: flags can change a lot + // Extract (relevant) flags from fen setFlags(fen) { // white a-castle, h-castle, black a-castle, h-castle @@ -137,7 +138,6 @@ class ChessRules /////////////////// // GETTERS, SETTERS - // Simple useful getters static get size() { return [8,8]; } // Two next functions return 'undefined' if called on empty square getColor(i,j) { return this.board[i][j].charAt(0); } @@ -199,7 +199,7 @@ class ChessRules return undefined; //default } - // can thing on square1 take thing on square2 + // Can thing on square1 take thing on square2 canTake([x1,y1], [x2,y2]) { return this.getColor(x1,y1) != this.getColor(x2,y2); @@ -291,7 +291,7 @@ class ChessRules return moves; } - // What are the pawn moves from square x,y considering color "color" ? + // What are the pawn moves from square x,y ? getPotentialPawnMoves([x,y]) { const color = this.turn; @@ -332,21 +332,22 @@ class ChessRules if (x+shift == lastRank) { // Promotion + const pawnColor = this.getColor(x,y); //can be different for checkered let promotionPieces = [V.ROOK,V.KNIGHT,V.BISHOP,V.QUEEN]; promotionPieces.forEach(p => { // Normal move if (this.board[x+shift][y] == V.EMPTY) - moves.push(this.getBasicMove([x,y], [x+shift,y], {c:color,p:p})); + moves.push(this.getBasicMove([x,y], [x+shift,y], {c:pawnColor,p:p})); // Captures if (y>0 && this.canTake([x,y], [x+shift,y-1]) && this.board[x+shift][y-1] != V.EMPTY) { - moves.push(this.getBasicMove([x,y], [x+shift,y-1], {c:color,p:p})); + moves.push(this.getBasicMove([x,y], [x+shift,y-1], {c:pawnColor,p:p})); } if (y= 8) { - // NOTE: crude detection, only moves repetition const L = this.moves.length; if (_.isEqual(this.moves[L-1], this.moves[L-5]) && _.isEqual(this.moves[L-2], this.moves[L-6]) && @@ -773,6 +763,7 @@ class ChessRules return false; } + // Is game over ? And if yes, what is the score ? checkGameOver() { if (this.checkRepetition()) @@ -831,7 +822,9 @@ class ChessRules this.shouldReturn = false; const maxeval = VariantRules.INFINITY; const color = this.turn; - let moves1 = this.getAllValidMoves(); + // 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"); // Can I mate in 1 ? (for Magnetic & Extinction) for (let i of _.shuffle(_.range(moves1.length))) @@ -847,27 +840,41 @@ class ChessRules for (let i=0; i eval2)) + eval2 = evalPos; + this.undo(moves2[j]); + } + } + else { - this.play(moves2[j]); - let evalPos = this.evalPosition(); - if ((color == "w" && evalPos < eval2) || (color=="b" && evalPos > eval2)) - eval2 = evalPos; - this.undo(moves2[j]); + const score = this.checkGameEnd(); + eval2 = (score=="1/2" ? 0 : (score=="1-0" ? 1 : -1) * maxeval); } if ((color=="w" && eval2 > moves1[i].eval) || (color=="b" && eval2 < moves1[i].eval)) moves1[i].eval = eval2; this.undo(moves1[i]); } 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 { return [this.getNotation(m), m.eval]; })); candidates = [0]; for (let j=1; j { return [this.getNotation(m), m.eval]; })); return moves1[_.sample(candidates, 1)]; } @@ -908,13 +915,16 @@ class ChessRules { switch (this.checkGameEnd()) { - case "1/2": return 0; - default: return color=="w" ? -maxeval : maxeval; + case "1/2": + return 0; + default: + const score = this.checkGameEnd(); + return (score=="1/2" ? 0 : (score=="1-0" ? 1 : -1) * maxeval); } } if (depth == 0) return this.evalPosition(); - const moves = this.getAllValidMoves(); + const moves = this.getAllValidMoves("computer"); let v = color=="w" ? -maxeval : maxeval; if (color == "w") { @@ -965,7 +975,7 @@ class ChessRules //////////// // FEN utils - // Overridable.. + // Setup the initial random (assymetric) position static GenRandInitFen() { let pieces = [new Array(8), new Array(8)]; @@ -1025,6 +1035,7 @@ class ChessRules return this.getBaseFen() + " " + this.getFlagsFen(); } + // Position part of the FEN string getBaseFen() { let fen = ""; @@ -1058,7 +1069,7 @@ class ChessRules return fen; } - // Overridable.. + // Flags part of the FEN string getFlagsFen() { let fen = ""; @@ -1066,7 +1077,7 @@ class ChessRules for (let i of ['w','b']) { for (let j=0; j<2; j++) - fen += this.castleFlags[i][j] ? '1' : '0'; + fen += (this.castleFlags[i][j] ? '1' : '0'); } return fen; } @@ -1074,14 +1085,8 @@ class ChessRules // Context: just before move is played, turn hasn't changed getNotation(move) { - if (move.appear.length == 2 && move.appear[0].p == VariantRules.KING) - { - // Castle - if (move.end.y < move.start.y) - return "0-0-0"; - else - return "0-0"; - } + if (move.appear.length == 2 && move.appear[0].p == VariantRules.KING) //castle + return (move.end.y < move.start.y ? "0-0-0" : "0-0"); // Translate final square const finalSquare = @@ -1126,15 +1131,17 @@ 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) + '-' + d.getDate() + '"]
'; + pgn += '[Date "' + d.getFullYear() + '-' + (d.getMonth()+1) + '-' + zeroPad(d.getDate()) + '"]
'; pgn += '[White "' + (mycolor=='w'?'Myself':opponent) + '"]
'; pgn += '[Black "' + (mycolor=='b'?'Myself':opponent) + '"]
'; - pgn += '[Fen "' + fenStart + '"]
'; + pgn += '[FenStart "' + fenStart + '"]
'; + pgn += '[Fen "' + this.getFen() + '"]
'; pgn += '[Result "' + score + '"]

'; // Standard PGN @@ -1144,7 +1151,7 @@ class ChessRules pgn += ((i/2)+1) + "."; pgn += this.moves[i].notation[0] + " "; } - pgn += score + "

"; + pgn += "

"; // "Complete moves" PGN (helping in ambiguous cases) for (let i=0; i