diff --git a/src/go.py b/src/go.py --- a/src/go.py +++ b/src/go.py @@ -1,57 +1,57 @@ -EMPTY=0 -BLACK=1 -WHITE=-1 - - -class Go: - ## Initializes self.board to a list[r][c]=EMPTY. - def __init__(self,boardSize=19): - self.boardSize=boardSize - self.board=[[EMPTY]*self.boardSize for x in range(boardSize)] - - ## Executes a move. - # - # Doesn't check for kos. Suicide not allowed. - # - # @param color BLACK or WHITE - # @return True on success, False on failure (illegal move) - def move(self,color,row,col): - if self.board[row][col]!=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() - - # check for suicide - self.temp=[[False]*self.boardSize for x in self.board] - if not self._floodFill(color,row,col): - self.board[row][col]=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]==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]=EMPTY - - -def exportBoard(board): - substitutions={EMPTY:".", BLACK:"X", WHITE:"O"} - return "\n".join("".join(substitutions.get(x,"?") for x in row) for row in board) +EMPTY=0 +BLACK=1 +WHITE=-1 + + +class Go: + ## Initializes self.board to a list[r][c]=EMPTY. + def __init__(self,boardSize=19): + self.boardSize=boardSize + self.board=[[EMPTY]*self.boardSize for x in range(boardSize)] + + ## Executes a move. + # + # Doesn't check for kos. Suicide not allowed. + # + # @param color BLACK or WHITE + # @return True on success, False on failure (illegal move) + def move(self,color,row,col): + if self.board[row][col]!=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() + + # check for suicide + self.temp=[[False]*self.boardSize for x in self.board] + if not self._floodFill(color,row,col): + self.board[row][col]=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]==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]=EMPTY + + +def exportBoard(board): + substitutions={EMPTY:".", BLACK:"X", WHITE:"O"} + return "\n".join("".join(substitutions.get(x,"?") for x in row) for row in board)