def test_next_move(): cur_ai = AI() current_board = BoardState.initial_state() answer1_board = BoardState.initial_state() answer2_board = BoardState.initial_state() current_board.load('board_3_in_a_row.pickle') answer1_board.load('board_3_in_a_row_ans1.pickle') answer2_board.load('board_3_in_a_row_ans2.pickle') assert (cur_ai.next_move(current_board, None)[0].board.all() == answer1_board.board.all() or cur_ai.next_move( current_board, None)[0].board == answer2_board.board.all())
def ai_1(board: BoardState) -> BoardState: """This AI will always choose the winning spot, if there is no winning spot it will place randomly """ cur_piece = board.cpiece if cur_piece is not None: for (x, y) in board.open_spots: move = find_win_spot(cur_piece, board) if move: return update_board_then_give_random(board, move) board.ai_random_move() return board
def ai_2(board: BoardState) -> BoardState: """This AI will always give a none-winable piece (if there is one) and will place randomly """ cur_piece = board.cpiece if cur_piece is None: board.cpiece_id = choose_none_winable_piece(board) else: board[choice(list(board.open_spots))] = board.cpiece_id board.cpiece_id = choose_none_winable_piece(board) if (board.cpiece_id is None) and not board.is_full: board.cpiece_id, _ = choice(list(board.unused_game_pieces)) return board
def game_loop(screen: Surface, board: BoardState, ai: AI): grid_size = screen.get_size()[0] // 8 player = 1 while True: for event in pygame.event.get(): if event.type == pygame.QUIT: return start_time = time.time() while True: new_board = ai.next_move(board if player == 1 else board.inverted()) if new_board is None: break else: board = new_board if player == 1 else new_board.inverted() if new_board.in_the_process_of_taking == False: player = player % 2 + 1 break if time.time() - start_time > 30.0: print('TL') break draw_board(screen, 0, 0, grid_size, board) pygame.display.flip()
class DraughtsTest(unittest.TestCase): MAX_MOVE_TIME = 3 def setUp(self): self.ai = AI(PositionEvaluation(), search_depth=2) self.board = BoardState() def test_ai_vs_ai(self): board = BoardState.initial_state() while not board.ended(): start_time = time() board = self.ai.next_move(board) finish_time = time() self.assertIsNotNone(board) elp_time = finish_time - start_time self.assertLess(elp_time, DraughtsTest.MAX_MOVE_TIME) def test_simple_move_forward(self): self.board.board[7, 0] = 1 result = self.ai.next_move(self.board) self.assertEqual(result.board[7, 0], 0) self.assertEqual(result.board[6, 1], 1) def test_simple_capt(self): self.board.board[7, 0] = 1 self.board.board[6, 1] = -1 result = self.ai.next_move(self.board) self.assertEqual(result.board[7, 0], 0) self.assertEqual(result.board[6, 1], 0) self.assertEqual(result.board[5, 2], 1) def test_king_creation(self): self.board.board[1, 0] = 1 result = self.ai.next_move(self.board) self.assertEqual(result.board[1, 0], 0) self.assertEqual(result.board[0, 1], 2) def test_king_capt(self): self.board.board[7, 0] = 2 self.board.board[1, 6] = -1 result = self.ai.next_move(self.board) self.assertEqual(result.board[7, 0], 0) self.assertEqual(result.board[1, 6], 0) self.assertEqual(result.board[0, 7], 2) def test_multi_move(self): self.board.board[7, 0] = 1 self.board.board[6, 1] = -1 self.board.board[4, 3] = -1 self.board.board[4, 5] = -1 result = self.board.copy() for i in range(3): result = self.ai.next_move(result) self.assertEqual(result.board[7, 0], 0) self.assertEqual(result.board[6, 1], 0) self.assertEqual(result.board[4, 3], 0) self.assertEqual(result.board[4, 5], 0) self.assertEqual(result.board[5, 6], 1)
def test_ai_vs_ai(self): board = BoardState.initial_state() while not board.ended(): start_time = time() board = self.ai.next_move(board) finish_time = time() self.assertIsNotNone(board) elp_time = finish_time - start_time self.assertLess(elp_time, DraughtsTest.MAX_MOVE_TIME)
def game_loop(screen: Surface, board: BoardState, ai: AI): grid_size = screen.get_size()[0] // 8 while True: for event in pygame.event.get(): if event.type == pygame.QUIT: return if event.type == pygame.KEYDOWN: if event.key == pygame.K_s: with open('save', 'wb') as f: f.write(pickle.dumps(board)) if event.key == pygame.K_l: with open('save', 'rb') as f: board = pickle.loads(f.read()) if board.ended(): continue if board.current_player == -1: pygame.display.set_caption(CAPTION + ' [Computing...]') start_time = time.time() new_board = ai.next_move(board) finish_time = time.time() elp_time = finish_time - start_time sleep_time = MOVE_TIME - elp_time if sleep_time > 0: time.sleep(sleep_time) pygame.display.set_caption(CAPTION) if new_board is not None: board = new_board if event.type == pygame.MOUSEBUTTONDOWN and event.button == 1: mouse_click_position = event.pos if event.type == pygame.MOUSEBUTTONUP and event.button == 1: new_x, new_y = [p // grid_size for p in event.pos] old_x, old_y = [p // grid_size for p in mouse_click_position] new_board = board.do_move(old_x, old_y, new_x, new_y) if new_board is not None: board = new_board draw_board(screen, 0, 0, grid_size, board) pygame.display.flip()
def ai_3(board: BoardState) -> BoardState: """This AI will always give a none-winable piece (if there is one) and will only choose winable placements when possible """ cur_piece = board.cpiece if cur_piece is not None: moved = False for (x, y) in board.open_spots: move = find_win_spot(cur_piece, board) if move: board[move] = board.cpiece_id moved = True break if not moved: board[choice(list(board.open_spots))] = board.cpiece_id board.cpiece_id = choose_none_winable_piece(board) else: board.cpiece_id = choose_none_winable_piece(board) if (board.cpiece_id is None) and not board.is_full: board.cpiece_id, _ = choice(list(board.unused_game_pieces)) return board
def game_loop(screen: Surface, board: BoardState, ai: AI): grid_size = screen.get_size()[0] // 8 while True: for event in pygame.event.get(): if event.type == pygame.QUIT: return if event.type == pygame.MOUSEBUTTONDOWN and event.button == 1: mouse_click_position = event.pos if event.type == pygame.MOUSEBUTTONUP and event.button == 1: new_x, new_y = [p // grid_size for p in event.pos] old_x, old_y = [p // grid_size for p in mouse_click_position] new_board = board.do_move(old_x, old_y, new_x, new_y) if new_board is not None: board = new_board if event.type == pygame.MOUSEBUTTONUP and event.button == 3: x, y = [p // grid_size for p in event.pos] board.board[ y, x] = (board.board[y, x] + 1 + 2) % 5 - 2 # change figure if event.type == pygame.KEYDOWN: if event.key == pygame.K_r: board = board.inverted() if event.key == pygame.K_SPACE: new_board = ai.next_move(board) if new_board is not None: board = new_board draw_board(screen, 0, 0, grid_size, board) pygame.display.flip()
def game_loop(screen: Surface, board: BoardState, ai: AI): grid_size = screen.get_size()[0] // game_set.board_size while True: for event in pygame.event.get(): if event.type == pygame.QUIT: return if event.type == pygame.MOUSEBUTTONUP: x, y = [p // grid_size for p in event.pos] if event.button == 1: # do move board.notification = None board = board.do_move(y, x) elif event.button == 3: # change figure board.board[y, x] = ((board.board[y, x] + 2) % 3) - 1 if event.type == pygame.KEYDOWN: if event.key == pygame.K_r: board = BoardState.initial_state() if event.key == pygame.K_s: board.save() if event.key == pygame.K_l: board = BoardState.load() if event.key == pygame.K_z: pass if (game_set.is_ai_enabled and event.key == pygame.K_SPACE and game_set.first_player_is_ai == board.is_first_player_turn): new_board = ai.next_move(board, None)[0] if new_board is not None: board = new_board if board.is_game_finished: board.notification = "Second" if board.is_first_player_turn \ else "First" board.notification += " player won! Press R to restart" draw_board(screen, 0, 0, grid_size, board) pygame.display.flip()
def __call__(self, board: BoardState) -> float: basic_value = [0] * game_set.win_len balance: float = 0 for y, x in product(range(game_set.board_size), range(game_set.board_size)): for vector in game_set.basic_vectors: max_y = y + vector[0] * (game_set.win_len - 1) max_x = x + vector[1] * (game_set.win_len - 1) if BoardState.is_coord_correct(max_y, max_x): for diff in range(game_set.win_len): basic_value[diff] = board.board[y + vector[0] * diff, x + vector[1] * diff] key_tuple = tuple(basic_value) balance += eval_score[key_tuple] return balance
def next_move(self, board: BoardState, top_res: Optional['int']) -> \ (Optional[BoardState], float): if self.depth == 0: return board, self.position_evaluation(board) moves = board.get_good_possible_moves() best_value = None best_board = None board_config = board.is_first_player_turn ^ 1 for move in moves: cur_board, cur_score = AI(self.position_evaluation, self.depth - 1).next_move( move, best_value) if cur_board is None: continue if top_res is not None and ((top_res > cur_score) == board_config): return None, 0 if best_value is None or (best_value > cur_score) == board_config: best_board, best_value = move, cur_score return best_board, best_value
def game_loop(screen: Surface, board: BoardState, ai: AI): max_y, max_x = screen.get_size()[1], screen.get_size()[0] elem_size = max_y // 16 # размер одной клетки save_box = InputBox('SAVE', max_y + (max_x - max_y) * 625 // 10000, max_y * 4 // 5, 250, 30) load_box = InputBox('LOAD', max_y + (max_x - max_y) * 625 // 10000, max_y * 4 // 5 + 50, 250, 30) while True: for event in pygame.event.get(): if event.type == pygame.QUIT: return if event.type == pygame.KEYDOWN and event.key == pygame.K_RETURN: return save_name = save_box.handle_event(event) load_name = load_box.handle_event(event) if save_name: db = shelve.open(save_name) db[save_name] = board db.close() elif load_name: if os.path.exists(os.path.join(os.getcwd(), load_name + '.db')): db = shelve.open(load_name) board = db[load_name] db.close() else: print('No such file:(') if event.type == pygame.MOUSEBUTTONDOWN and event.button == 1: mouse_click_position = event.pos to_x, to_y = [(p - elem_size // 2) // elem_size for p in mouse_click_position] try: new_board = board.do_move(to_x, to_y) except EndGame as EG: print(EG.winner, 'bruh') board = EG.board board.current_player *= 2 new_board = None # draw_board(screen, elem_size, elem_size, elem_size, board) # screen.fill((23, 123, 234)) # pygame.display.flip() # print('--------------') # print(new_board) # pygame.time.wait(1000) # return # screen.fill(color) # screen.blit(InputBox.FONT.render(('black' if EG.winner == 1 else 'white') + 'player won!!!', True, (0, 0, 0)), (0.7 * screen.get_size()[0], 0.2 * screen.get_size()[1])) # time.sleep(3) # return if new_board is not None: board = new_board if event.type == pygame.KEYDOWN and event.key == pygame.K_SPACE: print('kek') # print(ai.next_move(board)) again = True while again: try: position_evalution, *move = ai.next_move(board, (0, 0)) again = False except TypeError: pass # print(position_evalution) # print(move) # print((ai.next_move(board))) print( '+=+=+=++=++++++++=+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=' ) # break move = move[0] print(f'my move = {move}') try: new_board = board.do_move(move[1], move[0]) except EndGame as EG: print(EG.winner, 'bruh') board = EG.board board.current_player *= 2 new_board = None if new_board is not None: board = new_board save_box.update() load_box.update() draw_board(screen, elem_size, elem_size, elem_size, board) save_box.draw(screen) load_box.draw(screen) pygame.display.flip()
def game_loop(screen: Surface, board: BoardState, ai: AI): grid_size = screen.get_size()[0] // 8 previous_board = board visible_board = board step = 0 flag = True while True: for event in pygame.event.get(): if event.type == pygame.QUIT: return if event.type == pygame.MOUSEBUTTONDOWN and event.button == 1: mouse_click_position = event.pos if event.type == pygame.MOUSEBUTTONUP and event.button == 1: new_x, new_y = [p // grid_size for p in event.pos] old_x, old_y = [p // grid_size for p in mouse_click_position] new_board = board.do_move(old_x, old_y, new_x, new_y) if new_board is not None: previous_board = board board = new_board.inverted() if step % 2 == 0: visible_board = new_board else: visible_board = board step += 1 if board.get_winner != 0: flag = False #if event.type == pygame.MOUSEBUTTONUP and event.button == 3: #x, y = [p // grid_size for p in event.pos] #board.board[y, x] = (board.board[y, x] + 1 + 2) % 5 - 2 # change figure if event.type == pygame.KEYDOWN: if event.key == pygame.K_r: visible_board = visible_board.inverted() elif event.key == pygame.K_n: board = board.initial_state() visible_board = board step = 0 elif event.key == pygame.K_s: save_board(board, './src/save_board.bin') save_board(visible_board, './src/save_visible.bin') elif event.key == pygame.K_l: board = load_board('./src/save_board.bin') visible_board = load_board('./src/save_visible.bin') flag = True if board.current_player == visible_board.current_player: step = 0 else: step = 1 elif event.key == pygame.K_1: board = load_board( './src/test_boards/test_board_1_visible') visible_board = load_board( './src/test_boards/test_board_1_board') flag = True if board.current_player == visible_board.current_player: step = 0 else: step = 1 elif event.key == pygame.K_2: board = load_board( './src/test_boards/test_board_2_visible') visible_board = load_board( './src/test_boards/test_board_2_board') flag = True if board.current_player == visible_board.current_player: step = 0 else: step = 1 elif event.key == pygame.K_z: board = previous_board elif event.key == pygame.K_SPACE: new_board = ai.next_move(board) if new_board is not None: previous_board = board board = new_board.inverted() if step % 2 == 0: visible_board = new_board else: visible_board = board step += 1 if board.get_winner != 0: flag = False draw_board(screen, 0, 0, grid_size, visible_board) if not flag: draw_final_message(screen, board.get_winner) pygame.display.flip()
(self.next_move(new_board, move, current_depth + 1), move)) else: evolution_tree.append( self.next_move(new_board, move, current_depth + 1)) except EndGame as EG: if current_depth == 0: return self.position_evaluation(EG.board, move, player), move else: return self.position_evaluation(EG.board, move, player) if maximize: board.board[move[0], move[1]] = 0 return max(evolution_tree) elif not maximize: board.board[move[0], move[1]] = 0 return min(evolution_tree) if __name__ == '__main__': import numpy as np board = np.zeros(shape=(15, 15), dtype=np.int8) board = BoardState(board, 1) board.board[5, 5] = 1 board.board[6, 6] = 1 board.board[7, 7] = 1 board.board[8, 8] = 1 board.board[9, 9] = 1
def next_move(self, board: BoardState, move, current_depth=0) -> Optional[BoardState]: maximize = True if current_depth % 2 == 0 else False if maximize: player = board.current_player limit_score = -100000 elif not maximize: player = board.current_player * (-1) limit_score = 100000 if board == None: if maximize: return 1000000 elif not maximize: return -1000000 # new_board = board.copy() if current_depth == self.search_depth: # print(f'depth = {current_depth}') return self.position_evaluation(board, move, player) if current_depth == 0: highY, leftX, lowY, rightX = Restriction_first(board) # # print('rest_arr first = \n', rest_arr) # # print(f'delta_y = {delta_y}, delta_x = {delta_x}') else: highY, leftX, lowY, rightX = Restriction_first(board) # delta_y, delta_x, rest_arr = Restriction_first(new_board) # # print('rest_ arr = \n', rest_arr) # # print(f'delta_y = {delta_y}, delta_x = {delta_x}') moves = [(y, x) for y in range(highY, lowY+1) for x in range(leftX, rightX+1) if board.board[y, x] == 0] if len(moves) == 0: # if maximize: # return 1000000 # elif not maximize: return -1000000 # print(current_depth) # print("moves", moves) evolution_tree = [] for move in moves: try: # print('move', move) # # print(f'current depth = {current_depth}, self.depth = {self.search_depth}') new_board = board.do_move(move[1], move[0]) # if type(new_board) == 'NoneType': # # print(new_board) # if new_board == None: # if maximize: # return 10000 # elif not maximize: # return -10000 current_score = self.position_evaluation(new_board, move, player) # player = кто только что сделала ход move # print('move = ', move, 'score = ', current_score) if (maximize and current_score >= limit_score) or (not maximize and current_score <= limit_score): # todo : may be to fix coeficient # if (current_score >= limit_score): # todo : may be to fix coeficient limit_score = current_score if current_depth == 0: # # print('move = ', move, ) evolution_tree.append((self.next_move(new_board, move, current_depth + 1), move)) else: # # print(f'type = {type(board.do_move(move[0], move[1]))}') evolution_tree.append(self.next_move(new_board, move, current_depth + 1)) except EndGame as EG: if current_depth == 0: return self.position_evaluation(EG.board, move, player), move else: return self.position_evaluation(EG.board, move, player) if maximize: # print(f'current depth = {current_depth}, evoltion = {max(evolution_tree)}') # print(f'max = {max(evolution_tree)}') board.board[move[0], move[1]] = 0 return max(evolution_tree) elif not maximize: # print(f'current depth = {current_depth}, evoltion = {min(evolution_tree)}') # print(f'min = {min(evolution_tree)}') board.board[move[0], move[1]] = 0 return min(evolution_tree)
def game_loop(screen: Surface, board: BoardState, ai: AI): grid_size = screen.get_size()[0] // 8 for i, j in product(range(8), range(8)): board.board[i][j] = 0 board.board[7][0] = 1 board.board[7][2] = 1 board.board[7][4] = 1 board.board[7][6] = 1 board.board[5][6] = 1 board.board[5][4] = -1 board.board[5][2] = -1 board.board[3][2] = -1 board.board[3][6] = -1 board.board[1][4] = -1 board.board[1][6] = -1 player = 1 while True: for event in pygame.event.get(): if event.type == pygame.QUIT: return if event.type == pygame.KEYDOWN: if event.key == pygame.K_SPACE: while True: new_board = ai.next_move(board if player == 1 else board.inverted()) if new_board is None: break else: board = new_board if player == 1 else new_board.inverted() if new_board.in_the_process_of_taking == False: player = player % 2 + 1 break draw_board(screen, 0, 0, grid_size, board) pygame.display.flip()
def setUp(self): self.ai = AI(PositionEvaluation(), search_depth=2) self.board = BoardState()
def next_move(self, board: BoardState, move, current_depth=0) -> Optional[BoardState]: maximize = True if current_depth % 2 == 0 else False if maximize: player = board.current_player limit_score = -100000 elif not maximize: player = board.current_player * (-1) limit_score = 100000 if board == None: if maximize: return 1000000 elif not maximize: return -1000000 # new_board = board.copy() if current_depth == self.search_depth: return self.position_evaluation(board, move, player) if current_depth == 0: highY, leftX, lowY, rightX = Restriction_first(board) else: highY, leftX, lowY, rightX = Restriction_first(board) moves = [(y, x) for y in range(highY, lowY + 1) for x in range(leftX, rightX + 1) if board.board[y, x] == 0] if len(moves) == 0: return -1000000 evolution_tree = [] for move in moves: try: new_board = board.do_move(move[1], move[0]) current_score = self.position_evaluation( new_board, move, player) # player = кто только что сделала ход move if (maximize and current_score >= limit_score) or ( not maximize and current_score <= limit_score ): # todo : may be to fix coeficient limit_score = current_score if current_depth == 0: evolution_tree.append( (self.next_move(new_board, move, current_depth + 1), move)) else: evolution_tree.append( self.next_move(new_board, move, current_depth + 1)) except EndGame as EG: if current_depth == 0: return self.position_evaluation(EG.board, move, player), move else: return self.position_evaluation(EG.board, move, player) if maximize: board.board[move[0], move[1]] = 0 return max(evolution_tree) elif not maximize: board.board[move[0], move[1]] = 0 return min(evolution_tree)
if event.key == pygame.K_s: board.save_board("checkers.txt") if event.key == pygame.K_l: board.open_saved_board("checkers.txt") if event.key == pygame.K_SPACE: new_board = board.inverted() while True: new_board = ai.next_move(new_board) if new_board is None or new_board.in_the_process_of_taking == False: break if new_board is not None: board = new_board.inverted() draw_board(screen, 0, 0, grid_size, board) pygame.display.flip() pygame.init() screen: Surface = pygame.display.set_mode([512, 512]) ai = AI(PositionEvaluation(), search_depth=4) game_loop(screen, BoardState.initial_state(), ai) pygame.quit()
def game_loop(screen: Surface, board: BoardState, ai: AI): grid_size = screen.get_size()[0] // 8 # размер одной клетки count = -1 while True: # print(pygame.event.get()) for event in pygame.event.get(): if event.type == pygame.QUIT: return if event.type == pygame.MOUSEBUTTONDOWN and event.button == 1: mouse_click_position = event.pos # print(f'event.pos = {event.pos}') if event.type == pygame.MOUSEBUTTONUP and event.button == 1: new_x, new_y = [p // grid_size for p in event.pos] old_x, old_y = [p // grid_size for p in mouse_click_position] try: new_board = board.do_move(old_x, old_y, new_x, new_y) except EndGame: return if new_board is not None: board = new_board if event.type == pygame.MOUSEBUTTONUP and event.button == 3: # ???????????????????????? x, y = [p // grid_size for p in event.pos] board.board[ y, x] = (board.board[y, x] + 1 + 2) % 5 - 2 # change figure if event.type == pygame.KEYDOWN: if event.key == pygame.K_r: board = board.inverted() elif event.key == pygame.K_SPACE: new_board = ai.next_move(board) if new_board is not None: board = new_board elif event.key == pygame.K_s: count += 1 count %= 5 name = f'game{count}' # name = input_name() db = shelve.open(name) db[name] = board db.close() # todo elif event.key == pygame.K_l: load = True elif event.key in (pygame.K_0, pygame.K_1, pygame.K_2, pygame.K_3, pygame.K_4) and load: name = 'game' + (chr(event.key)) if os.path.exists(os.path.join(os.getcwd(), name + '.db')): db = shelve.open(name) board = db[name] db.close() load = False else: print('No such file:(') draw_board(screen, 0, 0, grid_size, board) pygame.display.flip()