Commit 9382c61e authored by Gerson Sunyé's avatar Gerson Sunyé
Browse files

Renamed identifiers line and column to rank and file according to chess...

Renamed identifiers line and column to rank and file according to chess vocabulary. Removed redondant functions for pieces that have the same behavior independently fom their colors
parents 1f830976 33fe1025
......@@ -128,7 +128,7 @@ Pour vérifier que les fonctions du module `move-validation` fonctionnent correc
Les mouvements sont possibles (ou impossibles) en accord avec les [règles des échecs](https://fr.wikipedia.org/wiki/Échecs).
Comme ces règles sont complexes, vous serez mené à écrire plusieurs tests unitaires pour vérifier les mouvements possibles et impossibles d'une même pièce.
Les signatures des fonctions du module `move-validation` suivent la même convention:
Les signatures des fonctions du module `move-validation` suivent la même convention :
```ts
function colorPieceMove(board: Chessboard, move: Move): boolean
......@@ -140,7 +140,7 @@ Les coordonnées indiquent **toujours** des cases à l'intérieur de l'échiquie
Donc, il n'y a pas besoin de vérifier si un déplacement conduit une pièce à l'extérieur de l'échiquier.
Les tests unitaires des fonctions `blackPawnMove()` et `whitePawnMove()` ont déjà été implémentés, vous les trouverez dans le fichier `./spec/move-validation-spec.ts`.
Ce fichier contient déjà le squelette des autres test unitaires que vous devez implémenter.
**Vous devez compléter tous les squelettes de tests unitaires fournis à l'intérieur de ce fichier !**
Vous devez procéder par itérations successives, n'essayez pas d'implémenter les fonctions d'un seul trait. Observez le cycle de développement suivant:
......@@ -226,7 +226,7 @@ Suivez la même démarche pour implémenter et tester les autres fonctionnalité
### Rendu
Vous allez pouvoir effectuer le rendu directement depuis l'interface de Gitlab, en réalisant ce qu'on appelle une **demande de fusion**.
Cela permet d'envoyer tous les changements que vous avez effectué aux propriétaires du dépôt Gitlab d'origine (donc nous !) en quelques clics.
Cela permet de nous envoyer tous les changements que vous avez effectué sur le projet en quelques clics.
0. Assurez vous d'avoir effectué tous les *commits* et *pushs* nécessaires avec git.
1. Dans le panneau de gauche, cliquez sur "Demandes de fusion".
......@@ -238,21 +238,22 @@ Cela permet d'envoyer tous les changements que vous avez effectué aux propriét
7. Enfin, cliquez en bas sur "Submit demande de fusion"
Vous atteignez alors une page qui résume la demande effectuée.
Nous vous recommandons alors de cliquer sur l'onglet "Changes" afin d'avoir accès une une représentation visuelle de tous les changements que vous avez effectué.
Nous vous recommandons alors de cliquer sur l'onglet "*Changes*" afin d'avoir accès une une représentation visuelle de tous les changements que vous avez effectué.
Les lignes rouges indiques ce que vous avez retiré, les lignes vertes indiquent ce que vous avez ajouté.
Vérifiez si tout votre rendu est bien présent sous la forme de lignes vertes.
Vérifiez si tout votre travail réalisé est bien présent sous la forme de lignes vertes.
Si vous le souhaitez, vous pouvez ajouter un fichier "`RENDU.md`" à la racine du projet, afin de décrire les spécificités de votre projet (choix techniques, parties non traitées, extensions non demandées, etc.).
### Derniers conseils
- Rappelez-vous que « *Une fonction sans test unitaire ne fonctionne pas* »!
- Rappelez-vous que « *Une fonction sans test unitaire ne fonctionne pas* » !
- Rappelez-vous aussi que «*N'importe qui peut écrire du code compréhensible par les ordinateurs, mais seulement les bon développeurs parviennent à écrire du code intelligible par les humains* » !
- Écrivez les tests unitaires avant ou en même temps que les fonctions. Ne les laissez pas pour la fin, les test unitaires sont très utiles pendant le développement et vous feront gagner du temps.
- Faites bon usage de `git`: effectuez des *commits* et des *pushs* régulièrement ! Cela vous permet d'éviter de perdre votre travail, et de mieux collaborer en équipe.
- Faites bon usage de `git` : effectuez des *commits* et des *pushs* régulièrement ! Cela vous permet d'éviter de perdre votre travail, et de mieux collaborer en équipe.
......@@ -139,9 +139,9 @@ describe("Test whitePawnMove()", () => {
});
/**
* TODO: Unit tests for function blackKingMove()
* TODO: Unit tests for function kingMove()
*/
describe("Test blackKingMove()", () => {
describe("Test kingMove()", () => {
beforeEach( () => {
// TODO:
// Initialize an empty chessboard
......@@ -171,9 +171,9 @@ describe("Test blackKingMove()", () => {
});
/**
* TODO: Unit tests for function blackQueenMove()
* TODO: Unit tests for function queenMove()
*/
describe("Test blackQueenMove()", () => {
describe("Test queenMove()", () => {
beforeEach( () => {
// TODO:
// Initialize an empty chessboard
......@@ -197,9 +197,9 @@ describe("Test blackQueenMove()", () => {
});
/**
* TODO: Unit tests for function blackBishopMove()
* TODO: Unit tests for function bishopMove()
*/
describe("Test blackBishopMove()", () => {
describe("Test bishopMove()", () => {
beforeEach( () => {
// TODO:
// Initialize an empty chessboard
......@@ -225,9 +225,9 @@ describe("Test blackBishopMove()", () => {
});
/**
* TODO: Unit tests for function blackKnightMove()
* TODO: Unit tests for function knightMove()
*/
describe("Test blackKnightMove()", () => {
describe("Test knightMove()", () => {
beforeEach( () => {
// TODO:
// Initialize an empty chessboard
......@@ -259,9 +259,9 @@ describe("Test blackKnightMove()", () => {
});
/**
* TODO: Unit tests for function blackRoockMove()
* TODO: Unit tests for function roockMove()
*/
describe("Test blackRoockMove()", () => {
describe("Test roockMove()", () => {
beforeEach( () => {
// TODO:
// Initialize an empty chessboard
......@@ -299,29 +299,4 @@ describe("Test blackRoockMove()", () => {
it("A Roock cannot move when there are other pieces between the initial and final squares", () => {
// TODO:
});
});
/**
* TODO: Unit tests for function whiteKingMove()
*/
describe("Test whiteKingMove()", () => {});
/**
* TODO: Unit tests for function whiteQueenMove()
*/
describe("Test whiteQueenMove()", () => {});
/**
* TODO: Unit tests for function whiteBishopMove()
*/
describe("Test whiteBishopMove()", () => {});
/**
* TODO: Unit tests for function whiteKnightMove()
*/
describe("Test whiteKnightMove()", () => {});
/**
* TODO: Unit tests for function whiteRoockMove()
*/
describe("Test whiteRoockMove()", () => {});
\ No newline at end of file
});
\ No newline at end of file
......@@ -4,28 +4,31 @@ import {Position, equals} from "../src/position"
describe("parseMoveString", () => {
it("A2-A4", () => {
let move: Move = parseMoveString("A2-A4");
let expectedFrom: Position = {column: 0, line:1}
let expectedTo: Position = {column:0, line:3}
let expectedFrom: Position = {file: 0, rank:1}
let expectedTo: Position = {file:0, rank:3}
expect(move.isValid).toBeTruthy();
expect(equals(expectedFrom, move.from!)).toBeTruthy();
expect(equals(expectedTo, move.to!)).toBeTruthy();
});
it("B8-B3", () => {
let move: Move = parseMoveString("B8-B3");
let expectedFrom: Position = {column: 1, line:7}
let expectedTo: Position = {column:1, line:2}
let expectedFrom: Position = {file: 1, rank:7}
let expectedTo: Position = {file:1, rank:2}
expect(move.isValid).toBeTruthy();
expect(equals(expectedFrom, move.from!)).toBeTruthy();
expect(equals(expectedTo, move.to!)).toBeTruthy();
});
it("H8-H3", () => {
let move: Move = parseMoveString("H8-H3");
let expectedFrom: Position = {column: 7, line:7}
let expectedTo: Position = {column:7, line:2}
let expectedFrom: Position = {file: 7, rank:7}
let expectedTo: Position = {file:7, rank:2}
expect(move.isValid).toBeTruthy();
expect(equals(expectedFrom, move.from!)).toBeTruthy();
expect(equals(expectedTo, move.to!)).toBeTruthy();
});
it("a1-h8 == A1-H8", () => {
let lowercaseMove: Move = parseMoveString("a1-h8");
let uppercaseMove: Move = parseMoveString("A1-H8");
......
/*
* Module d'échiquier
* @Author: Quentin Tonneau
* @Date: 2018-03-15 22:15:13
* @Last Modified by: Quentin Tonneau
* @Last Modified time: 2018-03-15 22:16:12
*/
import * as pieces from './piece'
import {Piece} from './piece'
import {Move} from './movements'
......@@ -17,26 +8,26 @@ export function isEmpty(chessboard : Chessboard, position : Position): boolean {
return square.isEmpty;
}
export function emptyColumn(chessboard : Chessboard, move: Move): boolean {
export function emptyfile(chessboard : Chessboard, move: Move): boolean {
let start: number;
let end : number;
let column : number = move.from!.column;
let file : number = move.from!.file;
if (column !== move.to!.column) {
if (file !== move.to!.file) {
//should not happen
return false;
}
if (move.from!.line > move.to!.line) {
start = move.to!.line;
end = move.from!.line;
if (move.from!.rank > move.to!.rank) {
start = move.to!.rank;
end = move.from!.rank;
} else {
end = move.to!.line;
start = move.from!.line;
end = move.to!.rank;
start = move.from!.rank;
}
let i : number = start;
while (i <= end && chessboard.board[column][i].isEmpty) {
while (i <= end && chessboard.board[file][i].isEmpty) {
i++;
}
......@@ -56,7 +47,7 @@ export interface Chessboard {
}
export function squareAtPosition(chessboard: Chessboard, position : Position): Square {
let square: Square = chessboard.board[position.column][position.line];
let square: Square = chessboard.board[position.file][position.rank];
return square;
}
......@@ -71,16 +62,16 @@ export function createInitialChessboard(): Chessboard {
let chessboard : Chessboard = createChessboard();
// Lines 2 - 6 are empty
for(let line: number = 2; line < 6; line++) {
// ranks 2 - 6 are empty
for(let rank: number = 2; rank < 6; rank++) {
for(let col: number = 0; col < 8; col++) {
let position: Position = {line : line, column : col};
let position: Position = {rank : rank, file : col};
let square : Square = {position : position, isEmpty : true};
chessboard.board[col][line] = square;
chessboard.board[col][rank] = square;
}
}
// Pawns in lines 2 and 6
// Pawns in ranks 2 and 6
let position: Position;
let square : Square;
for(let col: number = 0; col < 8; col++) {
......@@ -118,11 +109,11 @@ export function createInitialChessboard(): Chessboard {
export function createEmptyChessboard(): Chessboard {
let newChessboard : Chessboard = createChessboard();
for(let line: number = 0; line < 8; line++) {
for(let rank: number = 0; rank < 8; rank++) {
for(let col: number = 0; col < 8; col++) {
let position: Position = {line : line, column : col};
let position: Position = {rank : rank, file : col};
let square : Square = {position : position, isEmpty : true};
newChessboard.board[col][line] = square;
newChessboard.board[col][rank] = square;
}
}
......@@ -144,13 +135,13 @@ function createChessboard(): Chessboard {
}
function putPieceAtCoordinate(chessboard: Chessboard, column : number, line: number, piece : Piece) {
let position : Position = {line : line, column : column};
function putPieceAtCoordinate(chessboard: Chessboard, file : number, rank: number, piece : Piece) {
let position : Position = {rank : rank, file : file};
return putPiece(chessboard, position, piece);
}
export function putPiece(chessboard: Chessboard, position: Position, piece : Piece) {
let board : Array<Array<Square>> = chessboard.board;
let square : Square = {position : position, isEmpty : false, piece : piece};
board[position.column][position.line] = square;
board[position.file][position.rank] = square;
}
\ No newline at end of file
......@@ -2,6 +2,19 @@ import { Chessboard, isEmpty, Square, squareAtPosition } from "./chessboard";
import { Move } from "./movements";
import { equals, left, right, bottom, top } from "./position";
/**
* Checks whether a Black Pown can perform a given move.
* A pawn can move forward to the unoccupied square immediately in front of
* it on the same file, or on its first move it can advance two squares along
* the same file, provided both squares are unoccupied (black dots in the
* diagram); or the pawn can capture an opponent's piece on a square diagonally
* in front of it on an adjacent file, by moving to that square (black "x"s).
*
* A pawn has two special moves: the en passant capture and promotion.
*
* @param board The chessboard of the current game
* @param move
*/
export function blackPawnMove(board: Chessboard, move: Move): boolean {
// #TODO: Manage special 'En passant' move.
......@@ -10,7 +23,7 @@ export function blackPawnMove(board: Chessboard, move: Move): boolean {
return isEmpty(board, move.to!);
}
if (move.from!.line === 6 && equals(move.to!, top(top(move.from!)))) {
if (move.from!.rank === 6 && equals(move.to!, top(top(move.from!)))) {
//console.log("Double forward");
return isEmpty(board, top(move.from!)) && isEmpty(board, move.to!);
}
......@@ -23,40 +36,25 @@ export function blackPawnMove(board: Chessboard, move: Move): boolean {
return false;
}
export function blackKingMove(board: Chessboard, move: Move): boolean {
// #TODO: Implement this function
return true;
}
export function blackQueenMove(board: Chessboard, move: Move): boolean {
// #TODO: Implement this function
return true;
}
export function blackRoockMove(board: Chessboard, move: Move): boolean {
// #TODO: Implement this function
return true;
}
export function blackBishopMove(board: Chessboard, move: Move): boolean {
// #TODO: Implement this function
return true;
}
export function blackKnightMove(board: Chessboard, move: Move): boolean {
// #TODO: Implement this function
return true;
}
/**
* A pawn can move forward to the unoccupied square immediately in front of
* it on the same file, or on its first move it can advance two squares along
* the same file, provided both squares are unoccupied (black dots in
* the diagram); or the pawn can capture an opponent's piece on a square diagonally
* in front of it on an adjacent file, by moving to that square (black "x"s).
*
* A pawn has two special moves: the en passant capture and promotion.
*
* @param board The chessboard of the current game
* @param move
*/
export function whitePawnMove(board: Chessboard, move: Move): boolean {
// #TODO: Manage special 'En passant' move.
if (equals(move.to!, bottom(move.from!))) {
return isEmpty(board, move.to!);
}
if (move.from!.line === 1 && equals(move.to!, bottom(bottom(move.from!)))) {
if (move.from!.rank === 1 && equals(move.to!, bottom(bottom(move.from!)))) {
return isEmpty(board, bottom(move.from!)) && isEmpty(board, move.to!);
}
......@@ -68,27 +66,70 @@ export function whitePawnMove(board: Chessboard, move: Move): boolean {
return false;
}
export function whiteKingMove(board: Chessboard, move: Move): boolean {
/**
* Checks whether a King can perform a given move.
* The king moves one square in any direction.
*
* @param board The chessboard of the current game
* @param move
*/
export function kingMove(board: Chessboard, move: Move): boolean {
// #TODO: Implement this function
return true;
}
export function whiteQueenMove(board: Chessboard, move: Move): boolean {
/**
* Checks whether a Quenn can perform a given move.
* The queen combines the power of a rook and bishop and can move any
* number of squares along a rank, file, or diagonal, but cannot leap over other pieces.
*
* @param board The chessboard of the current game
* @param move
*/
export function queenMove(board: Chessboard, move: Move): boolean {
// #TODO: Implement this function
return true;
}
export function whiteRoockMove(board: Chessboard, move: Move): boolean {
/**
* Checks whether a Roock can perform a given move.
* A rook can move any number of squares along a rank or file,
* but cannot leap over other pieces.
*
* @param board The chessboard of the current game
* @param move
*/
export function roockMove(board: Chessboard, move: Move): boolean {
// #TODO: Implement this function
return true;
}
export function whiteBishopMove(board: Chessboard, move: Move): boolean {
/**
* Checks whether a Bishop can perform a given move.
* A bishop can move any number of squares diagonally,
* but cannot leap over other pieces.
*
* @param board The chessboard of the current game
* @param move
*/
export function bishopMove(board: Chessboard, move: Move): boolean {
// #TODO: Implement this function
return true;
}
export function whiteKnightMove(board: Chessboard, move: Move): boolean {
/**
* Checks whether a knight can perform a given move.
* A knight moves to any of the closest squares that are not on the
* same rank, file, or diagonal. (Thus the move forms an "L"-shape:
* two squares vertically and one square horizontally, or two
* squares horizontally and one square vertically.)
*
* The knight is the only piece that can leap over other pieces.
*
* @param board The chessboard of the current game
* @param move
*/
export function knightMove(board: Chessboard, move: Move): boolean {
// #TODO: Implement this function
return true;
}
\ No newline at end of file
}
\ No newline at end of file
......@@ -45,15 +45,15 @@ export function parseMoveString(movementString: string): Move {
let invalidMove : Move = {isValid : false};
newMove = invalidMove;
} else {
let fromColumn : number = movementString.charCodeAt(0);
let fromLine : number = parseInt(movementString[1]);
let toColumn : number = movementString.charCodeAt(3);
let toLine : number = parseInt(movementString[4]);
let fromFile : number = movementString.charCodeAt(0);
let fromRank : number = parseInt(movementString[1]);
let toFile : number = movementString.charCodeAt(3);
let toRank : number = parseInt(movementString[4]);
// In Unicode, charCode('A') == 65, charCode('a') == 97
// Remember that Arrays start from [0][0] == position 'A1'
let from : Position = {line : fromLine -1, column: fromColumn > 90 ? fromColumn - 97 : fromColumn - 65}
let to : Position = {line : toLine -1, column: toColumn > 90 ? toColumn - 97 : toColumn - 65 }
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 }
newMove = {isValid: true, from: from, to: to}
}
......@@ -73,17 +73,17 @@ function isMovePossible(chessboard : Chessboard, move : Move): boolean {
switch(piece) {
case pieces.whitePawn : return isPossible.whitePawnMove(chessboard, move);
case pieces.whiteKing : return isPossible.whiteKingMove(chessboard, move);
case pieces.whiteQueen : return isPossible.whiteQueenMove(chessboard, move);
case pieces.whiteBishop: return isPossible.whiteBishopMove(chessboard, move);
case pieces.whiteKnight: return isPossible.whiteKnightMove(chessboard, move);
case pieces.whiteRoock : return isPossible.whiteRoockMove(chessboard, move);
case pieces.blackPawn : return isPossible.blackPawnMove(chessboard, move);
case pieces.blackKing : return isPossible.blackKingMove(chessboard, move);
case pieces.blackQueen : return isPossible.blackQueenMove(chessboard, move);
case pieces.blackBishop: return isPossible.blackBishopMove(chessboard, move);
case pieces.blackKnight: return isPossible.blackKnightMove(chessboard, move);
case pieces.blackRoock : return isPossible.blackRoockMove(chessboard, move);
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);
case pieces.whiteRoock : return isPossible.roockMove(chessboard, move);
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);
case pieces.blackRoock : return isPossible.roockMove(chessboard, move);
}
return false;
......@@ -97,14 +97,3 @@ function performMove(board : Chessboard, move : Move) {
destination.isEmpty = false;
source.isEmpty = true;
}
function isSameColumn(move: Move) {
return move.from!.column === move.to!.column;
}
function height(move : Move) : number {
return Math.abs(move.from!.column - move.to!.column);
}
/**
* Chess is played on a square board of eight rows (called ranks,
* denoted 1 to 8) and eight columns (called files, denoted a to h).
*/
export interface Position {
line: number;
column: number;
rank: number;
file: number;
}
/**
* Creates a new Posistion from two numbers, representing
* the new position's column and line.
* the new position's file and rank.
*
* @param line this position line, from 0..7
* @param column this position column, from 0..7
* @param rank this position rank, from 0..7
* @param file this position file, from 0..7
*/
export function position(column:number, line: number): Position {
let position: Position = {line: line, column: column};
export function position(file:number, rank: number): Position {
let position: Position = {rank: rank, file: file};
return position;
}
export function top(pos: Position) : Position {
let topPosition = {column: pos.column, line: pos.line - 1};
let topPosition = {file: pos.file, rank: pos.rank - 1};
return topPosition;
}
export function bottom(pos: Position) : Position {
let topPosition = {column: pos.column, line: pos.line + 1};
let topPosition = {file: pos.file, rank: pos.rank + 1};
return topPosition;
}
export function left(pos: Position) : Position {
let leftPosition = {column: pos.column - 1, line: pos.line};
let leftPosition = {file: pos.file - 1, rank: pos.rank};
return leftPosition;
}
export function right(pos: Position) : Position {
let rightPosition = {column: pos.column + 1, line: pos.line};
let rightPosition = {file: pos.file + 1, rank: pos.rank};
return rightPosition;
}
export function equals(one: Position, other: Position) : boolean {
//console.log("Equals: " + JSON.stringify(one) + ", " + JSON.stringify(other));
return one.line === other.line && one.column === other.column;
return one.rank === other.rank && one.file === other.file;
}
\ No newline at end of file
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment