diff --git a/justcheckers/game/board.py b/justcheckers/game/board.py index 1dc7955..f5bde17 100644 --- a/justcheckers/game/board.py +++ b/justcheckers/game/board.py @@ -17,477 +17,342 @@ # Please share and enjoy! # -/** - * Container for the state of the checker board during a game. - * - * The size of the board is defined by the number of squares along one side, - * since all checker boards are square. The board coordinate system has both - * horizontal and vertical numeric components ranging from 0 to boardSize-1. - * Depicted on-screen, the horizontal component extends to the right and the - * vertical component extends downwards, making the upper left square (0, 0) and - * the lower right square (boardSize-1, boardSize-1). - * - * Navigating through the Board Internally, the checker board is - * organized as a two-dimensional array. So when iterating through the board, - * you first specify the vertical component and then the horizontal component. - * Another way of thinking about is first specifying which row you want to look - * at from top to bottom. Then you specify how across the row you are looking at - * from left to right. - * - * Players Places The light player (the starting player) starts at the - * top of the board. The dark player starts at the bottom of the board. - * - * @author Dorian Pula - * @author Ross Etchells - */ -public class Board { +from enum import Enum - /** Constant representing a dark king. */ - public static final int DARK_KING = 4; - /** Constant representing a dark single man. */ - public static final int DARK_PAWN = 3; - /** Constant representing an empty space. */ - public static final int EMPTY_SPACE = 0; - // -- Constants ------------------------------------------------------------ - /** - * Constant representing an illegal square. That is a white square in - * checkers. - */ - public static final int ILLEGAL_SPACE = -1; - /** Constant representing a light king. */ - public static final int LIGHT_KING = 2; - /** Constant representing a light single man. */ - public static final int LIGHT_PAWN = 1; +from justcheckers.game import rules - // -- Object Fields -------------------------------------------------------- - /** Is the board mirrored or a regular checker board. */ - private final boolean amIMirrored; - /** - * Holds the positions of the pieces on the board. - */ - private final int[][] board; - /** The size of the board. */ - private final int boardSize; - /** A reference to the rules being used. */ - private final Rulebook myRules; +class Square(Enum): + """Represents the state of a single square on a checkerboard.""" + WHITE = -1 + EMPTY = 0 + LIGHT_PAWN = 1 + LIGHT_KING = 2 + DARK_PAWN = 3 + DARK_KING = 4 - // -- Constructors --------------------------------------------------------- - /** - * Creates a new board for checkers. - * - * @param rules - * The rules for this board. - */ - public Board(Rulebook rules) { - this.myRules = rules; - final int size = this.myRules.getBoardSize(); - this.board = new int[size][size]; - this.boardSize = size; - this.amIMirrored = this.myRules.isBoardMirrored(); - } - // -- Public Methods (Setting Up the Board) -------------------------------- - /** - * Clears the board of pieces. Creates a brand new empty board already laid - * out by the rules (regular or mirrored). - */ - public void clearBoard() { - for (int row = 0; this.boardSize > row; row++) { - for (int col = 0; this.boardSize > col; col++) { +class Board(object): + """ + * Container for the state of the checker board during a game. + * + * The size of the board is defined by the number of squares along one side, + * since all checker boards are square. The board coordinate system has both + * horizontal and vertical numeric components ranging from 0 to boardSize-1. + * Depicted on-screen, the horizontal component extends to the right and the + * vertical component extends downwards, making the upper left square (0, 0) and + * the lower right square (boardSize-1, boardSize-1). + * + * Navigating through the Board Internally, the checker board is + * organized as a two-dimensional array. So when iterating through the board, + * you first specify the vertical component and then the horizontal component. + * Another way of thinking about is first specifying which row you want to look + * at from top to bottom. Then you specify how across the row you are looking at + * from left to right. + * + * Players Places The light player (the starting player) starts at the + * top of the board. The dark player starts at the bottom of the board. + * + * @author Dorian Pula + * @author Ross Etchells + """ - // Mirrored has opposite setup to a regular board. - if (row % 2 == 0 && col % 2 == 0) { - if (this.amIMirrored) { - this.board[row][col] = Board.ILLEGAL_SPACE; - } else { - this.board[row][col] = Board.EMPTY_SPACE; - } - } else if (row % 2 == 0 && col % 2 == 1) { - if (this.amIMirrored) { - this.board[row][col] = Board.EMPTY_SPACE; - } else { - this.board[row][col] = Board.ILLEGAL_SPACE; - } - } else if (row % 2 == 1 && col % 2 == 0) { - if (this.amIMirrored) { - this.board[row][col] = Board.EMPTY_SPACE; - } else { - this.board[row][col] = Board.ILLEGAL_SPACE; - } - } else { - if (this.amIMirrored) { - this.board[row][col] = Board.ILLEGAL_SPACE; - } else { - this.board[row][col] = Board.EMPTY_SPACE; - } - } + def __init__(self, size=rules.Rules.STANDARD_BOARD_SIZE, mirrored=False): + self.board_size = size + self._board = [[]] - } - } - } + # /** + # * Clears the board of pieces. Creates a brand new empty board already laid + # * out by the rules (regular or mirrored). + # */ + for row in xrange(0, size): + for col in xrange(0, size): - // -- Get/Set Methods ------------------------------------------------------ - /** - * Gets the size of the board. The board size is measured as the number of - * squares down one side of the board. - * - * @return The size of the board. - */ - public int getBoardSize() { - return this.boardSize; - } + # Mirrored has opposite setup to a regular board. + if (row % 2 == 0) and (col % 2 == 0): + if mirrored: + self._board[row][col] = Square.WHITE + else: + self._board[row][col] = Square.EMPTY - /** - * Provides a reference to a 2 dimensional array representation of the - * current board state. This is for use by the user interface. Each - * dimension of the array extends from 0 to boardSize - 1. Note that the - * referenced array is a clone of the internal board representation. Changes - * made to the array will not affect the board state. - * - * @return A 2 dimensional array representing the current state of the - * board. - */ - public int[][] getBoardState() { - final int[][] repBoard = new int[this.boardSize][this.boardSize]; - System.arraycopy(this.board, 0, repBoard, 0, this.boardSize); - return repBoard; - } + elif (row % 2 == 0) and (col % 2 == 1): + if mirrored: + self._board[row][col] = Square.EMPTY + else: + self._board[row][col] = Square.WHITE - /** - * Determines whether the piece at board coordinate (row, col) is dark. If - * the coordinates do not exist on the board or are empty, this method will - * return false. - * - * @param row - * The row of the square. - * @param col - * The column of the square. - * @return True if the piece at the specified coordinate is dark. False if - * otherwise. - */ - public boolean isDark(int row, int col) { - if (row >= 0 && row < this.boardSize && col >= 0 - && col < this.boardSize) { - return this.board[row][col] == Board.DARK_KING - || this.board[row][col] == Board.DARK_PAWN; - } - return false; - } + elif (row % 2 == 1) and (col % 2 == 0): + if mirrored: + self._board[row][col] = Square.EMPTY + else: + self._board[row][col] = Square.WHITE + else: + if mirrored: + self._board[row][col] = Square.WHITE + else: + self._board[row][col] = Square.EMPTY - /** - * Determines whether the piece at board coordinate (row, col) is empty. If - * the coordinates do not exist on the board or is illegal, this method will - * return false. - * - * @param row - * The row of the square. - * @param col - * The column of the square. - * @return True if the piece at the specified coordinate is empty. False if - * otherwise. - */ - public boolean isEmpty(int row, int col) { - if (row >= 0 && row < this.boardSize && col >= 0 - && col < this.boardSize) { - return this.board[row][col] == Board.EMPTY_SPACE; - } - return false; - } + def is_inside_board(self, row, col): + return (0 <= row < self.board_size) and (0 <= col < self.board_size) - /** - * Determines whether the board coordinate (x, y) is used in the game. In - * most cases, all light spaces on the board will be considered illegal. - * Also, any coordinate which does not exist is also considered illegal. - * - * @param row - * The row of the square. - * @param col - * The column of the square. - * @return True if the specified coordinate is nonexistent or unused in the - * current rules. False if otherwise. - */ - public boolean isIllegalSpace(int row, int col) { - if (row >= 0 && row < this.boardSize && col >= 0 - && col < this.boardSize) { - return this.board[row][col] == Board.ILLEGAL_SPACE; - } - return false; - } + def is_dark(self, row, col): + """ + /** + * Determines whether the piece at board coordinate (row, col) is dark. If + * the coordinates do not exist on the board or are empty, this method will + * return false. + * + * @param row + * The row of the square. + * @param col + * The column of the square. + * @return True if the piece at the specified coordinate is dark. False if + * otherwise. + */ + """ + return self.is_inside_board(row, col) and self._board[row][col] in [Square.DARK_KING, Square.DARK_PAWN] - /** - * Determines whether the piece at board coordinate (row, col) is a king. If - * the coordinates do not exist on the board or are empty, this method will - * return false. - * - * @param row - * The row of the square. - * @param col - * The column of the square. - * @return True if the piece at the specified coordinate is a king. False if - * otherwise. - */ - public boolean isKing(int row, int col) { - if (row >= 0 && row < this.boardSize && col >= 0 - && col < this.boardSize) { - return this.board[row][col] == Board.LIGHT_KING - || this.board[row][col] == Board.DARK_KING; - } - return false; - } + def is_empty(self, row, col): + """ + /** + * Determines whether the piece at board coordinate (row, col) is empty. If + * the coordinates do not exist on the board or is illegal, this method will + * return False. + * + * @param row + * The row of the square. + * @param col + * The column of the square. + * @return True if the piece at the specified coordinate is empty. False if + * otherwise. + */ + """ + return self.is_inside_board(row, col) and self._board[row][col] == Square.EMPTY - /** - * Returns if a position specified is legal. Returns true if the position is - * on the board, and if the space is not an illegal white space. Returns - * false otherwise. - * - * @param row - * The row coordinate of the position. - * @param col - * The column coordinate of the position. - * @return Returns true if the position is a legal playing position. - */ - public boolean isLegalPosition(int row, int col) { - return row >= 0 && row < this.boardSize && col >= 0 - && col < this.boardSize && !this.isIllegalSpace(row, col); - } + def is_illegal_space(self, row, col): + """ + /** + * Determines whether the board coordinate (x, y) is used in the game. In + * most cases, all light spaces on the board will be considered illegal. + * Also, any coordinate which does not exist is also considered illegal. + * + * @param row + * The row of the square. + * @param col + * The column of the square. + * @return True if the specified coordinate is nonexistent or unused in the + * current rules. False if otherwise. + */ + """ + return self.is_inside_board(row, col) and self._board[row][col] == Square.WHITE - /** - * Determines whether the piece at board coordinate (row, col) is light. If - * the coordinates do not exist on the board or are empty, this method will - * return false. - * - * @param row - * The row of the square. - * @param col - * The column of the square. - * @return True if the piece at the specified coordinate is light. False if - * otherwise. - */ - public boolean isLight(int row, int col) { - if (row >= 0 && row < this.boardSize && col >= 0 - && col < this.boardSize) { - return this.board[row][col] == Board.LIGHT_KING - || this.board[row][col] == Board.LIGHT_PAWN; - } - return false; - } + # /** + # * Determines whether the piece at board coordinate (row, col) is a king. If + # * the coordinates do not exist on the board or are empty, this method will + # * return False. + # * + # * @param row + # * The row of the square. + # * @param col + # * The column of the square. + # * @return True if the piece at the specified coordinate is a king. False if + # * otherwise. + # */ + def is_king(self, row, col): + return self.is_inside_board(row, col) and self._board[row][col] in [Square.LIGHT_KING, Square.DARK_KING] - /** - * Determines whether the piece at board coordinate (row, col) is a pawn. If - * the coordinates do not exist on the board or are empty, this method will - * return false. - * - * @param row - * The row of the square. - * @param col - * The column of the square. - * @return True if the piece at the specified coordinate is a pawn. False if - * otherwise. - */ - public boolean isPawn(int row, int col) { - if (row >= 0 && row < this.boardSize && col >= 0 - && col < this.boardSize) { - return this.board[row][col] == Board.LIGHT_PAWN - || this.board[row][col] == Board.DARK_PAWN; - } - return false; - } + # /** + # * Returns if a position specified is legal. Returns true if the position is + # * on the board, and if the space is not an illegal white space. Returns + # * False otherwise. + # * + # * @param row + # * The row coordinate of the position. + # * @param col + # * The column coordinate of the position. + # * @return Returns true if the position is a legal playing position. + # */ + def is_legal_position(self, row, col): + return self.is_inside_board(row, col) and not self.is_illegal_space(row, col) - // -- Board Updating Methods ----------------------------------------------- - /** - * Moves a pieces from one location to another. This method should be called - * from the Game using this Board. This method does not check for rule - * validity but does check for illegal white spaces. Also checks that the - * destination position is empty. - * - * @param sourceRow - * The row from where the piece is moving from. - * @param sourceCol - * The column from where the piece is moving from. - * @param targetRow - * The row to where the piece is moving to. - * @param targetCol - * The column to where the piece is moving to. - */ - protected void movePiece(int sourceRow, int sourceCol, int targetRow, - int targetCol) { + # /** + # * Determines whether the piece at board coordinate (row, col) is light. If + # * the coordinates do not exist on the board or are empty, this method will + # * return False. + # * + # * @param row + # * The row of the square. + # * @param col + # * The column of the square. + # * @return True if the piece at the specified coordinate is light. False if + # * otherwise. + # */ + def is_light(self, row, col): + return self.is_inside_board(row, col) and self._board[row][col] in [Square.LIGHT_KING, Square.LIGHT_PAWN] - if (this.isLegalPosition(sourceRow, sourceCol) - && this.isLegalPosition(targetRow, targetCol) - && this.board[targetRow][targetCol] == Board.EMPTY_SPACE) { + # /** + # * Determines whether the piece at board coordinate (row, col) is a pawn. If + # * the coordinates do not exist on the board or are empty, this method will + # * return False. + # * + # * @param row + # * The row of the square. + # * @param col + # * The column of the square. + # * @return True if the piece at the specified coordinate is a pawn. False if + # * otherwise. + # */ + def is_pawn(self, row, col): + return self.is_inside_board(row, col) and self._board[row][col] in [Square.LIGHT_PAWN, Square.DARK_PAWN] - final int piece = this.board[sourceRow][sourceCol]; - this.board[targetRow][targetCol] = piece; - this.board[sourceRow][sourceCol] = Board.EMPTY_SPACE; + # /** + # * Moves a pieces from one location to another. This method should be called + # * from the Game using this Board. This method does not check for rule + # * validity but does check for illegal white spaces. Also checks that the + # * destination position is empty. + # * + # * @param sourceRow + # * The row from where the piece is moving from. + # * @param sourceCol + # * The column from where the piece is moving from. + # * @param targetRow + # * The row to where the piece is moving to. + # * @param targetCol + # * The column to where the piece is moving to. + # */ + def move_piece(self, source_row, source_col, target_row, target_col): - } - } + if (self.is_legal_position(source_row, source_col) + and self.is_legal_position(target_row, target_col) + and self._board[target_row][target_col] == Square.EMPTY): - /** - * Removes a pieces from the specified location. This method should be - * called from the Game using this Board. This method does not check for - * rule validity but does check for illegal white spaces. - * - * @param row - * The row where the piece is to be removed from. - * @param col - * The column where the piece is to be removed from. - */ - protected void removePiece(int row, int col) { + self._board[source_row][source_col], self._board[target_row][target_col] = ( + Square.EMPTY, self._board[source_row][source_col]) - if (this.isLegalPosition(row, col)) { - this.board[row][col] = Board.EMPTY_SPACE; - } - } + # /** + # * Removes a pieces from the specified location. This method should be + # * called from the Game using this Board. This method does not check for + # * rule validity but does check for illegal white spaces. + # * + # * @param row + # * The row where the piece is to be removed from. + # * @param col + # * The column where the piece is to be removed from. + # */ + def remove_piece(self, row, col): + if self.is_legal_position(row, col): + self._board[row][col] = Square.EMPTY - /** - * Setups the board for a new game. There are three different setups for the - * three different types of boards: - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - *
NameSizeNumber of Pieces Per PlayerNumber of Rows Per Player
Standard8 x 8123
International10 x 10204
Canadian12 x 12305
- * - * The columns containing the players' tokens alternate between columns. The - * dark player traditionally takes the first few upper rows (0-3). The light - * player takes the last of the lower rows (5-7, 6-9 or 7-11). - * - * Note that the suicide checkers variant has a completely different setup, - * and has a setup function of its own: setupNewSuicideGame(). - */ - public void setupNewGame() { - this.clearBoard(); + # /** + # * Setups the board for a new game. There are three different setups for the + # * three different types of boards: + # * + # * + # * + # * + # * + # * + # * + # * + # * + # * + # * + # * + # * + # * + # * + # * + # * + # * + # * + # * + # * + # * + # * + # * + # * + # * + # * + # * + # *
NameSizeNumber of Pieces Per PlayerNumber of Rows Per Player
Standard8 x 8123
International10 x 10204
Canadian12 x 12305
+ # * + # * The columns containing the players' tokens alternate between columns. The + # * dark player traditionally takes the first few upper rows (0-3). The light + # * player takes the last of the lower rows (5-7, 6-9 or 7-11). + # * + # * Note that the suicide checkers variant has a completely different setup, + # * and has a setup function of its own: setupNewSuicideGame(). + # */ + def setup_new_game(self): - if (this.myRules.getCheckersVariant() == Rulebook.SUICIDE_CHECKERS) { - this.setupNewSuicideGame(); - } else { + # Used to decide which rows to fill up. + # Figure out the size of the board. + if self.board_size == rules.InternationalRules.INTERNATIONAL_BOARD_SIZE: + dark_player_bottom_row = 3 + light_player_top_row = 6 + elif self.board_size == rules.CanadianRules.CANADIAN_BOARD_SIZE: + dark_player_bottom_row = 3 + light_player_top_row = 7 + else: + # Default board is 8x8 Standard size. + dark_player_bottom_row = 2 + light_player_top_row = 5 - // Used to decide which rows to fill up. - int darkPlayerBottomRow; - int lightPlayerTopRow; + # Go through the board and set it up. + for row in xrange(0, self.board_size): + for col in xrange(0, self.board_size): + if row <= dark_player_bottom_row and self._board[row][col] == Square.EMPTY: + self._board[row][col] = Square.DARK_PAWN + elif row >= light_player_top_row and self._board[row][col] == Square.EMPTY: + self._board[row][col] = Square.LIGHT_PAWN - // Figure out the size of the board. - if (this.boardSize == Rulebook.INTERNATIONAL_BOARD_SIZE) { - darkPlayerBottomRow = 3; - lightPlayerTopRow = 6; - } else if (this.boardSize == Rulebook.CANADIAN_BOARD_SIZE) { - darkPlayerBottomRow = 3; - lightPlayerTopRow = 7; - } else { // Default board is 8x8 Standard size. - darkPlayerBottomRow = 2; - lightPlayerTopRow = 5; - } + # /** + # * Setups a checker board according to the suicide "French" rules. + # */ + def setup_new_suicide_game(self): + # TODO: Implement the suicide game setup. + pass - // Go through the board and set it up. - for (int row = 0; row < this.boardSize; row++) { - for (int col = 0; col < this.boardSize; col++) { - if (row <= darkPlayerBottomRow - && this.board[row][col] == Board.EMPTY_SPACE) { - this.board[row][col] = Board.DARK_PAWN; - } else if (row >= lightPlayerTopRow - && this.board[row][col] == Board.EMPTY_SPACE) { - this.board[row][col] = Board.LIGHT_PAWN; - } - } - } + # /** + # * Returns a string to represent the board state. This string is formatted + # * for use as a simple board display in the command window. + # * + # * Legend ## - White space which the piece can not move on to. __ - + # * An empty space. LP - A light pawn. LK - A light king. DP - A dark pawn. + # * DK - A dark king. + # * + # * @return A string representing the current board state. + # */ + def __str__(self): + # Prepare for output with a nice looking to banner. + output = " " + for row in xrange(0, self.board_size): + if row < 9: + output = '{}{}{}'.format(output, " ", row + 1) + else: + output = '{}{}{}'.format(output, " ", row + 1) + output = output + "\n\n" - } - } + output_atom = { + Square.WHITE: "## ", + Square.EMPTY: "__ ", + Square.LIGHT_PAWN: "LP ", + Square.LIGHT_KING: "LK ", + Square.DARK_PAWN: "DP ", + Square.DARK_KING:"DK ", + } - /** - * Setups a checker board according to the suicide "French" rules. - */ - private void setupNewSuicideGame() { - // TODO: Implement the suicide game setup. - } + # Go row by row, printing out the row number and the board's state. + for row in xrange(0, self.board_size): + if row < 9: + output = '{}{}{}'.format(output, " ", row + 1) + else: + output = '{}{}{}'.format(output, " ", row + 1) - // -- Private (Implementation) Methods ------------------------------------- + # // Get current row's state. + for col in xrange(0, self.board_size): + output = output + output_atom[self._board[row][col]] - /** - * Returns a string to represent the board state. This string is formatted - * for use as a simple board display in the command window. - * - * Legend ## - White space which the piece can not move on to. __ - - * An empty space. LP - A light pawn. LK - A light king. DP - A dark pawn. - * DK - A dark king. - * - * @return A string representing the current board state. - */ - @Override - public String toString() { - // Prepare for output with a nice looking to banner. - String output = " "; - for (int i = 0; i < this.boardSize; i++) { - if (i < 9) { - output = output + " " + (i + 1); - } else { - output = output + " " + (i + 1); - } - } - output = output + "\n\n"; + output = output + "\n" - // Go row by row, printing out the row number and the board's state. - for (int row = 0; row < this.boardSize; row++) { - if (row < 9) { - output = output + " " + (row + 1); - } else { - output = output + " " + (row + 1); - } - - // Get current row's state. - for (int col = 0; col < this.boardSize; col++) { - switch (this.board[row][col]) { - case Board.ILLEGAL_SPACE: - output = output + "## "; - break; - case Board.EMPTY_SPACE: - output = output + "__ "; - break; - case Board.LIGHT_PAWN: - output = output + "LP "; - break; - case Board.LIGHT_KING: - output = output + "LK "; - break; - case Board.DARK_PAWN: - output = output + "DP "; - break; - case Board.DARK_KING: - output = output + "DK "; - break; - } - } - - output = output + "\n"; - } - - return output; - - } -} + return output diff --git a/justcheckers/game/game_engine.py b/justcheckers/game/game_engine.py index d14c7f2..54422ee 100644 --- a/justcheckers/game/game_engine.py +++ b/justcheckers/game/game_engine.py @@ -17,271 +17,240 @@ # Please share and enjoy! # -class GameEngine(object): - // TODO: Add a constructor for games already in progress. - - // -- Game methods -------------------------------------------------------- - - private static boolean canJump(Game game, int sourceRow, int sourceCol, int targetRow, - int targetCol) { - - // TODO: Implement me. - return false; - } +def canJump(game, sourceRow, sourceCol, targetRow, targetCol): + # TODO: Implement me. + # TODO: Make as private method. + return False - /** - * Returns if a piece can or cannot move. This move maybe either be a move - * or a jump. This method is called by a user interface when a user wants to - * moves a piece on screen or over the network. The piece can moved if the - * current state of the game allows for it to do so. - * - * TODO: Add priority for king jumps over pawn jumps for any variants that - * do so. - * - * @param sourceRow - * The row from where the piece is moving from. - * @param sourceCol - * The column from where the piece is moving from. - * @param targetRow - * The row to where the piece is moving to. - * @param targetCol - * The column to where the piece is moving to. - * @return True if the piece can move. False if the piece can not move. - */ - public static boolean canMove(Game game, int sourceRow, int sourceCol, int targetRow, - int targetCol) { - - // A few things to figure out priorities in moving a piece. - boolean legalMove = false; // Is the proposed move/jump legal? - boolean realPositions = false; // Are the positions really on the board? - boolean isJump = false; // Is this a jump? - - // Sanity check. - if (game.getGameBoard().isLegalPosition(sourceRow, sourceCol) - && game.getGameBoard().isLegalPosition(targetRow, targetCol)) { - realPositions = true; - - } - - // Is there a jump in progress? - if (realPositions && game.getJumpInProgress() != null) { - - // Only allow the piece in movement to be moved. - if (sourceRow == game.getJumpInProgress().getY() - && sourceCol == game.getJumpInProgress().getX()) { - legalMove = canJump(game, sourceRow, sourceCol, targetRow, - targetCol); - isJump = true; - } - - } else if (realPositions) { - - // Go with the regular flow, jumps first then "slides". - isJump = canPlayerJump(game); - if (isJump) { - legalMove = canJump(game, sourceRow, sourceCol, targetRow, - targetCol); - } else { - legalMove = canSlide(game, sourceRow, sourceCol, targetRow, - targetCol); - } - - } - - return legalMove; - } - private static boolean canPlayerJump(Game game) { - // TODO: Implement me. - return false; - } +# /** +# * Returns if a piece can or cannot move. This move maybe either be a move +# * or a jump. This method is called by a user interface when a user wants to +# * moves a piece on screen or over the network. The piece can moved if the +# * current state of the game allows for it to do so. +# * +# * TODO: Add priority for king jumps over pawn jumps for any variants that +# * do so. +# * +# * @param sourceRow +# * The row from where the piece is moving from. +# * @param sourceCol +# * The column from where the piece is moving from. +# * @param targetRow +# * The row to where the piece is moving to. +# * @param targetCol +# * The column to where the piece is moving to. +# * @return True if the piece can move. False if the piece can not move. +# */ +def canMove(game, sourceRow, sourceCol, targetRow, targetCol): - private static boolean canSlide(Game game, int sourceRow, int sourceCol, int targetRow, - int targetCol) { - - boolean legalMove = true; - boolean mustJump = canPlayerJump(game); - - // Is the move even on the board? - legalMove = game.getGameBoard().isLegalPosition(sourceRow, sourceCol) - && game.getGameBoard().isLegalPosition(targetRow, targetCol); - - // See if the destination is even empty. - if (legalMove) { - legalMove = game.getGameBoard().isEmpty(targetRow, targetCol); - } - - // If yes, then look if right pieces were chosen. - if (legalMove && !mustJump) { - if (game.isLightPlayerTurn() - && game.getGameBoard().isLight(sourceRow, sourceCol)) { - - // To deal with flying kings. - if (game.getGameBoard().isKing(sourceRow, sourceCol) - && game.getGameRules().canKingsFly()) { - - // FIXME: Fix this! - } else { - // if ((Math.abs(targetRow - sourceRow) == 1) && (Math.abs(targetRow - sourceRow) == 1)) { - // legalMove = false; - // } - } - - // Is the path clear for that move? - - } else if (!game.isLightPlayerTurn() - && game.getGameBoard().isDark(sourceRow, sourceCol)) { - - //TODO: Implement me, sometime. - } else { - legalMove = false; - } - } - - return legalMove; - } + # // A few things to figure out priorities in moving a piece. + legalMove = False + # // Is the proposed move/jump legal? + realPositions = False + # // Are the positions really on the board? + isJump = False + # // Is this a jump? - private static void checkForVictory(Game game) { - // TODO: Implement me. - } + # // Sanity check. + if (game.getGameBoard().isLegalPosition(sourceRow, sourceCol) + and game.getGameBoard().isLegalPosition(targetRow, targetCol)): + realPositions = True - /** - * Gets if a piece is movable. Returns true if the piece can slide or jump. - * This method only calculates slides to the adjacent positions. Similarly, - * the method only looks at jumping an adjacent enemy piece. This check is - * used by the graphical user interface to determine if a piece can be moved - * either for sliding or jumping. The method is aware of whose turn is it to - * move. - * - * @param row - * The row coordinate of the piece to check. - * @param col - * The column coordinate of the piece to check. - * @return Returns true if the piece can slide or jump in this turn. - */ - public static boolean isMovablePiece(Game game, int row, int col) { - - // Fields for determining of a piece is movable. - boolean moveUpLeft = true; - boolean moveUpRight = true; - boolean moveDownLeft = true; - boolean moveDownRight = true; - - /* - * Checks first if the first colour of piece is being grabbed. Next if - * the piece is blocked by its own pieces. Next if the opponent has - * double blocked off the pieces. Also sanity checks if looking past the - * size of the board. - */ - if (game.isLightPlayerTurn() && game.getGameBoard().isLight(row, col)) { // Light - // player. - - // Can piece move normally? - moveDownLeft = canSlide(game, row, col, row + 1, col - 1); - moveDownRight = canSlide(game, row, col, row + 1, col + 1); - - if (game.getGameBoard().isKing(row, col)) { - moveUpLeft = canSlide(game, row, col, row - 1, col - 1); - moveUpRight = canSlide(game, row, col, row - 1, col + 1); - } else { - moveUpLeft = false; - moveUpRight = false; - } - - // If no slides available try doing the same except for jumps. - if (!moveDownLeft) { - moveDownLeft = canJump(game, row, col, row + 2, col - 2); - } else if (!moveDownRight) { - moveDownRight = canJump(game, row, col, row + 2, col + 2); - } else if (game.getGameBoard().isKing(row, col) - || game.getGameRules().canPawnsJumpBackwards()) { - - if (!moveUpLeft) { - moveUpLeft = canJump(game, row, col, row - 2, col + 2); - } else if (!moveUpRight) { - moveUpRight = canJump(game, row, col, row - 2, col - 2); - } - - } - - return moveUpLeft || moveUpRight || moveDownLeft || moveDownRight; - - } else if (game.isLightPlayerTurn() && game.getGameBoard().isDark(row, col)) { // Dark - // player - - // Can piece move normally? - moveUpLeft = canSlide(game, row, col, row - 1, col - 1); - moveUpRight = canSlide(game, row, col, row - 1, col + 1); - - if (game.getGameBoard().isKing(row, col)) { - moveDownLeft = canSlide(game, row, col, row + 1, col - 1); - moveDownRight = canSlide(game, row, col, row + 1, col + 1); - } else { - moveDownLeft = false; - moveDownRight = false; - } - - // If no slides available try doing the same except for jumps. - if (!moveUpLeft) { - moveUpLeft = canJump(game, row, col, row - 2, col - 2); - } else if (!moveUpRight) { - moveUpRight = canJump(game, row, col, row - 2, col + 2); - } else if (game.getGameBoard().isKing(row, col) - || game.getGameRules().canPawnsJumpBackwards()) { - - if (!moveDownLeft) { - moveDownLeft = canJump(game, row, col, row + 2, col + 2); - } else if (!moveDownRight) { - moveDownRight = canJump(game, row, col, row + 2, col - 2); - } - - } - - return moveUpLeft || moveUpRight || moveDownLeft || moveDownRight; - - } else { - return false; // A wrong coloured piece. - } - - } + # // Is there a jump in progress? + if (realPositions and game.getJumpInProgress() != None): - /** - * Moves a pieces from one location to another. This move maybe either be a - * move or a jump. This method is called by a user interface when a user - * moves a piece on screen or over the network. The piece is moved if the - * current state of the game allows for it to do so. - * - * TODO: Add priority for king jumps over pawn jumps for any variants that - * do so. TODO: Implement jumping by piece removal. - * - * @param sourceRow - * The row from where the piece is moving from. - * @param sourceCol - * The column from where the piece is moving from. - * @param targetRow - * The row to where the piece is moving to. - * @param targetCol - * The column to where the piece is moving to. - */ - public static void movePiece(Game game, int sourceRow, int sourceCol, int targetRow, - int targetCol) { - - // If everything checks out... move the piece! - if (canMove(game, sourceRow, sourceCol, targetRow, targetCol)) { - if (game.getJumpInProgress() != null) { - - // TODO: Implement jumping via removing of piece. - game.getGameBoard().movePiece(sourceRow, sourceCol, targetRow, - targetCol); - } else { - game.getGameBoard().movePiece(sourceRow, sourceCol, targetRow, - targetCol); - } - - checkForVictory(game); - } - - } + # // Only allow the piece in movement to be moved. + if (sourceRow == game.getJumpInProgress().getY() + and sourceCol == game.getJumpInProgress().getX()): + legalMove = canJump(game, sourceRow, sourceCol, targetRow, + targetCol) + isJump = True -} + elif (realPositions): + + # // Go with the regular flow, jumps first then "slides". + isJump = canPlayerJump(game) + if isJump: + legalMove = canJump(game, sourceRow, sourceCol, targetRow, + targetCol) + else: + legalMove = canSlide(game, sourceRow, sourceCol, targetRow, + targetCol) + + return legalMove + +def canPlayerJump(game): + # // TODO: Implement me. + # TODO Make as private method + return False + +def canSlide(game, sourceRow, sourceCol, targetRow, targetCol): + + # TODO Make private + legalMove = True + mustJump = canPlayerJump(game) + + # // Is the move even on the board? + legalMove = game.getGameBoard().isLegalPosition(sourceRow, sourceCol)\ + and game.getGameBoard().isLegalPosition(targetRow, targetCol) + + # // See if the destination is even empty. + if (legalMove): + legalMove = game.getGameBoard().isEmpty(targetRow, targetCol) + + # // If yes, then look if right pieces were chosen. + if (legalMove and not mustJump): + if (game.isLightPlayerTurn() and game.getGameBoard().isLight(sourceRow, sourceCol)): + + # // To deal with flying kings. + if (game.getGameBoard().isKing(sourceRow, sourceCol) + and game.getGameRules().canKingsFly()): + + # // FIXME: Fix this! + pass + else: + # // if ((Math.abs(targetRow - sourceRow) == 1) && (Math.abs(targetRow - sourceRow) == 1)) { + # // legalMove = false; + + # // Is the path clear for that move? + pass + + elif (not game.isLightPlayerTurn() and game.getGameBoard().isDark(sourceRow, sourceCol)): + + # //TODO: Implement me, sometime. + pass + else: + legalMove = False + + return legalMove; + + +def checkForVictory(game): + # // TODO: Implement me. + pass + +# /** +# * Gets if a piece is movable. Returns True if the piece can slide or jump. +# * This method only calculates slides to the adjacent positions. Similarly, +# * the method only looks at jumping an adjacent enemy piece. This check is +# * used by the graphical user interface to determine if a piece can be moved +# * either for sliding or jumping. The method is aware of whose turn is it to +# * move. +# * +# * @param row +# * The row coordinate of the piece to check. +# * @param col +# * The column coordinate of the piece to check. +# * @return Returns True if the piece can slide or jump in this turn. +# */ +def isMovablePiece(game, row, col): + + # // Fields for determining of a piece is movable. + moveUpLeft = True + moveUpRight = True + moveDownLeft = True + moveDownRight = True + + # /* + # * Checks first if the first colour of piece is being grabbed. Next if + # * the piece is blocked by its own pieces. Next if the opponent has + # * double blocked off the pieces. Also sanity checks if looking past the + # * size of the board. + # */ + if (game.isLightPlayerTurn() and game.getGameBoard().isLight(row, col)): + + # // Light player. + + # // Can piece move normally? + moveDownLeft = canSlide(game, row, col, row + 1, col - 1) + moveDownRight = canSlide(game, row, col, row + 1, col + 1) + + if (game.getGameBoard().isKing(row, col)): + moveUpLeft = canSlide(game, row, col, row - 1, col - 1) + moveUpRight = canSlide(game, row, col, row - 1, col + 1) + else: + moveUpLeft = False + moveUpRight = False + + # // If no slides available try doing the same except for jumps. + if (not moveDownLeft): + moveDownLeft = canJump(game, row, col, row + 2, col - 2) + elif (not moveDownRight): + moveDownRight = canJump(game, row, col, row + 2, col + 2) + elif (game.getGameBoard().isKing(row, col) + or game.getGameRules().canPawnsJumpBackwards()): + + if (not moveUpLeft): + moveUpLeft = canJump(game, row, col, row - 2, col + 2) + elif (not moveUpRight): + moveUpRight = canJump(game, row, col, row - 2, col - 2) + + return moveUpLeft or moveUpRight or moveDownLeft or moveDownRight + + elif (game.isLightPlayerTurn() and game.getGameBoard().isDark(row, col)): + # // Dark player + + # // Can piece move normally? + moveUpLeft = canSlide(game, row, col, row - 1, col - 1) + moveUpRight = canSlide(game, row, col, row - 1, col + 1) + + if (game.getGameBoard().isKing(row, col)): + moveDownLeft = canSlide(game, row, col, row + 1, col - 1) + moveDownRight = canSlide(game, row, col, row + 1, col + 1) + else: + moveDownLeft = False + moveDownRight = False + + # // If no slides available try doing the same except for jumps. + if (not moveUpLeft): + moveUpLeft = canJump(game, row, col, row - 2, col - 2) + elif (not moveUpRight): + moveUpRight = canJump(game, row, col, row - 2, col + 2) + elif (game.getGameBoard().isKing(row, col) + or game.getGameRules().canPawnsJumpBackwards()): + + if (not moveDownLeft): + moveDownLeft = canJump(game, row, col, row + 2, col + 2) + elif (not moveDownRight): + moveDownRight = canJump(game, row, col, row + 2, col - 2) + + return moveUpLeft or moveUpRight or moveDownLeft or moveDownRight + + else: + return False + # // A wrong coloured piece. + +# /** +# * Moves a pieces from one location to another. This move maybe either be a +# * move or a jump. This method is called by a user interface when a user +# * moves a piece on screen or over the network. The piece is moved if the +# * current state of the game allows for it to do so. +# * +# * TODO: Add priority for king jumps over pawn jumps for any variants that +# * do so. TODO: Implement jumping by piece removal. +# * +# * @param sourceRow +# * The row from where the piece is moving from. +# * @param sourceCol +# * The column from where the piece is moving from. +# * @param targetRow +# * The row to where the piece is moving to. +# * @param targetCol +# * The column to where the piece is moving to. +# */ +def movePiece(game, sourceRow, sourceCol, targetRow, targetCol): + + # // If everything checks out... move the piecenot + if (canMove(game, sourceRow, sourceCol, targetRow, targetCol)): + if (game.getJumpInProgress() != None): + + # TODO: Implement jumping via removing of piece. + game.getGameBoard().movePiece(sourceRow, sourceCol, targetRow, + targetCol) + else: + game.getGameBoard().movePiece(sourceRow, sourceCol, targetRow, + targetCol) + + checkForVictory(game)