diff --git a/src/go.py b/src/go.py --- a/src/go.py +++ b/src/go.py @@ -1,51 +1,51 @@ class Go: - EMPTY=0 - BLACK=1 - WHITE=-1 - - ## Initializes self.board to a list[r][c]=Go.EMPTY. - def __init__(self,boardSize=19): - self.boardSize=boardSize - self.board=[[Go.EMPTY]*self.boardSize for x in self.board] - - ## Executes a move. - # - # Doesn't check for kos. Suicide not allowed. - # - # @param color Go.BLACK or Go.WHITE - # @return True on success, False on failure (illegal move) - def move(self,color,row,col): - if self.board[row][col]!=Go.EMPTY: return False + EMPTY=0 + BLACK=1 + WHITE=-1 + + ## Initializes self.board to a list[r][c]=Go.EMPTY. + def __init__(self,boardSize=19): + self.boardSize=boardSize + self.board=[[Go.EMPTY]*self.boardSize for x in self.board] - self.board[row][col]=color + ## Executes a move. + # + # Doesn't check for kos. Suicide not allowed. + # + # @param color Go.BLACK or Go.WHITE + # @return True on success, False on failure (illegal move) + def move(self,color,row,col): + if self.board[row][col]!=Go.EMPTY: return False + + self.board[row][col]=color + + # capture neighbors + for r,c in ((-1,0),(1,0),(0,-1),(0,1)): + self.temp=[[False]*self.boardSize for x in self.board] + if not self._floodFill(-color,row+r,col+c): self._remove() - # capture neighbors - for r,c in ((-1,0),(1,0),(0,-1),(0,1)): - self.temp=[[False]*self.boardSize for x in self.board] - if not self._floodFill(-color,row+r,col+c): self._remove() - - # check for suicide - self.temp=[[False]*self.boardSize for x in self.board] - if not self._floodFill(color,row,col): - self.board[row][col]=Go.EMPTY - return False - return True - - ## Checks for liberties of a stone at given coordinates. - # - # The stone's group is marked with True in self.temp, ready for capture if needed. Recursively called for stone's neighbors. - # - # @return True if alive, False if captured - def _floodFill(self,color,row,col): - if col<0 or col>=self.boardSize or row<0 or row>=self.boardSize: return False # out of range - if self.temp[row][col]: return False # already visited - if self.board[row][col]==Go.EMPTY: return True # found a liberty - if self.board[row][col]!=color: return False # opponent's stone - self.temp[row][col]=True # set visited - return self._floodFill(color,row,col-1) or self._floodFill(color,row,col+1) or self._floodFill(color,row-1,col) or self._floodFill(color,row+1,col) # check neighbors - - ## Removes stones at coordinates marked with True in self.temp. - def _remove(self): - for r in range(self.boardSize): - for c in range(self.boardSize): - if self.temp[r][c]: self.board[r][c]=Go.EMPTY + # check for suicide + self.temp=[[False]*self.boardSize for x in self.board] + if not self._floodFill(color,row,col): + self.board[row][col]=Go.EMPTY + return False + return True + + ## Checks for liberties of a stone at given coordinates. + # + # The stone's group is marked with True in self.temp, ready for capture if needed. Recursively called for stone's neighbors. + # + # @return True if alive, False if captured + def _floodFill(self,color,row,col): + if col<0 or col>=self.boardSize or row<0 or row>=self.boardSize: return False # out of range + if self.temp[row][col]: return False # already visited + if self.board[row][col]==Go.EMPTY: return True # found a liberty + if self.board[row][col]!=color: return False # opponent's stone + self.temp[row][col]=True # set visited + return self._floodFill(color,row,col-1) or self._floodFill(color,row,col+1) or self._floodFill(color,row-1,col) or self._floodFill(color,row+1,col) # check neighbors + + ## Removes stones at coordinates marked with True in self.temp. + def _remove(self): + for r in range(self.boardSize): + for c in range(self.boardSize): + if self.temp[r][c]: self.board[r][c]=Go.EMPTY