def check_for_jump(self, player: str, row: int, col: int): """ Checks the two front diagonals for possible jumps. Black begins on the bottom side, white begins at the top side. left and right directions in perspective of the board side. """ found_jumps = [] other_player = self._checkers.other_player(player) # Check the player to correspond to direction if player == CheckersBoard.player_1: # If black then check row+1,col-1 and row+1,col+1 left = self._checkers.get(row + 1, col - 1) right = self._checkers.get(row + 1, col + 1) further_left = self._checkers.get(row + 2, col - 2) further_right = self._checkers.get(row + 2, col + 2) # Checks if the moves can be made and adds to the found jumps if left == other_player and further_left == CheckersBoard.empty: found_jumps.append(Move(row, col, 1, -1)) if right == other_player and further_right == CheckersBoard.empty: found_jumps.append(Move(row, col, 1, 1)) elif player == CheckersBoard.player_2: # If red then check row-1,col-1 and row-1,col+1 left = self._checkers.get(row - 1, col - 1) right = self._checkers.get(row - 1, col + 1) further_left = self._checkers.get(row - 2, col - 2) further_right = self._checkers.get(row - 2, col + 2) # Checks if the moves can be made and adds to the found jumps if left == other_player and further_left == CheckersBoard.empty: found_jumps.append(Move(row, col, -1, -1)) if right == other_player and further_right == CheckersBoard.empty: found_jumps.append(Move(row, col, -1, 1)) return found_jumps
def getRookMoves(self, row, column, whiteToMove, board, moves, pins): piecePinned = False pinDirection = () for i in range(len(pins) - 1, -1, -1): if pins[i][0] == row and pins[i][1] == column: piecePinned = True pinDirection = (pins[i][2], pins[i][3]) if not isinstance(board[row][column], Queen): pins.remove(pins[i]) break directions = ((-1, 0), (0, -1), (1, 0), (0, 1)) enemyColor = 'black' if whiteToMove else 'white' for currentDirection in directions: for i in range(1, 8): endRow = row + currentDirection[0] * i endCol = column + currentDirection[1] * i if 0 <= endRow < 8 and 0 <= endCol < 8: if not piecePinned or pinDirection == currentDirection or pinDirection == ( -currentDirection[0], -currentDirection[1]): endPiece = board[endRow][endCol] if endPiece == "--": moves.append( Move((row, column), (endRow, endCol), board)) elif isinstance( endPiece, Piece) and endPiece.color == enemyColor: moves.append((Move((row, column), (endRow, endCol), board))) break else: break else: break
def check_for_jump(self, player: str, row: int, col: int): found_jumps = [] other_player = self._checkers.other_player(player) # Tiles where an opponent might be north_west = self._checkers.get(row - 1, col - 1) north_east = self._checkers.get(row - 1, col + 1) south_west = self._checkers.get(row + 1, col - 1) south_east = self._checkers.get(row + 1, col + 1) # Tiles where a blank space might be further_nw = self._checkers.get(row - 2, col - 2) further_ne = self._checkers.get(row - 2, col + 2) further_sw = self._checkers.get(row + 2, col - 2) further_se = self._checkers.get(row + 2, col + 2) # Checks if a jump is possible and adds the possible Move to the list if north_west == other_player and further_nw == CheckersBoard.empty: found_jumps.append(Move(row, col, -1, -1)) if north_east == other_player and further_ne == CheckersBoard.empty: found_jumps.append(Move(row, col, -1, 1)) if south_west == other_player and further_sw == CheckersBoard.empty: found_jumps.append(Move(row, col, 1, -1)) if south_east == other_player and further_se == CheckersBoard.empty: found_jumps.append(Move(row, col, 1, 1)) return found_jumps
def testExistsMove(self): repoMoves = RepoMoves(4, 4) move = Move(2, 3, "x") otherMove = Move(1, 1, "o") repoMoves.moves.append(move) assert repoMoves.existsMove(move) == True assert repoMoves.existsMove(otherMove) == False
def testAddNeighbours(self): repoMoves = RepoMoves(4, 4) move = Move(0, 0, "x") repoMoves.moves.append(move) repoMoves.addNeighbours(move) assert repoMoves.moves == [ move, Move(0, 1, "#"), Move(1, 1, "#"), Move(1, 0, "#") ] assert len(repoMoves.moves) == 4
def makeMove(self, destination: List): curr_x = self.selected[0] curr_y = self.selected[1] move_x = destination[0] move_y = destination[1] move_dx = destination[0] - self.selected[0] move_dy = destination[1] - self.selected[1] if move_dx == 2 and move_dy == 2: move_dx = 1 move_dy = 1 if move_dx == 2 and move_dy == -2: move_dx = 1 move_dy = -1 if move_dx == -2 and move_dy == 2: move_dx = -1 move_dy = 1 if move_dx == -2 and move_dy == -2: move_dx = -1 move_dy = -1 if move_dx >= 2 or move_dx <= -2 or move_dy >= 2 or move_dy <= -2: self.selected = [-1, -1] return m = Move(curr_x, curr_y, move_dx, move_dy) print(self.controller.play(m)) print("from " + str(self.selected)) print("to " + str(destination)) self.selected = [-1, -1]
def get_move(self, row: int, col: int, drow: int, dcol: int): """ Pygame will retrieve the coordinates of the tile and pass those into getMove to return a Move object. """ # Row, col are the coordinates of the piece you are moving onto some # tile: final_row, final_col return Move(row, col, drow, dcol)
def getPawnMoves(self, row, column, whiteToMove, board, moves, pins): piecePinned = False pinDirection = () for i in range(len(pins) - 1, -1, -1): if pins[i][0] == row and pins[i][1] == column: piecePinned = True pinDirection = (pins[i][2], pins[i][3]) pins.remove(pins[i]) break if whiteToMove: # white's turn if row > 0 and board[row - 1][column] == "--": if not piecePinned or pinDirection == (-1, 0): moves.append((Move((row, column), (row - 1, column), board))) if row == 6 and board[row - 2][column] == "--": moves.append( Move((row, column), (row - 2, column), board)) # capturing other pieces cases if row > 0 and column - 1 >= 0: # left if isinstance( board[row - 1][column - 1], Piece) and board[row - 1][column - 1].color == 'black': if not piecePinned or pinDirection == (-1, -1): moves.append( Move((row, column), (row - 1, column - 1), board)) if row > 0 and column + 1 <= 7: # right if isinstance( board[row - 1][column + 1], Piece) and board[row - 1][column + 1].color == 'black': if not piecePinned or pinDirection == (-1, 1): moves.append( Move((row, column), (row - 1, column + 1), board)) else: # black's turn if row < 7 and board[row + 1][column] == "--": if not piecePinned or pinDirection == (1, 0): moves.append((Move((row, column), (row + 1, column), board))) if row == 1 and board[row + 2][column] == "--": moves.append( Move((row, column), (row + 2, column), board)) # capturing other pieces if row < 7 and column + 1 <= 7: # right if isinstance( board[row + 1][column + 1], Piece) and board[row + 1][column + 1].color == 'white': if not piecePinned or pinDirection == (1, -1): moves.append( Move((row, column), (row + 1, column + 1), board)) if row < 7 and column - 1 >= 0: # left if isinstance( board[row + 1][column - 1], Piece) and board[row + 1][column - 1].color == 'white': if not piecePinned or pinDirection == (1, 1): moves.append( Move((row, column), (row + 1, column - 1), board))
def addNeighbours(self, move): currentX = move.getX() currentY = move.getY() dl = [-1, -1, 0, 1, 1, 1, 0, -1] dc = [0, 1, 1, 1, 0, -1, -1, -1] for i in range(0, 8): newX = currentX + dl[i] newY = currentY + dc[i] if newX >= 0 and newX < self.row and newY >= 0 and newY < self.column: neighbour = Move(newX, newY, "#") if self.existsMove(neighbour) == False: self.moves.append(neighbour)
def testAddMove(self): repoMoves = RepoMoves(5, 4) move = Move(0, 0, "x") repoMoves.addMove(move) assert len(repoMoves.moves) == 4 try: repoMoves.addMove(move) assert False except: assert True repoMoves.drawTable()
def drawTable(self): for i in range(0, self.row): row = "" for j in range(0, self.column): emptyMove = Move(i, j, "-") found = False for move in self.moves: if emptyMove == move: row += move.getMark() found = True if found == False: row += "-" print(row)
def getKnightMoves(self, row, column, whiteToMove, board, moves, pins): piecePinned = False pinDirection = () for i in range(len(pins) - 1, -1, -1): if pins[i][0] == row and pins[i][1] == column: piecePinned = True pinDirection = (pins[i][2], pins[i][3]) pins.remove(pins[i]) break knightMoves = ((-2, -1), (-2, 1), (-1, -2), (-1, 2), (1, -2), (1, 2), (2, -1), (2, 1)) enemyColor = 'black' if whiteToMove else 'white' for currentMove in knightMoves: endRow = row + currentMove[0] endCol = column + currentMove[1] if 0 <= endRow < 8 and 0 <= endCol < 8: if not piecePinned: endPiece = board[endRow][endCol] if (isinstance(endPiece, Piece) and endPiece.color == enemyColor) or endPiece == "--": moves.append( Move((row, column), (endRow, endCol), board))
def getKingMoves(self, row, column, whiteToMove, board, moves, whiteKingPos, blackKingPos, pinsAndChecks): rowMoves = (-1, -1, -1, 0, 0, 1, 1, 1) colMoves = (-1, 0, 1, -1, 1, -1, 0, 1) enemyColor = 'black' if whiteToMove else 'white' for currentMove in range(8): endRow = row + rowMoves[currentMove] endCol = column + colMoves[currentMove] if 0 <= endRow < 8 and 0 <= endCol < 8: endPiece = board[endRow][endCol] if (isinstance(endPiece, Piece) and endPiece.color == enemyColor) or endPiece == "--": if enemyColor == "black": whiteKingPos = (endRow, endCol) else: blackKingPos = (endRow, endCol) inCheck, pins, checks = pinsAndChecks if not inCheck: moves.append( Move((row, column), (endRow, endCol), board)) if enemyColor == "black": whiteKingPos = (row, column) else: blackKingPos = (row, column)
def _get_easy_move(self): """ Easy mode will calculate a random move to make Checks if any piece can jump, if so does that. Otherwise makes random move. This method will return either a list containing a single more or a list containing multiple moves representing a path of multiple jumps. """ # Stores the possible moves and jump paths found moves = [] required_jumps = [] for row in range(self._checkers.dimension): for col in range(self._checkers.dimension): # Check same color pieces as player to see if they can jump. if self._checkers.get(row, col) == self._player: path_made = False found_jumps = [] # Attempt to build a jump path in the two forward # directions for i in range(1): current_path = [] while (not path_made): jumps = self.check_for_jump(self._player, row, col) if jumps == []: path_made = True break current_path += (jumps) incrow = 0 inccol = 0 # The forward direction depends on the player's # perspective. if (self._player == CheckersBoard.player_1): # Black looks downwards if i == 0: incrow = 2 inccol = 2 elif i == 1: incrow = 2 incrow = -2 elif (self._player == CheckersBoard.player_2): # Red looks upwards if i == 0: incrow = -2 inccol = -2 elif i == 1: incrow = -2 incrow = 2 row += incrow col += inccol found_jumps.append(current_path) # If some jump paths were found then add them to the jumps # list if len(found_jumps) > 0: required_jumps += found_jumps else: # Checks for regular moves in the forward direction if self._player == CheckersBoard.player_1: # If player is black left = self._checkers.get(row + 1, col + 1) right = self._checkers.get(row + 1, col - 1) if left == CheckersBoard.empty: moves.append(Move(row, col, 1, 1)) if right == CheckersBoard.empty: moves.append(Move(row, col, 1, -1)) else: # If player is red left = self._checkers.get(row - 1, col - 1) right = self._checkers.get(row - 1, col + 1) if left == CheckersBoard.empty: moves.append(Move(row, col, -1, -1)) if right == CheckersBoard.empty: moves.append(Move(row, col, -1, 1)) # Calculates a random move or move path from the two built lists # If a move can be made we prioritize the list with possible moves random_index = 0 if len(required_jumps) != 0: random_index = random.randint(0, len(required_jumps)) move_path = required_jumps[random_index] return move_path else: random_index = random.randint(0, len(moves)) move = moves[random_index] return [move]
def _get_easy_move(self): """ Easy mode for the computer king will search the four diagonals around the player for empty spots and potential pieces to jump. If it finds pieces to jump it prioritizes them.This method will return either a list containing a single more or a list containing multiple moves representing a path of multiple jumps. """ # Two lists keep track of regular moves and paths of possible jumps moves = [] required_jumps = [] for row in range(self._checkers.dimension): for col in range(self._checkers.dimension): # Check same color pieces as player to see if they can jump. if self._checkers.get(row, col) == self._player: path_made = False found_jumps = [] # i represents an option of direction to check for i in range(3): current_path = [] # Builds a path of jumps by checking for a jump each # move while (not path_made): jumps = self.check_for_jump(self._player, row, col) if jumps == []: path_made = True break current_path += (jumps) incrow = 0 inccol = 0 # South west and east if i == 0: incrow = 2 inccol = 2 elif i == 1: incrow = 2 incrow = -2 # North west and east elif i == 2: incrow = -2 inccol = -2 elif i == 3: incrow = -2 incrow = 2 row += incrow col += inccol found_jumps.append(current_path) if len(found_jumps) > 0: # If there is at least one path then we append it # to the list of jumps required_jumps += found_jumps else: # Checks if a move can be made in each direction north_west = self._checkers.get(row - 1, col - 1) north_east = self._checkers.get(row - 1, col + 1) south_west = self._checkers.get(row + 1, col + 1) south_east = self._checkers.get(row + 1, col - 1) if north_west == CheckersBoard.empty: moves.append(Move(row, col, -1, -1)) if north_east == CheckersBoard.empty: moves.append(Move(row, col, -1, 1)) if south_west == CheckersBoard.empty: moves.append(Move(row, col, 1, 1)) if south_east == CheckersBoard.empty: moves.append(Move(row, col, 1, -1)) # A random move is calculated for the lists of moves # If a move can be made we prioritize the list with possible moves random_index = 0 if len(required_jumps) != 0: random_index = random.randint(0, len(required_jumps)) move_path = required_jumps[random_index] return move_path else: random_index = random.randint(0, len(moves)) move = moves[random_index] return [move]