Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[#27] check #59

Merged
merged 4 commits into from
Feb 14, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/controllers/GameController.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ class GameController {

if (isLegalMove) {
this.playSound(this.activeSquare, square);
this.gameEngine.movePiece(this.activeSquare, square);
this.gameEngine.movePiece(this.activeSquare, square, false);
this.boardView.render(this.gameEngine.board);
this.changePlayer();
}
Expand Down
14 changes: 11 additions & 3 deletions src/services/game-logic/Board.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,8 @@ import { Queen } from './pieces/Queen';
class Board {
public static BOARD_SIZE = 8;

private state: Array<Array<Piece | null>>;
private movesHistory: [Piece, Square][] = [];
public state: Array<Array<Piece | null>>;
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

to jest chujowe, myślę co z tym zrobić

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ale widzę ten sam ruch w innym prze :P

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

u mnie jest na public, bo sie bardzo przyadło :P


constructor() {
this.state = new Array(Board.BOARD_SIZE);
Expand All @@ -27,9 +27,17 @@ class Board {
return this.state[square.row][square.column];
}

public movePiece(location: Square, destination: Square): void {
public checkAllSquares = (callback: any) => {
this.state.forEach((row) => {
row.forEach((square) => {
callback(square);
});
});
};

public movePiece(location: Square, destination: Square, potentialMove: boolean): void {
const piece = this.getPiece(location);
if (piece) this.movesHistory.push([piece, destination]);
if (!potentialMove && piece) this.movesHistory.push([piece, destination]);

this.state[location.row][location.column]?.move(destination);
this.state[destination.row][destination.column] = this.state[location.row][location.column];
Expand Down
70 changes: 58 additions & 12 deletions src/services/game-logic/GameEngine.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { PieceNames, Constants } from '../../enums';
import { PieceNames, Constants, Colors } from '../../enums';
import { Square } from '../../models/Square';
import { Board } from './Board';
import { King } from './pieces/King';
import { Piece } from './pieces/Piece';

class GameEngine {
Expand All @@ -12,13 +13,61 @@ class GameEngine {

getLegalMoves = (square: Square): Square[] => {
const piece = this.board.getPiece(square);
let legalMoves = piece?.getPossibleMoves(this.board).filter(this.isOnBoard) ?? [];
let legalMoves = piece?.getPossibleMoves(this.board) ?? [];
if (piece?.name === PieceNames.KING) {
legalMoves = legalMoves.filter(
(move) => !this.isCastling(move, piece) || this.isCastlingLegal(move, piece)
);
}
return legalMoves.filter((destination) => !this.isOccupiedBySameColor(destination, piece));
return legalMoves
.filter((destination) => !this.isOccupiedBySameColor(destination, piece))
.filter((move) => this.moveNotResultWithCheck(move, piece, square));
};

moveNotResultWithCheck(move: Square, piece: Piece | null, square: Square): boolean {
const potentialMove = new Square(move.row, move.column);
const potentialPiece = this.board.getPiece(potentialMove);

this.movePiece(square, potentialMove, true);
piece!.hasMoved = true;
const isMovePossible = !this.isCheck(piece);

this.movePiece(potentialMove, square, true);
piece!.hasMoved = false;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

to tylko działa, jeśli bierka się wcześniej nie ruszyła - trzeba by zapisywać jej poprzedni status do stałej

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

hmm, ale ona zawsze będzie się ruszać, o tutaj:
this.movePiece(square, potentialMove);


if (potentialPiece)
this.board.state[potentialPiece.position.row][potentialPiece.position.column] = potentialPiece;

return isMovePossible;
}

private isCheck(piece: Piece | null): boolean {
const color = piece?.color === Colors.BLACK ? Colors.WHITE : Colors.BLACK;
let currentPlayerKing = this.getKingForCheck(piece)?.position;
const isChecked = this.isKingUnderCheck(color, currentPlayerKing);
return isChecked;
}

isKingUnderCheck(color: Colors, piecePosition: Square | undefined): boolean {
let checked = false;
this.board.checkAllSquares((square: Piece) => {
if (square && square.color === color) {
checked = square
.getPossibleMoves(this.board)
.some((move) => move.row === piecePosition?.row && move.column === piecePosition.column);
}
});
return checked;
}

getKingForCheck = (piece: Piece | null): King | null => {
let king = null;
this.board.checkAllSquares((square: Piece) => {
if (square && square?.color === piece?.color && square.name === PieceNames.KING) {
king = square;
}
});
return king;
};

public runSpecialRoutines(location: Square, destination: Square): void {
Expand All @@ -31,11 +80,11 @@ class GameEngine {
}
}

public movePiece(location: Square, destination: Square): void {
public movePiece(location: Square, destination: Square, potentialMove: boolean): void {
const piece = this.board.getPiece(location);
if (piece) {
this.runSpecialRoutines(piece?.position, destination);
this.board.movePiece(location, destination);
this.board.movePiece(location, destination, potentialMove);
}
}

Expand All @@ -52,12 +101,14 @@ class GameEngine {
if (destination.column - location.column === Constants.KINGSIDE_CASTLING) {
this.board.movePiece(
{ row: location.row, column: Constants.KINGSIDE_ROOK_COLUMN },
{ row: location.row, column: Constants.KINGSIDE_ROOK_DESTINATION_COLUMN }
{ row: location.row, column: Constants.KINGSIDE_ROOK_DESTINATION_COLUMN },
false
);
} else if (destination.column - location.column === Constants.QUEENSIDE_CASTLING) {
this.board.movePiece(
{ row: location.row, column: Constants.QUEENSIDE_ROOK_COLUMN },
{ row: location.row, column: Constants.QUEENSIDE_ROOK_DESTINATION_COLUMN }
{ row: location.row, column: Constants.QUEENSIDE_ROOK_DESTINATION_COLUMN },
false
);
}
}
Expand Down Expand Up @@ -87,11 +138,6 @@ class GameEngine {
return this.getLegalMoves(from).some(({ row, column }) => row === to.row && column === to.column);
}; // might be useful for 'check'

private isOnBoard = (square: Square): boolean => {
// here or in knight.ts (for now knights can get outside the board)
return square.row >= 0 && square.row < 8 && square.column >= 0 && square.column < 8;
};

private isOccupiedBySameColor = (square: Square, piece: Piece | null): boolean =>
this.board.getPiece(square)?.color === piece?.color;
}
Expand Down
7 changes: 5 additions & 2 deletions src/services/game-logic/pieces/King.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,13 +17,16 @@ class King extends Piece {
[1, -1]
];
if (!this.hasMoved) positions = [...positions, [0, 2], [0, -2]];
const [row, column] = positions;

const possibleMoves = positions.map(([row, column]) => ({
row: this.position.row + row,
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

do wyrzucenia linia 20 const [row, column] = positions; nie jest to używane nigdzie

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

poprawione

column: this.position.column + column
}));
return possibleMoves;

const kingPossibleMovesOnBoard = possibleMoves.filter(
(move) => move.row >= 0 && move.row < 8 && move.column >= 0 && move.column < 8
);
return kingPossibleMovesOnBoard;
}
}

Expand Down
3 changes: 2 additions & 1 deletion src/services/game-logic/pieces/Knight.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,8 @@ class Knight extends Piece {
destination.push(new Square(row + possibleRowMoves[i], column + possibleColumnMoves[i]));
}

return destination;
const knightPossibleMoves = destination.filter((d) => d.row >= 0 && d.row < 8 && d.column >= 0 && d.column < 8);
return knightPossibleMoves;
}
}

Expand Down
11 changes: 11 additions & 0 deletions test/services/game-logic/Board.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,3 +18,14 @@ describe('Testing Board.setup()', () => {
});
});
});

