Skip to content

Commit

Permalink
Add one unit test for a sample gameplay
Browse files Browse the repository at this point in the history
  • Loading branch information
Udit Agarwal committed Jul 18, 2020
1 parent d71d364 commit 22bc4dc
Show file tree
Hide file tree
Showing 20 changed files with 377 additions and 63 deletions.
3 changes: 3 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,4 +12,7 @@
* **And Operation**: We are allowed to do something if all conditions fulfill.
Try to improve the design for this.
* Add history of moves for each player.
* Add support for casteling move.
* Can we remove putting currentCell in Piece? How about introducing something like position?
* A piece will have a position and you can always get the cell back from board using this position.

19 changes: 19 additions & 0 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -32,5 +32,24 @@
<artifactId>google-collections</artifactId>
<version>1.0</version>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter</artifactId>
<version>RELEASE</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-api</artifactId>
<version>5.7.0-M1</version>
<scope>compile</scope>
</dependency>
<!-- https://mvnrepository.com/artifact/org.mockito/mockito-all -->
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-all</artifactId>
<version>1.10.19</version>
<scope>test</scope>
</dependency>
</dependencies>
</project>
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,12 @@
import com.uditagarwal.chess.model.Board;
import com.uditagarwal.chess.model.Cell;
import com.uditagarwal.chess.model.Piece;
import com.uditagarwal.chess.model.Player;

