def first_move(): print( '|----------------------------------------------------------------------------|' ) print(' TEST OBJECTIVE: choose the optimal first move\n') start_time = time() shape = (4, 5) game = DynamicGame(grid_shape=shape) print('\n', game) solver = Solver(game.gameState) game.step(solver.get_action()) end_time = time() assert (game.gameState.board[17] == 1) print('\n TEST SUCCESSFUL:', solver.nodes_explored, 'nodes explored in ', round(end_time - start_time, 2), 'seconds.') print( '|----------------------------------------------------------------------------|' )
def __init__(self, shape=(4, 5), human_first=True): # Game environment self.shape = shape self.env = DynamicGame(grid_shape=shape) self.WINDOW_DIMS = (shape[1] * self.CELL_SIZE, shape[0] * self.CELL_SIZE) self.main_window = pg.display.set_mode(self.WINDOW_DIMS, 0, 32) self.main_window.fill((255, 255, 255)) self.render(self.main_window) pg.display.update() while 1: # Check if AI plays first if not human_first: self.update_AI() # Check for draw if self.env.gameState.isEndGame: break # Ask user for valid command event = self.choose_move() # User wishes to quit if event.type == pg.QUIT: pg.quit() sys.exit() # User selects a valid command elif event.type == pg.MOUSEBUTTONDOWN: try_again = self.update_player(event) while try_again: event = self.choose_move() try_again = self.update_player(event) if self.env.gameState.isEndGame: break # Check if AI plays second if human_first: self.update_AI() # Check for draw if self.env.gameState.isEndGame: break
def positive_alignments(shape=(6, 7)): print( '|----------------------------------------------------------------------------|' ) print(' TEST OBJECTIVE: test all possible alignments in grid of', shape, 'shape') # Start with an empty board and node game = DynamicGame(shape) solver = Solver(game.gameState) node = solver.root_node # Binary values leading to the victory of the first player or second winners = [] index = np.flip(np.arange(0, node.WIDTH * (node.HEIGHT + 1), dtype=np.int64).reshape( (node.WIDTH, (node.HEIGHT + 1))), axis=1).transpose() # Vertical alignments are possible if shape[0] >= 4: for col in range(node.WIDTH): for row in range(1, node.HEIGHT - 2): winners.append( sum(map(lambda x: 2**x, index[row:row + 4, col]))) # Horizontal alignments are possible if shape[1] >= 4: for row in range(node.HEIGHT): for col in range(node.WIDTH - 3): winners.append( sum(map(lambda x: 2**x, index[row, col:col + 4]))) # Diagonal alignments are possible if shape[0] >= 4 and shape[1] >= 4: for col in range(node.WIDTH - 3): for row in range(1, node.HEIGHT - 2): indexes = [] for c in range(4): indexes.append(index[row + c, col + c]) winners.append(sum(map(lambda x: 2**x, indexes))) for col in range(node.WIDTH - 1, 2, -1): for row in range(node.HEIGHT - 3, 0, -1): indexes = [] for c in range(4): indexes.append(index[row + c, col - c]) winners.append(sum(map(lambda x: 2**x, indexes))) for winner in winners: assert (node.alignment(winner)) print('\n TEST SUCCESSFUL') print( '|----------------------------------------------------------------------------|' )
def counter_double_menace(): print( '|----------------------------------------------------------------------------|' ) print(' TEST OBJECTIVE: counter the double menace\n') start_time = time() shape = (4, 5) sequence = [18, 13, 17] game = DynamicGame(grid_shape=shape) for action in sequence: game.step(action) print('Initial state: \n', game) solver = Solver(game.gameState) game.step(solver.get_action()) print('\n', game) end_time = time() assert (game.gameState.board[16] == -1) print('\n TEST SUCCESSFUL:', solver.nodes_explored, 'nodes explored in ', round(end_time - start_time, 2), 'seconds.') print( '|----------------------------------------------------------------------------|' )
def double_menace(): print( '|----------------------------------------------------------------------------|' ) print(' TEST OBJECTIVE: complete the double menace\n') start_time = time() shape = (4, 5) sequence = [18, 13, 17, 12] game = DynamicGame(grid_shape=shape) for action in sequence: game.step(action) print('Initial state: \n', game) total_nodes = 0 for x in range(3): solver = Solver(game.gameState) game.step(solver.get_action()) total_nodes += solver.nodes_explored print('\n', game) end_time = time() assert (game.gameState.board[15] == 1 and game.gameState.board[16] == 1 or game.gameState.board[16] == 1 and game.gameState.board[19] == 1) print('\n TEST SUCCESSFUL:', total_nodes, ' nodes explored in ', round(end_time - start_time, 2), 'seconds.') print( '|----------------------------------------------------------------------------|' )
class LocalPlay: CELL_SIZE = 100 def __init__(self, shape=(4, 5), human_first=True): # Game environment self.shape = shape self.env = DynamicGame(grid_shape=shape) self.WINDOW_DIMS = (shape[1] * self.CELL_SIZE, shape[0] * self.CELL_SIZE) self.main_window = pg.display.set_mode(self.WINDOW_DIMS, 0, 32) self.main_window.fill((255, 255, 255)) self.render(self.main_window) pg.display.update() while 1: # Check if AI plays first if not human_first: self.update_AI() # Check for draw if self.env.gameState.isEndGame: break # Ask user for valid command event = self.choose_move() # User wishes to quit if event.type == pg.QUIT: pg.quit() sys.exit() # User selects a valid command elif event.type == pg.MOUSEBUTTONDOWN: try_again = self.update_player(event) while try_again: event = self.choose_move() try_again = self.update_player(event) if self.env.gameState.isEndGame: break # Check if AI plays second if human_first: self.update_AI() # Check for draw if self.env.gameState.isEndGame: break @staticmethod def choose_move(): while True: event = pg.event.wait() if event.type == pg.QUIT: pg.quit() sys.exit() elif event.type == pg.MOUSEBUTTONDOWN: return event def render(self, main_window): for x in range(self.shape[1]): for y in range(self.shape[0]): pg.draw.rect(main_window, (255, 255, 255), (x * self.CELL_SIZE, y * self.CELL_SIZE, self.CELL_SIZE, self.CELL_SIZE)) for x in range(self.shape[1]): pg.draw.line(main_window, (0, 0, 0), (x * self.CELL_SIZE, 0), (x * self.CELL_SIZE, self.shape[0] * self.CELL_SIZE)) pg.draw.line(main_window, (0, 0, 0), (0, x * self.CELL_SIZE), (self.shape[1] * self.CELL_SIZE, x * self.CELL_SIZE)) matrix = self.env.gameState.board.reshape(self.shape) for x in range(self.shape[1]): for y in range(self.shape[0]): if matrix[y, x] == 1: pg.draw.circle(main_window, (255, 0, 0), (int((x + 0.5) * self.CELL_SIZE), int((y + 0.5) * self.CELL_SIZE)), self.CELL_SIZE // 2, 0) elif matrix[y, x] == -1: pg.draw.circle(main_window, (0, 255, 0), (int((x + 0.5) * self.CELL_SIZE), int((y + 0.5) * self.CELL_SIZE)), self.CELL_SIZE // 2, 0) def update_player(self, event): x = event.pos[0] // self.CELL_SIZE y = event.pos[1] // self.CELL_SIZE action = y * self.shape[1] + x try_again = True if action in self.env.gameState.allowedActions: next_state, _, _, _ = self.env.step(action) try_again = False self.render(self.main_window) pg.display.update() return try_again def update_AI(self): solver = Solver(self.env.gameState) action = solver.get_action() self.env.step(action) self.render(self.main_window) pg.display.update()
def fill_position_mask(shape=(6, 7)): print( '|----------------------------------------------------------------------------|' ) print(' TEST OBJECTIVE: test binary representation of grid of', shape, 'shape') # Start with an empty board and node game = DynamicGame(grid_shape=shape) solver = Solver(game.gameState) node = solver.root_node # Node should be empty assert (node.position == 0 and node.mask == 0) # Every column should be playable for col in range(node.WIDTH): assert (node.can_play(col)) # Move sequence (row, col) move_order_h = [] move_order_v = [] # Fill the board left to right, bottom to top for row in range(node.HEIGHT): for col in range(node.WIDTH): move_order_h.append((row, col)) # Fill the board bottom to top, lef to right for col in range(node.WIDTH): for row in range(node.HEIGHT): move_order_v.append((row, col)) for i in range(0, 2): solver = Solver(game.gameState) node = solver.root_node played_cells = [] if i == 0: moves = move_order_h else: moves = move_order_v for row, col in moves: # Current player plays a move played_cells.append(col * (node.HEIGHT + 1) + row) node.play(col) # Compute what should be position of the current player expected_position = 0 for idx, cell in enumerate(played_cells): # It is the starting players turn if node.total_moves % 2 == 0: if idx % 2 == 0: expected_position += 2**cell # It is the second players turn else: if idx % 2 == 1: expected_position += 2**cell # The value of the position is the sum of 2**cell for all cell played by the current player. assert (node.position == expected_position) # The value of the mask is the sum of 2**cell for all cell played. assert (node.mask == sum(map(lambda x: 2**x, played_cells))) # Node should be full at this point and have no legal moves left for col in range(node.WIDTH): assert (not node.can_play(col)) print('\n TEST SUCCESSFUL') print( '|----------------------------------------------------------------------------|' )