Skip to content

Commit

Permalink
Support hurdles in path while moving
Browse files Browse the repository at this point in the history
  • Loading branch information
Udit Agarwal committed Jul 17, 2020
1 parent 927bbf6 commit 004181c
Show file tree
Hide file tree
Showing 19 changed files with 229 additions and 31 deletions.
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
.idea
*.iml
*.iml
target
5 changes: 5 additions & 0 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -27,5 +27,10 @@
<version>1.18.12</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>com.google.collections</groupId>
<artifactId>google-collections</artifactId>
<version>1.0</version>
</dependency>
</dependencies>
</project>
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package com.uditagarwal.chess.conditions;

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

/**
* 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);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package com.uditagarwal.chess.conditions;

import com.google.common.collect.ImmutableList;
import com.uditagarwal.chess.model.Piece;

import java.util.List;

public class PieceCellOccupyBlockerFactory {

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

public static List<PieceCellOccupyBlocker> kingCheckEvaluationBlockers() {
return ImmutableList.of(new PieceCellOccupyBlockerSelfPiece());
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
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;

/**
* 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) {
Cell pieceOriginalCell = piece.getCurrentCell();
piece.setCurrentCell(cell);
boolean playerGettingCheckByMove = board.isPlayerOnCheck(piece.getPlayer());
piece.setCurrentCell(pieceOriginalCell);
return playerGettingCheckByMove;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package com.uditagarwal.chess.conditions;

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

public class PieceCellOccupyBlockerSelfPiece implements PieceCellOccupyBlocker {

@Override
public boolean isCellNonOccupiableForPiece(Cell cell, Piece piece, Board board) {
if (cell.isFree()) {
return false;
}
return cell.getCurrentPiece().getColor() == piece.getColor();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package com.uditagarwal.chess.conditions;

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

public interface PieceMoveFurtherCondition {

boolean canPieceMoveFurtherFromCell(Piece piece, Cell cell, Board board);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package com.uditagarwal.chess.conditions;

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

public class PieceMoveFurtherConditionDefault implements PieceMoveFurtherCondition {

@Override
public boolean canPieceMoveFurtherFromCell(Piece piece, Cell cell, Board board) {
return cell.isFree();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
package com.uditagarwal.chess.exceptions;

public class PieceNotFoundException extends RuntimeException {
}
24 changes: 24 additions & 0 deletions src/main/java/com/uditagarwal/chess/model/Board.java
Original file line number Diff line number Diff line change
@@ -1,9 +1,14 @@
package com.uditagarwal.chess.model;

import com.uditagarwal.chess.conditions.PieceCellOccupyBlocker;
import com.uditagarwal.chess.conditions.PieceCellOccupyBlockerFactory;
import com.uditagarwal.gameplay.Player;
import lombok.Getter;

import java.util.List;

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

@Getter
public class Board {
int boardSize;
Expand Down Expand Up @@ -40,4 +45,23 @@ public Cell getCellAtLocation(int x, int y) {

return cells[x][y];
}

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

public boolean checkIfPieceCanBeKilled(Piece targetPiece, List<PieceCellOccupyBlocker> cellOccupyBlockers) {
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 (nextPossibleCells.contains(targetPiece.getCurrentCell())) {
return true;
}
}
}
}
return false;
}
}
3 changes: 3 additions & 0 deletions src/main/java/com/uditagarwal/chess/model/Cell.java
Original file line number Diff line number Diff line change
Expand Up @@ -16,4 +16,7 @@ public class Cell {
private Piece currentPiece;


public boolean isFree() {
return currentPiece == null;
}
}
30 changes: 22 additions & 8 deletions src/main/java/com/uditagarwal/chess/model/Piece.java
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
package com.uditagarwal.chess.model;

import com.uditagarwal.chess.conditions.PieceCellOccupyBlocker;
import com.uditagarwal.chess.exceptions.InvalidMoveException;
import com.uditagarwal.chess.moves.PossibleMovesProvider;
import com.uditagarwal.gameplay.Player;
import lombok.Getter;
import lombok.NonNull;
import sun.jvm.hotspot.gc.shared.Generation;
import lombok.Setter;

import java.util.ArrayList;
import java.util.List;
Expand All @@ -14,23 +16,32 @@ public class Piece {
private boolean isKilled = false;
private final Color color;
private final List<PossibleMovesProvider> movesProviders;
private Cell currentCell;
private Integer numMoves = 0;
Player player;
PieceType pieceType;

@Setter
@NonNull
private Cell currentCell;

public Piece(@NonNull final Color color, @NonNull final List<PossibleMovesProvider> movesProviders) {
public Piece(@NonNull final Color color, @NonNull final List<PossibleMovesProvider> movesProviders,
@NonNull final Player player, @NonNull final PieceType pieceType, @NonNull final Cell currentCell) {
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) {
public void move(Cell toCell, Board board, List<PieceCellOccupyBlocker> cellOccupyBlockers) {
if (isKilled) {
throw new InvalidMoveException();
}
List<Cell> nextPossibleCells = nextPossibleCells(board);
List<Cell> nextPossibleCells = nextPossibleCells(board, cellOccupyBlockers);
if (!nextPossibleCells.contains(toCell)) {
throw new InvalidMoveException();
}
Expand All @@ -42,20 +53,23 @@ public void move(Cell toCell, Board board) {
}

private void killPieceInCell(Cell targetCell) {
//TODO: use killing strategy here and also check that piece here should be of opponent.
if (targetCell.getCurrentPiece() != null) {
targetCell.getCurrentPiece().killIt();
}
}

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

public boolean isPieceFromSamePlayer(Piece piece) {
return piece.getPlayer().equals(this.player);
}
}
10 changes: 10 additions & 0 deletions src/main/java/com/uditagarwal/chess/model/PieceType.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package com.uditagarwal.chess.model;

public enum PieceType {
KING,
QUEEN,
ROOK,
KNIGHT,
BISHOP,
PAWN
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
package com.uditagarwal.chess.moves;

import com.uditagarwal.chess.conditions.PieceCellOccupyBlocker;
import com.uditagarwal.chess.conditions.PieceMoveFurtherCondition;
import com.uditagarwal.chess.model.Board;
import com.uditagarwal.chess.model.Cell;
import com.uditagarwal.chess.model.Piece;
Expand All @@ -14,30 +16,47 @@ interface NextCellProvider {
public abstract class PossibleMovesProvider {
int maxSteps;
MoveBaseCondition baseCondition;
PieceMoveFurtherCondition moveFurtherCondition;

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

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

protected List<Cell> findAllNextMoves(Cell startCell, NextCellProvider nextCellProvider) {
protected List<Cell> findAllNextMoves(Piece piece, NextCellProvider nextCellProvider, Board board, List<PieceCellOccupyBlocker> cellOccupyBlockers) {
List<Cell> result = new ArrayList<>();
Cell nextCell = nextCellProvider.nextCell(startCell);
Cell nextCell = nextCellProvider.nextCell(piece.getCurrentCell());
int numSteps = 1;
while (nextCell != null && numSteps <= maxSteps) {
result.add(nextCell);
if (checkIfCellCanBeOccupied(piece, nextCell, board, cellOccupyBlockers)) {
result.add(nextCell);
}
if (!moveFurtherCondition.canPieceMoveFurtherFromCell(piece, nextCell, board)) {
break;
}

nextCell = nextCellProvider.nextCell(nextCell);
numSteps++;
}
return result;
}

protected abstract List<Cell> possibleMovesAsPerCurrentType(Piece piece, Board board);
private boolean checkIfCellCanBeOccupied(Piece piece, Cell cell, Board board, List<PieceCellOccupyBlocker> cellOccupyBlockers) {
for (PieceCellOccupyBlocker cellOccupyBlocker : cellOccupyBlockers) {
if (cellOccupyBlocker.isCellNonOccupiableForPiece(cell, piece, board)) {
return false;
}
}
return true;
}

protected abstract List<Cell> possibleMovesAsPerCurrentType(Piece piece, Board board, List<PieceCellOccupyBlocker> cellOccupyBlockers);
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
package com.uditagarwal.chess.moves;

import com.uditagarwal.chess.conditions.PieceCellOccupyBlocker;
import com.uditagarwal.chess.conditions.PieceMoveFurtherCondition;
import com.uditagarwal.chess.model.Board;
import com.uditagarwal.chess.model.Cell;
import com.uditagarwal.chess.model.Piece;
Expand All @@ -8,12 +10,14 @@

public class PossibleMovesProviderDiagonal extends PossibleMovesProvider {

public PossibleMovesProviderDiagonal(int maxSteps, MoveBaseCondition baseCondition) {
super(maxSteps, baseCondition);

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

@Override
protected List<Cell> possibleMovesAsPerCurrentType(Piece piece, Board board) {
protected List<Cell> possibleMovesAsPerCurrentType(Piece piece, Board board, List<PieceCellOccupyBlocker> cellOccupyBlockers) {
return null;
}
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
package com.uditagarwal.chess.moves;

import com.uditagarwal.chess.conditions.PieceCellOccupyBlocker;
import com.uditagarwal.chess.conditions.PieceMoveFurtherCondition;
import com.uditagarwal.chess.model.Board;
import com.uditagarwal.chess.model.Cell;
import com.uditagarwal.chess.model.Piece;
Expand All @@ -9,14 +11,15 @@

public class PossibleMovesProviderHorizontal extends PossibleMovesProvider {

public PossibleMovesProviderHorizontal(int maxSteps, MoveBaseCondition baseCondition) {
super(maxSteps, baseCondition);
public PossibleMovesProviderHorizontal(int maxSteps, MoveBaseCondition baseCondition,
PieceMoveFurtherCondition moveFurtherCondition) {
super(maxSteps, baseCondition, moveFurtherCondition);
}

protected List<Cell> possibleMovesAsPerCurrentType(Piece piece, final Board board) {
protected List<Cell> possibleMovesAsPerCurrentType(Piece piece, final Board board, List<PieceCellOccupyBlocker> cellOccupyBlockers) {
List<Cell> result = new ArrayList<>();
result.addAll(findAllNextMoves(piece.getCurrentCell(), board::getLeftCell));
result.addAll(findAllNextMoves(piece.getCurrentCell(), board::getRightCell));
result.addAll(findAllNextMoves(piece, board::getLeftCell, board, cellOccupyBlockers));
result.addAll(findAllNextMoves(piece, board::getRightCell, board, cellOccupyBlockers));
return result;
}
}
Loading

0 comments on commit 004181c

Please sign in to comment.