/**
* This check tells whether a piece can occupy a given cell in the board or not.
*/
public interface PieceCellOccupyBlocker {

boolean isCellNonOccupiableForPiece(Cell cell, Piece piece, Board board);
boolean isCellNonOccupiableForPiece(Cell cell, Piece piece, Board board, Player player);
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,15 @@

public class PieceCellOccupyBlockerFactory {

public static List<PieceCellOccupyBlocker> defaultBlockers() {
return ImmutableList.of(new PieceCellOccupyBlockerSelfPiece(), new PieceCellOccupyBlockerKingCheck());
public static PieceCellOccupyBlocker defaultBaseBlocker() {
return new PieceCellOccupyBlockerSelfPiece();
}

public static List<PieceCellOccupyBlocker> defaultAdditionalBlockers() {
return ImmutableList.of(new PieceCellOccupyBlockerKingCheck());
}

public static List<PieceCellOccupyBlocker> kingCheckEvaluationBlockers() {
return ImmutableList.of(new PieceCellOccupyBlockerSelfPiece());
return ImmutableList.of();
}
}
Original file line number Diff line number Diff line change
@@ -1,25 +1,17 @@
package com.uditagarwal.chess.conditions;

import com.uditagarwal.chess.model.Board;
import com.uditagarwal.chess.model.Cell;
import com.uditagarwal.chess.model.Piece;
import com.uditagarwal.chess.model.PieceType;

import java.util.ArrayList;
import java.util.List;

import static com.uditagarwal.chess.conditions.PieceCellOccupyBlockerFactory.kingCheckEvaluationBlockers;
import com.uditagarwal.chess.model.*;

/**
* This tells whether making piece move to a cell will attract check for king.
*/
public class PieceCellOccupyBlockerKingCheck implements PieceCellOccupyBlocker {

@Override
public boolean isCellNonOccupiableForPiece(final Cell cell, final Piece piece, final Board board) {
public boolean isCellNonOccupiableForPiece(final Cell cell, final Piece piece, final Board board, Player player) {
Cell pieceOriginalCell = piece.getCurrentCell();
piece.setCurrentCell(cell);
boolean playerGettingCheckByMove = board.isPlayerOnCheck(piece.getPlayer());
boolean playerGettingCheckByMove = board.isPlayerOnCheck(player);
piece.setCurrentCell(pieceOriginalCell);
return playerGettingCheckByMove;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,12 @@
import com.uditagarwal.chess.model.Board;
import com.uditagarwal.chess.model.Cell;
import com.uditagarwal.chess.model.Piece;
import com.uditagarwal.chess.model.Player;

public class PieceCellOccupyBlockerSelfPiece implements PieceCellOccupyBlocker {

@Override
public boolean isCellNonOccupiableForPiece(Cell cell, Piece piece, Board board) {
public boolean isCellNonOccupiableForPiece(Cell cell, Piece piece, Board board, Player player) {
if (cell.isFree()) {
return false;
}
Expand Down
16 changes: 16 additions & 0 deletions src/main/java/com/uditagarwal/chess/helpers/ListHelpers.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package com.uditagarwal.chess.helpers;

import java.util.ArrayList;
import java.util.List;

public class ListHelpers {
public static <T> List<T> removeDuplicates(List<T> list) {
List<T> newList = new ArrayList<T>();
for (T element : list) {
if (!newList.contains(element)) {
newList.add(element);
}
}
return newList;
}
}
16 changes: 8 additions & 8 deletions src/main/java/com/uditagarwal/chess/model/Board.java
Original file line number Diff line number Diff line change
Expand Up @@ -18,19 +18,19 @@ public Board(int boardSize, Cell[][] cells) {
}

public Cell getLeftCell(Cell cell) {
return getCellAtLocation(cell.getX() - 1, cell.getY());
return getCellAtLocation(cell.getX(), cell.getY() - 1);
}

public Cell getRightCell(Cell cell) {
return getCellAtLocation(cell.getX() + 1, cell.getY());
return getCellAtLocation(cell.getX(), cell.getY() + 1);
}

public Cell getUpCell(Cell cell) {
return getCellAtLocation(cell.getX(), cell.getY() + 1);
return getCellAtLocation(cell.getX() + 1, cell.getY());
}

public Cell getDownCell(Cell cell) {
return getCellAtLocation(cell.getX(), cell.getY() - 1);
return getCellAtLocation(cell.getX() - 1, cell.getY());
}

public Cell getCellAtLocation(int x, int y) {
Expand All @@ -45,15 +45,15 @@ public Cell getCellAtLocation(int x, int y) {
}

public boolean isPlayerOnCheck(Player player) {
return checkIfPieceCanBeKilled(player.getPiece(PieceType.KING), kingCheckEvaluationBlockers());
return checkIfPieceCanBeKilled(player.getPiece(PieceType.KING), kingCheckEvaluationBlockers(), player);
}

public boolean checkIfPieceCanBeKilled(Piece targetPiece, List<PieceCellOccupyBlocker> cellOccupyBlockers) {
public boolean checkIfPieceCanBeKilled(Piece targetPiece, List<PieceCellOccupyBlocker> cellOccupyBlockers, Player player) {
for (int i = 0; i < getBoardSize(); i++) {
for (int j = 0; j < getBoardSize(); j++) {
Piece currentPiece = getCellAtLocation(i, j).getCurrentPiece();
if (!currentPiece.isPieceFromSamePlayer(targetPiece)) {
List<Cell> nextPossibleCells = currentPiece.nextPossibleCells(this, cellOccupyBlockers);
if (currentPiece != null && !currentPiece.isPieceFromSamePlayer(targetPiece)) {
List<Cell> nextPossibleCells = currentPiece.nextPossibleCells(this, cellOccupyBlockers, player);
if (nextPossibleCells.contains(targetPiece.getCurrentCell())) {
return true;
}
Expand Down
5 changes: 5 additions & 0 deletions src/main/java/com/uditagarwal/chess/model/Cell.java
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,11 @@ public class Cell {
private int x;
private int y;

public Cell(int x, int y) {
this.x = x;
this.y = y;
}

//TODO: Ensure that this does not get used in equals.
@Setter
private Piece currentPiece;
Expand Down
22 changes: 11 additions & 11 deletions src/main/java/com/uditagarwal/chess/model/Piece.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import com.uditagarwal.chess.conditions.PieceCellOccupyBlocker;
import com.uditagarwal.chess.exceptions.InvalidMoveException;
import com.uditagarwal.chess.helpers.ListHelpers;
import com.uditagarwal.chess.moves.PossibleMovesProvider;
import lombok.Getter;
import lombok.NonNull;
Expand All @@ -10,44 +11,43 @@
import java.util.ArrayList;
import java.util.List;

import static com.uditagarwal.chess.helpers.ListHelpers.removeDuplicates;

@Getter
public class Piece {
private boolean isKilled = false;
private final Color color;
private final List<PossibleMovesProvider> movesProviders;
private Integer numMoves = 0;
Player player;
PieceType pieceType;

@Setter
@NonNull
private Cell currentCell;

public Piece(@NonNull final Color color, @NonNull final List<PossibleMovesProvider> movesProviders,
@NonNull final Player player, @NonNull final PieceType pieceType, @NonNull final Cell currentCell) {
public Piece(@NonNull final Color color, @NonNull final List<PossibleMovesProvider> movesProviders, @NonNull final PieceType pieceType) {
this.color = color;
this.movesProviders = movesProviders;
this.player = player;
this.pieceType = pieceType;
this.currentCell = currentCell;
}

public void killIt() {
this.isKilled = true;
}

public void move(Cell toCell, Board board, List<PieceCellOccupyBlocker> cellOccupyBlockers) {
public void move(Player player, Cell toCell, Board board, List<PieceCellOccupyBlocker> additionalBlockers) {
if (isKilled) {
throw new InvalidMoveException();
}
List<Cell> nextPossibleCells = nextPossibleCells(board, cellOccupyBlockers);
List<Cell> nextPossibleCells = nextPossibleCells(board, additionalBlockers, player);
if (!nextPossibleCells.contains(toCell)) {
throw new InvalidMoveException();
}

killPieceInCell(toCell);
this.currentCell.setCurrentPiece(null);
this.currentCell = toCell;
this.currentCell.setCurrentPiece(this);
this.numMoves ++;
}

Expand All @@ -57,18 +57,18 @@ private void killPieceInCell(Cell targetCell) {
}
}

public List<Cell> nextPossibleCells(Board board, List<PieceCellOccupyBlocker> cellOccupyBlockers) {
public List<Cell> nextPossibleCells(Board board, List<PieceCellOccupyBlocker> additionalBlockers, Player player) {
List<Cell> result = new ArrayList<>();
for (PossibleMovesProvider movesProvider: this.movesProviders) {
List<Cell> cells = movesProvider.possibleMoves(this, board, cellOccupyBlockers);
List<Cell> cells = movesProvider.possibleMoves(this, board, additionalBlockers, player);
if (cells != null) {
result.addAll(cells);
}
}
return result;
return removeDuplicates(result);
}

public boolean isPieceFromSamePlayer(Piece piece) {
return piece.getPlayer().equals(this.player);
return piece.getColor().equals(this.color);
}
}
12 changes: 9 additions & 3 deletions src/main/java/com/uditagarwal/chess/model/Player.java
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,20 @@
import com.uditagarwal.chess.model.PieceType;
import com.uditagarwal.gameplay.contracts.PlayerMove;
import com.uditagarwal.chess.model.Piece;
import lombok.Getter;

import java.util.List;

public abstract class Player {

@Getter
public abstract class Player {
List<Piece> pieces;

public Player(List<Piece> pieces) {
this.pieces = pieces;
}

public Piece getPiece(PieceType pieceType) {
for (Piece piece :pieces) {
for (Piece piece :getPieces()) {
if (piece.getPieceType() == pieceType) {
return piece;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
import com.uditagarwal.chess.model.Board;
import com.uditagarwal.chess.model.Cell;
import com.uditagarwal.chess.model.Piece;
import com.uditagarwal.chess.model.Player;

import java.util.ArrayList;
import java.util.List;
Expand All @@ -14,26 +15,28 @@ public abstract class PossibleMovesProvider {
int maxSteps;
MoveBaseCondition baseCondition;
PieceMoveFurtherCondition moveFurtherCondition;
PieceCellOccupyBlocker baseBlocker;

public PossibleMovesProvider(int maxSteps, MoveBaseCondition baseCondition, PieceMoveFurtherCondition moveFurtherCondition) {
public PossibleMovesProvider(int maxSteps, MoveBaseCondition baseCondition, PieceMoveFurtherCondition moveFurtherCondition, PieceCellOccupyBlocker baseBlocker) {
this.maxSteps = maxSteps;
this.baseCondition = baseCondition;
this.moveFurtherCondition = moveFurtherCondition;
this.baseBlocker = baseBlocker;
}

public List<Cell> possibleMoves(Piece piece, Board inBoard, List<PieceCellOccupyBlocker> cellOccupyBlockers) {
public List<Cell> possibleMoves(Piece piece, Board inBoard, List<PieceCellOccupyBlocker> additionalBlockers, Player player) {
if (baseCondition.isBaseConditionFullfilled(piece)) {
return possibleMovesAsPerCurrentType(piece, inBoard, cellOccupyBlockers);
return possibleMovesAsPerCurrentType(piece, inBoard, additionalBlockers, player);
}
return null;
}

protected List<Cell> findAllNextMoves(Piece piece, NextCellProvider nextCellProvider, Board board, List<PieceCellOccupyBlocker> cellOccupyBlockers) {
protected List<Cell> findAllNextMoves(Piece piece, NextCellProvider nextCellProvider, Board board, List<PieceCellOccupyBlocker> cellOccupyBlockers, Player player) {
List<Cell> result = new ArrayList<>();
Cell nextCell = nextCellProvider.nextCell(piece.getCurrentCell());
int numSteps = 1;
while (nextCell != null && numSteps <= maxSteps) {
if (checkIfCellCanBeOccupied(piece, nextCell, board, cellOccupyBlockers)) {
if (checkIfCellCanBeOccupied(piece, nextCell, board, cellOccupyBlockers, player)) {
result.add(nextCell);
}
if (!moveFurtherCondition.canPieceMoveFurtherFromCell(piece, nextCell, board)) {
Expand All @@ -46,14 +49,17 @@ protected List<Cell> findAllNextMoves(Piece piece, NextCellProvider nextCellProv
return result;
}

private boolean checkIfCellCanBeOccupied(Piece piece, Cell cell, Board board, List<PieceCellOccupyBlocker> cellOccupyBlockers) {
for (PieceCellOccupyBlocker cellOccupyBlocker : cellOccupyBlockers) {
if (cellOccupyBlocker.isCellNonOccupiableForPiece(cell, piece, board)) {
private boolean checkIfCellCanBeOccupied(Piece piece, Cell cell, Board board, List<PieceCellOccupyBlocker> additionalBlockers, Player player) {
if (baseBlocker != null && baseBlocker.isCellNonOccupiableForPiece(cell, piece, board, player)) {
return false;
}
for (PieceCellOccupyBlocker cellOccupyBlocker : additionalBlockers) {
if (cellOccupyBlocker.isCellNonOccupiableForPiece(cell, piece, board, player)) {
return false;
}
}
return true;
}

protected abstract List<Cell> possibleMovesAsPerCurrentType(Piece piece, Board board, List<PieceCellOccupyBlocker> cellOccupyBlockers);
protected abstract List<Cell> possibleMovesAsPerCurrentType(Piece piece, Board board, List<PieceCellOccupyBlocker> additionalBlockers, Player player);
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,19 +6,20 @@
import com.uditagarwal.chess.model.Board;
import com.uditagarwal.chess.model.Cell;
import com.uditagarwal.chess.model.Piece;
import com.uditagarwal.chess.model.Player;

import java.util.List;

public class PossibleMovesProviderDiagonal extends PossibleMovesProvider {


public PossibleMovesProviderDiagonal(int maxSteps, MoveBaseCondition baseCondition,
PieceMoveFurtherCondition moveFurtherCondition) {
super(maxSteps, baseCondition, moveFurtherCondition);
PieceMoveFurtherCondition moveFurtherCondition, PieceCellOccupyBlocker baseBlocker) {
super(maxSteps, baseCondition, moveFurtherCondition, baseBlocker);
}

@Override
protected List<Cell> possibleMovesAsPerCurrentType(Piece piece, Board board, List<PieceCellOccupyBlocker> cellOccupyBlockers) {
protected List<Cell> possibleMovesAsPerCurrentType(Piece piece, Board board, List<PieceCellOccupyBlocker> additionalBlockers, Player player) {
return null;
}
}
Loading

0 comments on commit 22bc4dc

Please sign in to comment.