Java_Chess

.idea
    .name 5 B
    artifacts
       Chess_jar.xml 371 B
    compiler.xml 734 B
    copyright
    description.html 97 B
    encodings.xml 171 B
    libraries
       jansi_1_11.xml 214 B
    misc.xml 5 KB
    modules.xml 261 B
    project-template.xml 91 B
    scopes
       scope_settings.xml 143 B
    uiDesigner.xml 8 KB
    vcs.xml 176 B
    workspace.xml 61 KB
Chess.iml 1 KB
Doxyfile 101 KB
GUI_Manual_Testplan.pdf 437 KB
Graphics
    blackBerolinaPawn.png 1 KB
    blackBishop.png 5 KB
    blackKing.png 8 KB
    blackKnight.png 6 KB
    blackPawn.png 2 KB
    blackQueen.png 8 KB
    blackRook.png 3 KB
    blackWazir.png 1 KB
    whiteBerolinaPawn.png 2 KB
    whiteBishop.png 7 KB
    whiteKing.png 8 KB
    whiteKnight.png 7 KB
    whitePawn.png 4 KB
    whiteQueen.png 10 KB
    whiteRook.png 4 KB
    whiteWazir.png 2 KB
README 342 B
jansi-1.11.jar 111 KB
src
    CHANGES 1001 B
    GUI
       Controller.java 15 KB
       Main.java 360 B
       View.java 14 KB
       textPanel.java 776 B
    Game
       Board.java 5 KB
       CLI.java 5 KB
       Command.java 1022 B
       GameManager.java 11 KB
       GameType.java 74 B
       MoveHandler.java 1 KB
       Player.java 133 B
    META-INF
       MANIFEST.MF 53 B
    Main.java 154 B
    Pieces
       BerolinaPawn.java 1 KB
       Bishop.java 480 B
       BoardSquare.java 4 KB
       King.java 470 B
       Knight.java 846 B
       MoveType.java 530 B
       Pawn.java 1 KB
       Queen.java 474 B
       Rook.java 471 B
       Wazir.java 627 B
    TODO 176 B
    Tests
       BoardTest.java 2 KB
       GameManagerTest.java 21 KB
GameManager.java
package Game;

import Pieces.BoardSquare;

import java.util.Stack;

/**
 * @author      Nicholas Lochner    <nlochne2@illinois.edu>
 *
 * This class manages the game by keeping track of the current owner's turn, validating moves, and makes calls to the Game.Board to move pieces.
 */
public class GameManager {

    /**
     *The game board.
     */
    public Board gameBoard;

    /**
     *True if it is player 1's turn.<br>
     *False if it is player 2's turn.
     *
     */
    private Player playerTurn;

    private boolean ignoreTurn;//flag to ignore who's turn it is for check testing

    /**
     *This enum is used as a return value from the move functions.<br>
     * NONE: If the piece is moving to a blank square.<br>
     * CAPTURE: If this move would capture the opponent's piece.<br>
     * ERROR: The move can not be made.<br>
     */
    public enum MoveStatus {
        NONE, CAPTURE, ERROR
    }

    /**
     * Stack containing the move history.
     */
    public Stack MoveHist;

    private int moveCount = 0;

    /**
     * GameManager Constructor, sets up the game board and starting turn state.
     */
    public GameManager(GameType type){
        MoveHist = new Stack();
        gameBoard = new Board(8, 8, type);
        System.out.println("Setting up new game.\n");
        playerTurn = Player.WHITE;
        ignoreTurn = false;
    }

    /**
     * Undos the last move.
     *
     * @return true if the undo is successful, false otherwise.
     */
    public boolean undo(){

        if(!MoveHist.empty()){
            Command command = (Command) MoveHist.pop();

            BoardSquare startSquare = gameBoard.getPiece(command.destX, command.destY);
            BoardSquare destSquare = gameBoard.getPiece(command.sourceX, command.sourceY);

            //Player start_player = startSquare.owner;
            //Player dest_player = destSquare.owner;

            gameBoard.setPiece(destSquare.x, destSquare.y, startSquare, startSquare.owner);//Make the move
            gameBoard.setBlank(startSquare.x, startSquare.y);

            gameBoard.getPiece(command.sourceX, command.sourceY).hasMoved = command.hasMoved;

            if (currentTurn() == Player.BLACK) {
                moveCount--;
            }

            nextTurn();//Next owner's turn.

            return true;
        }

        return false;
    }


