1"""This module defines the Board class for managing the state of a Connect Four game."""
3from __future__
import annotations
5from collections.abc
import Sequence
7from bitbully
import bitbully_core
11 """Represents the state of a Connect Four board. Mostly a thin wrapper around BoardCore."""
13 def __init__(self, board: Sequence[Sequence[int]] | Sequence[int] | str |
None =
None) ->
None:
14 """Initializes a Board instance.
17 board (Sequence[Sequence[int]] | Sequence[int] | str | None):
18 Optional initial board state. Accepts:
19 - 2D array (list, tuple, numpy-array) with shape 7x6 or 6x7
20 - 1D sequence of ints: a move sequence of columns (e.g., [0, 0, 2, 2, 3, 3])
21 - String: A move sequence of columns as string (e.g., "002233...")
22 - None for an empty board
25 Here we have an example:
27 board = Board() # Empty board
29 board = Board([[0] * 6 for _ in range(7)]) # empty board as 2D list
32 It is possible to write some text inbetween the examples.
35 And here we have another example:
37 board = Board("002233...") # String
41 self.
_board = bitbully_core.BoardCore()
43 def __eq__(self, value: object) -> bool:
44 """Checks equality between two Board instances.
47 value (object): The other Board instance to compare against.
50 bool: True if both boards are equal, False otherwise.
53 NotImplementedError: If the other value is not a Board instance.
55 if not isinstance(value, Board):
56 raise NotImplementedError(
"Can only compare with another Board instance.")
57 return bool(self.
_board == value._board)
59 def __ne__(self, value: object) -> bool:
60 """Checks inequality between two Board instances.
63 value (object): The other Board instance to compare against.
66 bool: True if both boards are not equal, False otherwise.
68 return not self.
__eq__(value)
71 """Returns a string representation of the Board instance."""
72 return f
"Board({self._board})"
74 def all_positions(self, up_to_n_ply: int, exactly_n: bool) -> list[Board]:
75 """Finds all positions on the board up to a certain ply.
78 up_to_n_ply (int): The maximum ply depth to search.
79 exactly_n (bool): If True, only returns positions at exactly N ply.
82 list[Board]: A list of Board instances representing all positions.
89 """Checks if the current player can win in the next move.
92 move (int | None): Optional column to check for an immediate win. If None, checks all columns.
95 bool: True if the current player can win next, False otherwise.
98 return self.
_board.canWin()
99 return bool(self.
_board.canWin(move))
102 """Creates a copy of the current Board instance.
105 Board: A new Board instance that is a copy of the current one.
112 """Counts the total number of tokens on the board.
115 int: The total number of tokens.
117 return self.
_board.countTokens()
120 """Returns a list of legal moves (columns) that can be played.
123 list[int]: A list of column indices (0-6) where a move can be played.
126 NotImplementedError: If the method is not implemented yet.
128 raise NotImplementedError(
"get_legal_moves is not implemented yet.")
131 """Checks if the current player has a winning position.
134 bool: True if the current player has a winning position (4-in-a-row), False otherwise.
136 return self.
_board.hasWin()
139 """Returns a hash of the Board instance for use in hash-based collections.
142 int: The hash value of the Board instance.
147 """Checks if a move (column) is legal.
150 move (int): The column index (0-6) to check.
153 bool: True if the move is legal, False otherwise.
155 return self.
_board.isLegalMove(move)
158 """Returns a new Board instance that is the mirror image of the current board.
161 Board: A new Board instance that is the mirror image.
168 """Returns the number of moves left until the board is full.
171 int: The number of moves left (0-42).
173 return self.
_board.movesLeft()
176 """Plays a move (column) for the current player.
179 move (int): The column index (0-6) where the token should be placed.
182 bool: True if the move was played successfully, False if the move was illegal.
184 return self.
_board.playMove(move)
187 """Plays a move on a copy of the current board and returns the new board.
190 move (int): The column index (0-6) where the token should be placed.
193 Board | None: A new Board instance with the move played, or None if the move was illegal.
195 new_board = self.
copy()
196 if new_board.play_move(move):
200 def set_board(self, board: list[list[int]] | list[int]) -> bool:
201 """Sets (overrides) the board to a specific state.
204 board (list[list[int]] | list[int]):
205 The new board state. Accepts:
206 - 2D array (list, tuple, numpy-array) with shape 7x6 or 6x7
207 - 1D sequence of ints: a move sequence of columns (e.g., [0, 0, 2, 2, 3, 3])
208 - String: A move sequence of columns as string (e.g., "002233...")
211 bool: True if the board was set successfully, False otherwise.
214 if isinstance(board, list):
215 return self.
_board.setBoard(board)
219 """Returns the board state as a 2D array (list of lists).
222 list[list[int]]: A 2D list representing the board state.
224 return self.
_board.toArray()
227 """Returns a string representation of the board to print on the command line.
230 str: A string representing the board (e.g., "002233...").
232 return self.
_board.toString()
235 """Returns a unique identifier for the current board state.
238 int: A unique integer identifier for the board state.
244 """Generates a random board state by playing a specified number of random moves.
247 n_ply (int): The number of random moves to play on the board.
248 forbid_direct_win (bool): If True, the board will have a state that would result in an immediate win.
250 bitbully_core.BoardCore.randomBoard(n_ply, forbid_direct_win)
253 """Resets the board to an empty state."""
254 self.
_board = bitbully_core.BoardCore()
bool __eq__(self, object value)
list[Board] all_positions(self, int up_to_n_ply, bool exactly_n)
Board|None play_move_on_copy(self, int move)
bool can_win_next(self, int|None move=None)
list[int] get_legal_moves(self)
bool play_move(self, int move)
None __init__(self, Sequence[Sequence[int]]|Sequence[int]|str|None board=None)
bool set_board(self, list[list[int]]|list[int] board)
list[list[int]] to_array(self)
None random_board(int n_ply, bool forbid_direct_win)
bool is_legal_move(self, int move)
bool __ne__(self, object value)