+ // Normalize direction to know the step
+ getNormalizedDirection([dx, dy]) {
+ const absDir = [Math.abs(dx), Math.abs(dy)];
+ let divisor = 0;
+ if (absDir[0] != 0 && absDir[1] != 0 && absDir[0] != absDir[1])
+ // Knight
+ divisor = Math.min(absDir[0], absDir[1]);
+ else
+ // Standard slider (or maybe a pawn or king: same)
+ divisor = Math.max(absDir[0], absDir[1]);
+ return [dx / divisor, dy / divisor];
+ }
+
+ // There is something on x2,y2, maybe our color, pushed/pulled
+ static IsAprioriValidMove([x1, y1], [x2, y2]) {
+ const color1 = this.getColor(x1, y1);
+ const color2 = this.getColor(x2, y2);
+ const pawnShift = (color1 == 'w' ? -1 : 1);
+ const pawnStartRank = (color1 == 'w' ? 6 : 1);
+ const deltaX = Math.abs(x1 - x2);
+ const deltaY = Math.abs(y1 - y2);
+ switch (this.getPiece(x1, y1)) {
+ case V.PAWN:
+ return (
+ (
+ color1 == color2 &&
+ y1 == y2 &&
+ (
+ x1 + pawnShift == x2 ||
+ x1 == pawnStartRank && x1 + 2 * pawnShift == x2
+ )
+ )
+ ||
+ (
+ color1 != color2 &&
+ deltaY == 1 &&
+ x1 + pawnShift == x2
+ )
+ );
+ case V.ROOK:
+ return (x1 == x2 || y1 == y2);
+ case V.KNIGHT: {
+ return (deltaX + deltaY == 3 && (deltaX == 1 || deltaY == 1));
+ }
+ case V.BISHOP:
+ return (deltaX == deltaY);
+ case V.QUEEN:
+ return (
+ (deltaX == 0 || deltaY == 0 || deltaX == deltaY)
+ );
+ case V.KING:
+ return (deltaX <= 1 && deltaY <= 1);
+ }
+ return false;
+ }
+
+ // NOTE: for pushes, play the pushed piece first.
+ // for pulls: play the piece doing the action first
+ // NOTE: to push a piece out of the board, make it slide until its king
+ getPotentialMovesFrom([x, y]) {
+ const color = this.turn;
+ if (this.subTurn == 1) {
+ // Free to play any move:
+ const moves = super.getPotentialMovesFrom([x, y])
+ // Structure to avoid adding moves twice (can be action & move)
+ let hashMoves = {};
+ moves.forEach(m => { hashMoves[getMoveHash(m)] = true; });
+ const getMoveHash = (m) => {
+ return V.CoordsToSquare(m.start) + V.CoordsToSquare(m.end);
+ };
+ const addMoves = (dir, nbSteps) => {
+ const newMoves =
+ this.getMovesInDirection([x, y], [-dir[0], -dir[1]], nbSteps)
+ .filter(m => !movesHash[getMoveHash(m)]);
+ newMoves.forEach(m => { hashMoves[getMoveHash(m)] = true; });
+ Array.prototype.push.apply(moves, newMoves);
+ };
+ const pawnShift = (color == 'w' ? -1 : 1);
+ const pawnStartRank = (color == 'w' ? 6 : 1);
+ // [x, y] is pushed by 'color'