    /**
     * Adds a move to the history.
     * @param startX starting x-coordinate
     * @param startY starting y-coordinate.
     * @param destX destination x-coordinate.
     * @param destY destination y-coordinate.
     * @param startSquare starting square.
     */
    public void addToMoveHist(int startX, int startY, int destX, int destY, BoardSquare startSquare){

        //char xs = ((char) (startX + 97));
        char xEndChar = ((char) (destX + 97));

        String commandStr = "";

        if (currentTurn() == Player.WHITE) {
            moveCount++;
            commandStr += moveCount;
            commandStr += ". ";
        } else {
            commandStr += " ";
        }

        char symbol = startSquare.symbol;

        if (symbol != 'P' && symbol != ' ')
            commandStr += symbol;

        commandStr += xEndChar;
        commandStr += (destY + 1);

        Command command = new Command(startX, startY, destX, destY, startSquare.owner, startSquare.hasMoved, commandStr);
        MoveHist.push(command);
    }

    /**
     * Sets playerTurn to the next players turn.
     */
    public void nextTurn(){
        if(playerTurn == Player.WHITE)
            playerTurn = Player.BLACK;
        else
            playerTurn = Player.WHITE;
    }

    /**
     * Returns the player whose turn it is.
     * @return Returns the player whose turn it is.
     */
    public Player currentTurn() {
        return playerTurn;
    }

    /**
     * Attempt to move a Piece from (startX,startY) to (destX,destY).
     *
     * @param startX starting y-coordinate.
     * @param startY starting y-coordinate.
     * @param destX destination x-coordinate.
     * @param destY destination y-coordinate.
     *
     * @return Returns a MoveStatus enum.
     */
    public MoveStatus Move(int startX, int startY, int destX, int destY) {
        return MoveWrapped(startX, startY, destX, destY, false);//call wrapped function not testing for checkmate
    }

    /**
     * Helper function for move.
     *
     * @param startX starting y-coordinate.
     * @param startY starting y-coordinate.
     * @param destX destination x-coordinate.
     * @param destY destination y-coordinate.
     * @param testMate, true if testing for checkmate, false if testing for check.
     *
     * @return Returns a MoveStatus enum.
     */
    private MoveStatus MoveWrapped(int startX, int startY, int destX, int destY, boolean testMate) {
        if(startX<0 || startY<0 || startX>=gameBoard.width || startY>=gameBoard.height || destX<0 || destY<0 || destX>=gameBoard.width || destY>=gameBoard.height)
            return MoveStatus.ERROR;

        MoveStatus ret = validMove(startX, startY, destX, destY);
        if(ret != MoveStatus.ERROR) {
            //Check placement:
            BoardSquare startSquare = gameBoard.getPiece(startX, startY);
            BoardSquare destSquare = gameBoard.getPiece(destX, destY);

            if (attemptMove_andTestCheck(startSquare, destSquare, testMate) == false)
                return MoveStatus.ERROR;

            //Move succeeded.

            if(!testMate) {//if we were not checking for checkmate, it is the next players turn.

                addToMoveHist(startX, startY, destX,destY, startSquare);
                nextTurn();//Next player's turn.
            }
        }
        return ret;
    }

    /**
     * Tests the validity of a move.
     *
     * @param startX starting y-coordinate.
     * @param startY starting y-coordinate.
     * @param destX destination x-coordinate.
     * @param destY destination y-coordinate.
     *
     * @return Returns a MoveStatus enum.
     */
    public MoveStatus validMove(int startX, int startY, int destX, int destY) {
        if(startX<0 || startY<0 || startX>=gameBoard.width || startY>=gameBoard.height || destX<0 || destY<0 || destX>=gameBoard.width || destY>=gameBoard.height)
            return MoveStatus.ERROR;//return 0 if args are out of bounds.

        BoardSquare startSquare = gameBoard.getPiece(startX, startY);
        BoardSquare destSquare = gameBoard.getPiece(destX, destY);

        if(!ignoreTurn) {
            if (playerTurn == Player.WHITE && startSquare.owner != Player.WHITE)
                return MoveStatus.ERROR;//return 0 if it is not our turn.

            if (playerTurn == Player.BLACK && startSquare.owner != Player.BLACK)
                return MoveStatus.ERROR;
        }

        //Test moving the Piece

        if(!startSquare.MoveThis(gameBoard, startSquare, destSquare))
            return MoveStatus.ERROR;//move invalid

        return testPlacement(destSquare, startSquare);
    }


