aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorInigoGutierrez <inigogf.95@gmail.com>2021-02-09 20:40:13 +0100
committerInigoGutierrez <inigogf.95@gmail.com>2021-02-09 20:40:13 +0100
commit5cf270c29aec83bd81121e6b72f24e2c35340e38 (patch)
tree3ab85cac54e0b0e769fedce907bb0fb415e616a5
parenta9f645e19dd80f243c0e246e3dca9465207e60cb (diff)
downloadimago-5cf270c29aec83bd81121e6b72f24e2c35340e38.tar.gz
imago-5cf270c29aec83bd81121e6b72f24e2c35340e38.zip
logic: Fixed ko checks in gameBoard.py
-rw-r--r--imago/gameLogic/gameBoard.py45
-rw-r--r--imago/gameLogic/gameMove.py29
-rw-r--r--imago/gameLogic/gameState.py8
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