aboutsummaryrefslogtreecommitdiffstats
path: root/python/board.py
diff options
context:
space:
mode:
Diffstat (limited to 'python/board.py')
-rw-r--r--python/board.py110
1 files changed, 110 insertions, 0 deletions
diff --git a/python/board.py b/python/board.py
new file mode 100644
index 0000000..36cfe8c
--- /dev/null
+++ b/python/board.py
@@ -0,0 +1,110 @@
+from GameState import GameState
+
+class Board(GameState):
+
+ # Interface methods
+
+ def __init__(self, nb_rows, nb_cols, player):
+
+ # Basic initialization
+ self.nb_rows = nb_rows
+ self.nb_cols = nb_cols
+ self.player = player # 1 or 2
+ self.scores = [0, 0, 0]
+ self.max_score = nb_rows*nb_cols
+
+ # Construct edges and nodes matrix
+ self.edges = [] # Boolean, true means uncut
+ self.nodes = [] # Represents valence of nodes from strings-and-coins
+ for x in range(self.nb_cols):
+ self.edges.append([True]*self.nb_rows)
+ self.edges.append([True]*(self.nb_rows + 1))
+ self.nodes.append([4]*self.nb_rows)
+ self.edges.append([True]*self.nb_rows)
+
+ # Construct all possible moves
+ self.moves_left = set() # Moves are represented as ints
+ for x in range(len(self.edges)):
+ for y in range(len(self.edges[x])):
+ self.moves_left.add(self.coords_to_edge(x, y))
+
+ # TODO: chain updating
+ # Initialize chains
+ # Chains are represented as lists of nodes
+ self.closed_chains = [] # Chains which start and end in nodes of valence
+
+ @property
+ def game_result(self):
+
+ own_score = self.scores[self.player]
+ opponent_score = self.scores[self.player % 2 + 1]
+ if len(self.moves_left) == 0:
+ diff = own_score - opponent_score
+ if diff > 0:
+ return 1
+ elif diff < 0:
+ return 0
+ else:
+ return 0.5
+ else:
+ # Check if one player already has at least half of all points
+ if own_score > self.max_score//2:
+ return 1
+ elif opponent_score > self.max_score//2:
+ return 0
+ else:
+ return None
+
+ def get_moves(self):
+ return self.moves_left
+
+ def get_random_move(self):
+ moves = self.get_moves()
+ return choice(tuple(moves)) if moves != set() else None
+
+ def play_move(self, move):
+ x, y = self.edge_to_coords(move)
+ self.edges[x][y] = False
+ self.moves_left.remove(move)
+
+ # Update valence
+ if x%2 == 0:
+ # Horizontal edge, decrease valence of left and right nodes
+ for node_x in x//2 - 1, x//2:
+ if node_x >= 0 and node_x < nb_cols:
+ self.nodes[node_x][y] -= 1
+ else:
+ # Vertical edge, decrease valence of top and bottom nodes
+ for node_y in y - 1, y:
+ if node_y >= 0 and node_y < nb_rows:
+ self.nodes[x//2][node_y] -= 1
+
+ # TODO: chain updating
+
+ # Own methods
+
+ def undo_move(self, move):
+ x, y = self.edge_to_coords(move)
+ self.edges[x][y] = True
+ self.moves_left.add(move)
+
+ # Update valence
+ if x%2 == 0:
+ # Horizontal edge, decrease valence of left and right nodes
+ for node_x in x//2 - 1, x//2:
+ if node_x >= 0 and node_x < nb_cols:
+ self.nodes[node_x][y] += 1
+ else:
+ # Vertical edge, decrease valence of top and bottom nodes
+ for node_y in y - 1, y:
+ if node_y >= 0 and node_y < nb_rows:
+ self.nodes[x//2][node_y] += 1
+
+ # TODO: chain updating
+
+ def coords_to_edge(self, x, y):
+ return x*(self.nb_cols + 1) + y
+
+ def edge_to_coords(self, move):
+ return move//(self.nb_cols + 1), move%(self.nb_cols + 1)
+