    /**
     * Tests placement of the Piece at sourceSquare, placing the Piece at x,y
     *
     * @param destSquare destination Pieces.BoardSquare
     * @param sourceSquare source Pieces.BoardSquare
     *
     * @return Returns a MoveStatus enum.
     */
    private MoveStatus testPlacement(BoardSquare destSquare, BoardSquare sourceSquare) {
        if(destSquare == null || sourceSquare == null)
            return MoveStatus.ERROR;

        if(sourceSquare.owner == destSquare.owner)
            return MoveStatus.ERROR;

        if(destSquare.owner == Player.NONE)
            return MoveStatus.NONE;

        return MoveStatus.CAPTURE;//Piece captured
    }

    /**
     * Additional helper function, After a move was determined valid, attempt the move and test for the check condition
     *
     * @param destSquare destination Pieces.BoardSquare
     * @param startSquare source Pieces.BoardSquare
     * @param testMate true if testing for checkmate, false otherwise.
     *
     * @return Returns a boolean if the move does not place the player into check.
     */
    private boolean attemptMove_andTestCheck(BoardSquare startSquare, BoardSquare destSquare, boolean testMate){

        Player start_player = startSquare.owner;
        Player dest_player = destSquare.owner;

        boolean startHasMoved = startSquare.hasMoved;

        gameBoard.setPiece(destSquare.x, destSquare.y, startSquare, startSquare.owner);//Make the move
        gameBoard.setBlank(startSquare.x, startSquare.y);

        //If this move places the owner in check, rollback.
        if(((testMate || testCheck(false) == start_player) && testCheck(false) != Player.NONE)) {//You can not make this move, it would place you in check.

            gameBoard.setPiece(destSquare.x, destSquare.y, destSquare, dest_player);
            gameBoard.setPiece(startSquare.x, startSquare.y, startSquare, start_player);

            gameBoard.getPiece(startSquare.x, startSquare.y).hasMoved = startHasMoved;//@todo refactor setting hasMoved

            return false;
        }

        //if the move is allowed, and we are testing for check, rollback since this was just a simulation
        if(testMate){
            gameBoard.setPiece(destSquare.x, destSquare.y, destSquare, dest_player);
            gameBoard.setPiece(startSquare.x, startSquare.y, startSquare, start_player);

            gameBoard.getPiece(startSquare.x, startSquare.y).hasMoved = startHasMoved;
        }

        return true;


    }

    /**
     * Test if the game situation is check or checkmate.
     *
     * @param testMate true if testing for checkmate, false if testing for check.
     *
     * @return Returns owner id of the owner in check or checkmate, else returns -1.
     */
    public Player testCheck(boolean testMate){

        if(!testMate)//If we are only checking for check, ignore who's turn it is to check ALL possible moves.
            ignoreTurn = true;

        for(int sx = 0; sx < gameBoard.width; sx++){
            for(int sy = 0; sy < gameBoard.height; sy++) {
                for(int x = 0; x < gameBoard.width; x++) {
                    for(int y = 0; y < gameBoard.height; y++) {

                        BoardSquare p = gameBoard.getPiece(x, y);
                        //If we are checking for checkmate, simulate a move for each Piece to see if the Pieces.King gets out of check.
                        if (testMate && MoveWrapped(sx, sy, x, y, testMate) != MoveStatus.ERROR) {
                            System.out.println("Not checkmate");
                            ignoreTurn = false;
                            return Player.NONE;

                            //If we are checking for check, call validMove for each Piece with the king as destination.
                        } else if (p.symbol == 'K' && validMove(sx, sy, x, y) != MoveStatus.ERROR) {
                            ignoreTurn = false;
                            return p.owner;
                        }

                    }
                }
            }
        }

        ignoreTurn = false;

        if(testMate) {//If we were checking for checkmate, return the owner who is in checkmate.
            return currentTurn();
        }

        return Player.NONE;

    }

    /**
     * Check if the game is in stale mate.
     *
     * @return returns true if the game is stale mate, false otherwise
     */
    public boolean testStalemate(){

        for(int sx = 0; sx < gameBoard.width; sx++){
            for(int sy = 0; sy < gameBoard.height; sy++) {
                for(int x = 0; x < gameBoard.width; x++) {
                    for(int y = 0; y < gameBoard.height; y++) {

                        if (MoveWrapped(sx, sy, x, y, true) != MoveStatus.ERROR) {
                            return false;
                        }

                    }
                }
            }
        }

        return true;

    }

}