diff options
author | InigoGutierrez <inigogf.95@gmail.com> | 2021-02-09 20:40:13 +0100 |
---|---|---|
committer | InigoGutierrez <inigogf.95@gmail.com> | 2021-02-09 20:40:13 +0100 |
commit | 5cf270c29aec83bd81121e6b72f24e2c35340e38 (patch) | |
tree | 3ab85cac54e0b0e769fedce907bb0fb415e616a5 | |
parent | a9f645e19dd80f243c0e246e3dca9465207e60cb (diff) | |
download | imago-5cf270c29aec83bd81121e6b72f24e2c35340e38.tar.gz imago-5cf270c29aec83bd81121e6b72f24e2c35340e38.zip |
logic: Fixed ko checks in gameBoard.py
-rw-r--r-- | imago/gameLogic/gameBoard.py | 45 | ||||
-rw-r--r-- | imago/gameLogic/gameMove.py | 29 | ||||
-rw-r--r-- | imago/gameLogic/gameState.py | 8 |
3 files changed, 56 insertions, 26 deletions
diff --git a/imago/gameLogic/gameBoard.py b/imago/gameLogic/gameBoard.py index 42b50d9..327728b 100644 --- a/imago/gameLogic/gameBoard.py +++ b/imago/gameLogic/gameBoard.py @@ -122,31 +122,34 @@ class GameBoard: """Checks surrounding captures of a move, removes them and returns a set containing the vertices where stones were captured. """ + + self.board[row][col] = player + captured = set() if row > 0: if (self.board[row-1][col] != player and self.board[row-1][col] != Player.EMPTY and len(self.getGroupLiberties(row-1, col)) == 0): - captured.add(self.__captureGroup(row-1, col)) + captured.update(self.__captureGroup(row-1, col)) if row < self.getBoardHeight()-1: if (self.board[row+1][col] != player and self.board[row+1][col] != Player.EMPTY and len(self.getGroupLiberties(row+1, col)) == 0): - captured.add(self.__captureGroup(row+1, col)) + captured.update(self.__captureGroup(row+1, col)) if col > 0: if (self.board[row][col-1] != player and self.board[row][col-1] != Player.EMPTY and len(self.getGroupLiberties(row, col-1)) == 0): - captured.add(self.__captureGroup(row, col-1)) + captured.update(self.__captureGroup(row, col-1)) if col < self.getBoardWidth()-1: if (self.board[row][col+1] != player and self.board[row][col+1] != Player.EMPTY and len(self.getGroupLiberties(row, col+1)) == 0): - captured.add(self.__captureGroup(row, col+1)) + captured.update(self.__captureGroup(row, col+1)) return captured @@ -174,20 +177,23 @@ class GameBoard: if not self.isCellEmpty(row, col): raise RuntimeError("Cell to play should be empty when checking for suicide.") - # Play and capture + # Temporarily play and capture self.board[row][col] = player groupLiberties = self.getGroupLibertiesCount(row, col) captured = self.moveAndCapture(row, col, player) + illegal = False # If move didn't capture anything and its group is left without liberties, it's # suicidal if len(captured) == 0 and groupLiberties == 0: - # Restore captured stones - for vertex in captured: - self.board[vertex[0]][vertex[1]] = Player.otherPlayer(player) - self.board[row][col] = Player.EMPTY - # Remove played stone - return True + illegal = True + + # Restore captured stones + for vertex in captured: + self.board[vertex[0]][vertex[1]] = Player.otherPlayer(player) + # Remove temporarily played stone + self.board[row][col] = Player.EMPTY + return illegal def isMoveKoIllegal(self, row, col, player, prevBoards): """Returns True if move is illegal because of ko.""" @@ -197,8 +203,8 @@ class GameBoard: raise RuntimeError("Cell to play should be empty when checking for ko.") illegal = False - # Temporarily place stone to play for comparisons - self.board[row][col] = player + # Temporarily play and capture for comparisons + captured = self.moveAndCapture(row, col, player) # Check previous boards for prevBoard in prevBoards: # A ko is possible in boards where the stone to play exists @@ -206,7 +212,10 @@ class GameBoard: if self.equals(prevBoard): illegal = True - # Remove temporarily placed stone + # Restore captured stones + for vertex in captured: + self.board[vertex[0]][vertex[1]] = Player.otherPlayer(player) + # Remove temporarily played stone self.board[row][col] = Player.EMPTY return illegal @@ -219,7 +228,7 @@ class GameBoard: return False for row in range(self.getBoardHeight()): for col in range(self.getBoardWidth()): - if self.board[row][col] != otherBoard[row][col]: + if self.board[row][col] != otherBoard.board[row][col]: return False return True @@ -227,9 +236,13 @@ class GameBoard: """Print the board.""" colTitle = 'A' rowTitlePadding = 2 + if self.getBoardHeight() >= 10: + firstRowPadding = 2 + else: + firstRowPadding = 1 # Print column names - rowText = " " * (rowTitlePadding + 2) + rowText = " " * (rowTitlePadding + firstRowPadding) for col in range(self.getBoardWidth()): rowText += colTitle + " " colTitle = chr(ord(colTitle)+1) diff --git a/imago/gameLogic/gameMove.py b/imago/gameLogic/gameMove.py index dc93909..b2db34f 100644 --- a/imago/gameLogic/gameMove.py +++ b/imago/gameLogic/gameMove.py @@ -1,5 +1,7 @@ """Information about one move.""" +from imago.data.enums import Player + class GameMove: """Stores information about a move. A move in this context is one position of the Game Tree: the board can be empty, or the move can consist of more than one added or @@ -19,15 +21,34 @@ class GameMove: """Returns the column of the vertex the move was played on.""" return self.board.lastStone[1] - def addMove(self, row, col, player): + def getThisAndPrevBoards(self): + """Returns an array with all the boards of this and previous moves.""" + prevBoards = [] + checkedMove = self.previousMove + while checkedMove is not None: + prevBoards.append(checkedMove.board) + checkedMove = checkedMove.previousMove + return prevBoards + + def addMove(self, row, col): + """Adds a move to the next moves list creating its board from this move's board + plus a new stone at the specified row and column. + """ + if self.player == Player.EMPTY: + player = Player.BLACK + else: + player = Player.otherPlayer(self.player) + return self.addMoveForPlayer(row, col, player) + + def addMoveForPlayer(self, row, col, player): """Adds a move to the next moves list creating its board from this move's board plus a new stone at the specified row and column. """ newBoard = self.board.getDeepCopy() - newBoard.board[row][col] = player - return self.addMoveWithBoard(player, newBoard) + newBoard.moveAndCapture(row, col, player) + return self.addMoveForPlayerAndBoard(player, newBoard) - def addMoveWithBoard(self, player, board): + def addMoveForPlayerAndBoard(self, player, board): """Adds a move to the next moves list containing the provided board.""" newMove = GameMove(player, board) newMove.previousMove = self diff --git a/imago/gameLogic/gameState.py b/imago/gameLogic/gameState.py index 0108887..cc65c75 100644 --- a/imago/gameLogic/gameState.py +++ b/imago/gameLogic/gameState.py @@ -51,11 +51,7 @@ class GameState: return False # Check ko - prevBoards = [] - checkedMove = self.lastMove - while checkedMove is not None: - prevBoards.append(checkedMove.board) - checkedMove = checkedMove.previousMove + prevBoards = self.lastMove.getThisAndPrevBoards() if self.getBoard().isMoveKoIllegal(row, col, player, prevBoards): print("Invalid move! (Ko)") return False @@ -83,5 +79,5 @@ class GameState: raise RuntimeError("Last move of the GameState is None.") # Add and return the new move - self.lastMove = self.lastMove.addMove(player, row, col) + self.lastMove = self.lastMove.addMoveForPlayer(row, col, player) return self.lastMove |