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

Adding checks #78

Merged
merged 5 commits into from
Nov 3, 2019
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
168 changes: 166 additions & 2 deletions rollerball/src/main/java/game/ChessBoard.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
package game;

import java.util.ArrayList;

public class ChessBoard {
private ChessPiece[][] board;

Expand Down Expand Up @@ -47,7 +49,8 @@ public boolean placePiece(ChessPiece piece, String position){
return false;
try{
ChessPiece destinationPiece = getPiece(position);
if(destinationPiece == null || destinationPiece.getColor() != piece.getColor()) {
//System.out.println("hi");
if(destinationPiece == null || destinationPiece.getColor() != piece.getColor()) { //if destination is empty or an opponents piece
piece.setPosition(position);
int[] indexes = positionToIndexes(position);
board[indexes[0]][indexes[1]] = piece;
Expand All @@ -59,6 +62,157 @@ public boolean placePiece(ChessPiece piece, String position){
}
}

//returns the position of the king of the same color of the moving piece
//this is assuming that piece is moving to position
private String getKingLocation(ChessPiece piece, String position)
{
String kpos = "";
if (piece instanceof King)
{
kpos = position;
}
else
{
kpos = getKingLocation(piece.getColor()); //position of the king doesnt change based on the move, so can use a simpler searcher
}
return kpos;
}

private String getKingLocation(ChessPiece.Color color)
{
for (int k = 0; k < board.length; k++)
{
for (int j = 0; j < board.length; j++)
{
if (board[k][j] != null && board[k][j] instanceof King && board[k][j].getColor() == color)
{
return board[k][j].getPosition();
}
}
}
return "";
}

//returns the validity of the move if the moving king is in check, or the move puts them in check
//this is assuming that piece is moving to position
private boolean king_in_check(ChessPiece piece, String position)
{
try
{
String kpos = getKingLocation(piece, position); //location of the king
String oldPos = piece.getPosition();
ChessPiece capPiece = getPiece(position);
//System.out.println(kpos);
if(!placePiece(piece, position)) //need to update the board first
{
//System.out.println("huh?");
return false; //move wasnt legal for other reasons...
}
int[] fromIndexes = positionToIndexes(oldPos);
board[fromIndexes[0]][fromIndexes[1]] = null;

boolean ret = false;
if (king_in_check(piece.getColor(), kpos))
{
System.out.println("this move is invalid");
ret = true;
}
placePiece(piece, oldPos); //undo the update to not change the state of the board
fromIndexes = positionToIndexes(position);
board[fromIndexes[0]][fromIndexes[1]] = capPiece; //put the possibly captured piece back

return ret;
}
catch (IllegalPositionException e)
{
//System.out.println("hi");
return false;
}
}

private boolean king_in_check(ChessPiece.Color color, String kpos)
{
for (int k = 0; k < board.length; k++)
{
for (int j = 0; j < board[k].length; j++) //going over the whole board to find all of the enemies pieces
{
ChessPiece checker = board[k][j]; //possible enemy piece
if (checker != null && checker.getColor() != color) //checker is an enemy piece
{
ArrayList<String> checkerMoves = checker.legalMoves();
for (String move : checkerMoves) //go through their legal moves to see if they can capture the king
{
if (move.equals(kpos)) //if they can, the king is in check and the move is illegal.
{
return true;
}
}
}
}
}
return false;
}

//returns true if the game is over (win or draw), false otherwise
//piece is the moving piece (so the winning piece)
private boolean game_is_over(ChessPiece piece)
{
if (game_is_won(piece))
{
return true;
}
else if (game_is_draw(piece))
{
return true;
}
return false; //the game can never end Chell...
}

//returns true if the player opposite piece is in checkmate, false otherwise
private boolean game_is_won(ChessPiece piece)
{
if(game_is_stalemate(piece)) //opposing team cant move
{
ChessPiece.Color losing_color = piece.getColor() == ChessPiece.Color.WHITE ? ChessPiece.Color.BLACK : ChessPiece.Color.WHITE;
if (king_in_check(losing_color, getKingLocation(losing_color)))
{
return true; //no legal moves, and king is in check, therefore checkmate
}
}
return false;
}

private boolean game_is_draw(ChessPiece piece)
{
return game_is_stalemate(piece); //for now, lets only support stalemate
//if we want we could check for three fold repitition, but that sounds difficult
}

private boolean game_is_stalemate(ChessPiece piece)
{
for (int k = 0; k < board.length; k++)
{
for (int j = 0; j < board[k].length; j++)
{
ChessPiece mover = board[k][j];
if (mover != null && mover.getColor() != piece.getColor()) //mover is on the possibly losing team
{
ArrayList<String> moves = mover.legalMoves();
for (String move : moves)
{
if (!king_in_check(mover, move))
{
return false; //the losing team has at least this move
}
}
}
}
}
return true; //no moves were found for the next turn, therefore it is stalemate.
}



public void move(String from, String to) throws IllegalMoveException{
try {
ChessPiece fromPiece = getPiece(from);
Expand All @@ -68,9 +222,19 @@ public void move(String from, String to) throws IllegalMoveException{
if(!fromPiece.legalMoves().contains(to)){
throw new IllegalMoveException("Second argument must be a valid move.");
}
if (king_in_check(fromPiece, to))
{
throw new IllegalMoveException("Your king is in check!");
}
if(placePiece(fromPiece, to)){
int[] fromIndexes = positionToIndexes(from);
board[fromIndexes[0]][fromIndexes[1]] = null;
board[fromIndexes[0]][fromIndexes[1]] = null; //move has been made
//if(game_is_over(fromPiece)) //commented out because it does nothing
{
//how do we want to handle this?
//personally I want to change the return type and handle it above
//perhaps to a boolean true if the game is over, false otherwise
}
}
else {
throw new IllegalMoveException("Invalid move.");
Expand Down
24 changes: 23 additions & 1 deletion rollerball/src/test/java/game/ChessBoardTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -96,5 +96,27 @@ void move() throws IllegalPositionException {

}

@Test
void moveCheck() throws IllegalMoveException {
board.placePiece(new King(board, ChessPiece.Color.WHITE), "b4");
board.placePiece(new Bishop(board, ChessPiece.Color.WHITE), "f3");
board.placePiece(new King(board, ChessPiece.Color.BLACK), "b6");
board.placePiece(new Rook(board, ChessPiece.Color.BLACK), "b2");

assertThrows(IllegalMoveException.class, ()->board.move("f3", "d1"));
assertDoesNotThrow(()-> board.move("b4", "a3"));
}

@Test
void moveCheckPin() throws IllegalMoveException {
board.placePiece(new King(board, ChessPiece.Color.WHITE), "a1");
board.placePiece(new Pawn(board, ChessPiece.Color.WHITE), "b1");
board.placePiece(new King(board, ChessPiece.Color.BLACK), "a5");
board.placePiece(new Rook(board, ChessPiece.Color.BLACK), "f4");

assertDoesNotThrow(()-> board.move("f4", "f1")); //move should allow this, as black is not in check
assertThrows(IllegalMoveException.class, ()->board.move("b1", "a2")); //should not allow this, as it would put white in check
}


}
}