test(`should run function on all squares`, () => {
let arr = [];
const board = new Board();

board.checkAllSquares((square) => {
arr.push(square);
});

expect(arr.length).toBe(32);
});
36 changes: 36 additions & 0 deletions test/services/game-logic/GameEngine.test.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,10 @@
import { Square } from '../../../src/models/Square';
import { GameEngine } from '../../../src/services/game-logic/GameEngine';
import { Colors } from '../../../src/enums';
import { Board } from '../../../src/services/game-logic/Board';
import { King } from '../../../src/services/game-logic/pieces/King';

const gameEngine = new GameEngine();

describe('Testing GameEngine.getLegalMoves() while playing Pawn', () => {
test(`Pawn shall return 2 capturing moves `, () => {
Expand All @@ -16,6 +21,7 @@ describe('Testing GameEngine.getLegalMoves() while playing Pawn', () => {
// Test
expect(legalMoves).toEqual(expected);
});

test(`Extra En Passat move while playing white`, () => {
// Setup
const gameEngine = new GameEngine();
Expand All @@ -32,6 +38,7 @@ describe('Testing GameEngine.getLegalMoves() while playing Pawn', () => {
// Test
expect(legalMoves).toEqual(expected);
});

test(`White En Passat removes Black Pawn`, () => {
// Setup
const gameEngine = new GameEngine();
Expand All @@ -49,3 +56,32 @@ describe('Testing GameEngine.getLegalMoves() while playing Pawn', () => {
expect(removedPiece).toBe(null);
});
});

test(`should target king`, () => {
const piece = gameEngine.board.getPiece(new Square(1, 4));
const king = gameEngine.getKingForCheck(piece);
const expected = new Square(0, 4);

expect(king instanceof King).toBe(true);
expect(king.position).toStrictEqual(expected);
});

test(`should return true when check`, () => {
const color = Colors.BLACK;
const piece = new King({ column: 7, row: 3 }, Colors.WHITE);

const isKingChecked = gameEngine.isKingUnderCheck(color, piece.position);

expect(isKingChecked).toBe(true);
});

test(`should verify if oponent move result with check`, () => {
const board = new Board();
const square = { row: 6, column: 3 };
const move = new Square(4, 3);
const piece = board.getPiece(square);

const notCheck = gameEngine.moveNotResultWithCheck(move, piece, square);

expect(notCheck).toBe(true);
});
27 changes: 2 additions & 25 deletions test/services/game-logic/pieces/Knight.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,35 +3,12 @@ import { Square } from '../../../../src/models/Square';
import { Knight } from '../../../../src/services/game-logic/pieces/Knight';

test.each([
[
Colors.WHITE,
7,
5,
[
new Square(9, 6),
new Square(8, 7),
new Square(6, 7),
new Square(5, 6),
new Square(5, 4),
new Square(6, 3),
new Square(8, 3),
new Square(9, 4)
]
],
[Colors.WHITE, 7, 5, [new Square(6, 7), new Square(5, 6), new Square(5, 4), new Square(6, 3)]],
[
Colors.BLACK,
3,
6,
[
new Square(5, 7),
new Square(4, 8),
new Square(2, 8),
new Square(1, 7),
new Square(1, 5),
new Square(2, 4),
new Square(4, 4),
new Square(5, 5)
]
[new Square(5, 7), new Square(1, 7), new Square(1, 5), new Square(2, 4), new Square(4, 4), new Square(5, 5)]
]
])(
'should return knights possible moves',
Expand Down