Bugs fixing, finalization of rules in french+english
[vchess.git] / public / javascripts / base_rules.js
index 7a42a38..9599fdb 100644 (file)
@@ -64,22 +64,16 @@ class ChessRules
                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;
        }
@@ -113,12 +107,29 @@ class ChessRules
                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)
        {
@@ -126,9 +137,9 @@ class ChessRules
        }
 
        // 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}
@@ -288,7 +299,7 @@ class ChessRules
        // Return current fen (game state)
        getFen()
        {
-               return this.getBaseFen() + " " + this.turn +
+               return this.getBaseFen() + " " + this.getTurnFen() +
                        (V.HasFlags ? (" " + this.getFlagsFen()) : "") +
                        (V.HasEnpassant ? (" " + this.getEnpassantFen()) : "");
        }
@@ -326,6 +337,11 @@ class ChessRules
                return position;
        }
 
+       getTurnFen()
+       {
+               return this.turn;
+       }
+
        // Flags part of the FEN string
        getFlagsFen()
        {
@@ -389,7 +405,7 @@ class ChessRules
                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);
        }
 
@@ -612,7 +628,8 @@ class ChessRules
                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]
@@ -959,8 +976,25 @@ class ChessRules
        // After move is played, update variables + flags
        updateVariables(move)
        {
-               const piece = move.vanish[0].p;
-               const c = this.getOppCol(this.turn); //'move.vanish[0].c' doesn't work for Checkered
+               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
@@ -968,22 +1002,27 @@ class ChessRules
                {
                        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;
+                       }
                }
        }
 
@@ -1083,7 +1122,7 @@ class ChessRules
                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");
        }
 
        ///////////////
@@ -1211,7 +1250,7 @@ class ChessRules
                }
                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++)