movements.ts 4.12 KB
Newer Older
1
2
import { Chessboard, squareAtPosition, Square } from './chessboard'
import { Position } from "./position";
3
4
import * as pieces from './piece'
import {Piece}  from './piece'
5
import * as isPossible from './move-validation'
6
7
8
9
10

const VALID_MOVE_STRING: RegExp = new RegExp('([a-z]|[A-Z])([1-8])-([A-H]|[a-z])([1-8])')

export interface Move {
    isValid : boolean;
Théo Winterhalter's avatar
Théo Winterhalter committed
11
12
    from?   : Position;
    to?     : Position;
13
14
}

15
16
17
18
19
20
21
22
23
24
25
26
/**
 * Creates a new Move from two Positions, representing
 * the Move's initial and final position.
 * 
 * @param from The initial position
 * @param to The final position
 */
export function move(from: Position, to: Position): Move {
    let move: Move = {from: from, to: to, isValid: true};
    return move;
}

27
28
29
/**
 * Processes a move received from a client browser.
 * If the move is valid and possible, the move is performed and this function
Théo Winterhalter's avatar
Théo Winterhalter committed
30
 * returns true. Otherwise, it returns false
31
32
33
34
35
36
37
 * 
 * @param chessboard The chessboard for the current game
 * @param moveString The string received from the client containing a move
 * @returns true, if the move is valid and possible
 */
export function processMove(chessboard:Chessboard, moveString: string): boolean {
    let move : Move = parseMoveString(moveString);
38
39
40
41
42

    if (move.isValid && isMovePossible(chessboard, move)) {
        performMove(chessboard, move); 
    } else {
        console.log("Invalid movement !");
43
        return false;
44
    }
45
    return true;
46
47
}

48
49
/**
 * Parses a string in the format "A1-F8" and returns a Move.
Théo Winterhalter's avatar
Théo Winterhalter committed
50
 * If the format is not valid, returns a Move with isValid === false.
51
52
53
 * 
 * @param movementString A 5 characters string containing a move
 */
54
55
56
57
58
59
export function parseMoveString(movementString: string): Move {
    let newMove : Move;
    if (movementString.length != 5 ||  ! movementString.match(VALID_MOVE_STRING)) {
        let invalidMove : Move = {isValid : false};
        newMove = invalidMove;
    } else {
60
61
62
63
        let fromFile  : number = movementString.charCodeAt(0);
        let fromRank    : number = parseInt(movementString[1]);
        let toFile      : number = movementString.charCodeAt(3);
        let toRank      : number = parseInt(movementString[4]);
64
65
66

        // In Unicode, charCode('A') == 65, charCode('a') == 97
        // Remember that Arrays start from [0][0] == position 'A1'
67
68
        let from : Position = {rank : fromRank -1, file: fromFile > 90 ? fromFile - 97 : fromFile - 65}
        let to   : Position = {rank : toRank -1, file: toFile > 90 ? toFile - 97 : toFile - 65 }
69
70
71
72
73
74

        newMove = {isValid: true, from: from, to: to}
    }
    return newMove;
}

75
76
77
78
79
/**
 * Checks whether a move is possible in the given chessboard
 * @param chessboard 
 * @param move 
 */
80
function isMovePossible(chessboard : Chessboard, move : Move): boolean {
81
82
    let square: Square = squareAtPosition(chessboard, move.from!);
    if (square.isEmpty) { return false;}
83

84
    let piece : Piece = square.piece!;
85
86

    switch(piece) {
87
88
        case pieces.whitePawn  : return isPossible.whitePawnMove(chessboard, move);
        case pieces.blackPawn  : return isPossible.blackPawnMove(chessboard, move);
89
90
91
92
        case pieces.whiteKing  : return isPossible.kingMove(chessboard, move);
        case pieces.whiteQueen : return isPossible.queenMove(chessboard, move);
        case pieces.whiteBishop: return isPossible.bishopMove(chessboard, move);
        case pieces.whiteKnight: return isPossible.knightMove(chessboard, move);
Théo Winterhalter's avatar
Théo Winterhalter committed
93
        case pieces.whiteRoock : return isPossible.rookMove(chessboard, move);
94
95
96
97
        case pieces.blackKing  : return isPossible.kingMove(chessboard, move);
        case pieces.blackQueen : return isPossible.queenMove(chessboard, move);
        case pieces.blackBishop: return isPossible.bishopMove(chessboard, move);
        case pieces.blackKnight: return isPossible.knightMove(chessboard, move);
Théo Winterhalter's avatar
Théo Winterhalter committed
98
        case pieces.blackRoock : return isPossible.rookMove(chessboard, move);
99
100
    }

101
    return false;
102
103
104
}

function performMove(board : Chessboard, move : Move) {
105
106
    let source      : Square = squareAtPosition(board, move.from!);
    let destination : Square = squareAtPosition(board, move.to!);
107
108
109
110
111

    destination.piece = source.piece;
    destination.isEmpty = false;
    source.isEmpty = true;
}