def callback_query(call): chat_id = call.message.chat.id base = SQLighter(config.database_name) player = base.select_single(chat_id) i = int(call.data[0]) j = int(call.data[1]) if not utils.update_board(chat_id, i, j, True): bot.answer_callback_query(call.id, 'Выберите пустую ячейку!') else: if utils.check_win(chat_id): bot.send_message(chat_id, 'Поздравляю, ты победил(а)!') return elif player[2] == 8: bot.send_message(chat_id, 'Победила дружба!') return utils.bot_move(chat_id) if utils.check_win(chat_id): bot.send_message(chat_id, 'К сожалению, ты проиграл!') return elif player[2] == 7: bot.send_message(chat_id, 'Победила дружба!') return global prev_msg if prev_msg != '': bot.delete_message(chat_id, prev_msg) msg = bot.send_message(chat_id, 'Твой ход!', reply_markup=utils.create_markup(chat_id)) prev_msg = msg.message_id
def _selection(self, root_id): node_id = root_id while self.tree[node_id]['n'] > 0: win_index = utils.check_win(self.tree[node_id]['board'], self.win_mark) if win_index != 0: return node_id, win_index qu = {} ids = [] total_n = 0 for action_idx in self.tree[node_id]['child']: edge_id = node_id + (action_idx, ) n = self.tree[edge_id]['n'] total_n += n for action_index in self.tree[node_id]['child']: child_id = node_id + (action_index, ) n = self.tree[child_id]['n'] q = self.tree[child_id]['q'] p = self.tree[child_id]['p'] u = self.c_puct * p * np.sqrt(total_n) / (n + 1) qu[child_id] = q + u max_value = max(qu.values()) ids = [key for key, value in qu.items() if value == max_value] node_id = ids[np.random.choice(len(ids))] win_index = utils.check_win(self.tree[node_id]['board'], self.win_mark) return node_id, win_index
def minimax(self, board, move, computerChar, playerChar, depth=0): """ Implements the minimax algorithm. Returns 1 : computer has won. Returns -1 when player wins. When it's the computer's turn and it has to return a value to its parent, the maximum value from the array is chosen else, the minimum value. """ [is_win, who_won] = utils.check_win(board, computerChar, playerChar) if is_win == 2: return 0 if is_win == 1: if who_won == computerChar: return 1 if who_won == playerChar: return -1 ret_list = [] for i in range(9): if board[i] == '-': if move == computerChar: next_move = playerChar else: next_move = computerChar board[i] = move minimax_val = self.minimax(board, next_move, computerChar, playerChar, depth + 1) board[i] = '-' ret_list.append(minimax_val) if depth == 0: return ret_list if move == computerChar: return max(ret_list) else: return min(ret_list)
def abprune(board, depth, Max, alpha, beta): # Max - True for maximizer , False for minimizer value_board = utils.check_win(board) # printer(board,value_board) if value_board != 2: return value_board # if game-over return winner.. moves = utils.get_moves_left(board) if Max: best = -99 for move in moves: board[move] = 1 val = abprune(board, depth + 1, False, alpha, beta) best = max(best, val) board[move] = 9 alpha = max(alpha, best) if beta <= alpha: break return best else: best = 99 for move in moves: board[move] = 0 val = abprune(board, depth + 1, True, alpha, beta) best = min(best, val) board[move] = 9 beta = min(beta, best) if beta <= alpha: break return best
def decide_winner(win_conditions, size, board, move): winner = utils.check_win(win_conditions, board) if winner != -1: print("The winner is {}".format("X" if winner == 1 else "O")) return True elif move >= size * size: print("No winner") return True
def _expansion_simulation(self, leaf_id, win_index): leaf_board = self.tree[leaf_id]['board'] current_player = self.tree[leaf_id]['player'] if win_index == 0: # expansion actions = utils.valid_actions(leaf_board) for action in actions: action_index = action[1] child_id = leaf_id + (action_index, ) child_board = utils.get_board(child_id, self.board_size) next_turn = utils.get_turn(child_id) self.tree[child_id] = { 'board': child_board, 'player': next_turn, 'parent': leaf_id, 'child': [], 'n': 0., 'w': 0., 'q': 0. } self.tree[leaf_id]['child'].append(action_index) if self.tree[leaf_id]['parent']: # simulation board_sim = leaf_board.copy() turn_sim = current_player while True: actions_sim = utils.valid_actions(board_sim) action_sim = actions_sim[np.random.choice( len(actions_sim))] coord_sim = action_sim[0] if turn_sim == 0: board_sim[coord_sim] = 1 else: board_sim[coord_sim] = -1 win_idx_sim = utils.check_win(board_sim, self.win_mark) if win_idx_sim == 0: turn_sim = abs(turn_sim - 1) else: reward = utils.get_reward(win_idx_sim, leaf_id) return reward else: # root node don't simulation reward = 0. return reward else: # terminal node don't expansion reward = 1. return reward
def two_player(self, board): ''' Play in 2 player mode ''' keyboardIndexMapping = constants.keyboardIndexMapping playerOne, playerTwo, playerOneChar, playerTwoChar, whichPlayerFirst = utils.getTwoPlayerDetails( ) move_mapping = {playerOne: playerOneChar, playerTwo: playerTwoChar} if whichPlayerFirst == 1: chance = playerOne else: chance = playerTwo while (utils.check_win(board, playerOneChar, playerTwoChar)[0] == 0): utils.clearScreen() utils.display_board(board) print(chance + ": Your chance") index = int(input()) if index > 9 or index < 1: utils.clearScreen() continue index = keyboardIndexMapping[index] if (board[index] != '-'): continue board[index] = move_mapping[chance] if (chance == playerOne): chance = playerTwo else: chance = playerOne [isWin, whoWon] = utils.check_win(board, playerOneChar, playerTwoChar) if (isWin == 2): utils.clearScreen() utils.display_board(board) print("It's a tie") if (isWin == 1): utils.clearScreen() utils.display_board(board) if (whoWon == playerOneChar): print(playerOne + " won!") else: print(playerTwo + " won!")
def _selection(self, root_id): node_id = root_id # 한 번이라도 시뮬레이션이 이루어진 노드에서만 선택 while self.tree[node_id]['n'] > 0: # node_id로부터 보드의 현 상태를 생성하고 승패를 판단함 board = utils.get_board(node_id, self.board_size) win_index = utils.check_win(board, self.win_mark) if win_index != 0: return node_id, win_index # 해당 노드에서 승패가 결정나면 node_id 와 win_index(승패결과) 반환 qu = {} # q + u ids = [] # key에 child_id와 value에 qu가 입력될 dict total_n = 0 # 해당 부모노드에 포함된 자식노드들 시뮬레이션 수의 합 # 모든 자식노드들의 n값을 더해 total_n을 구함 for action_idx in self.tree[node_id]['child']: edge_id = node_id + (action_idx, ) n = self.tree[edge_id]['n'] total_n += n # 모든 자식노드들의 q+u 값을 구함 for i, action_index in enumerate(self.tree[node_id]['child']): child_id = node_id + (action_index, ) n = self.tree[child_id]['n'] q = self.tree[child_id]['q'] p = self.tree[child_id]['p'] u = self.c_puct * p * np.sqrt(total_n) / (n + 1) qu[child_id] = q + u max_value = max(qu.values()) # qu중 최대값을 구함 ids = [key for key, value in qu.items() if value == max_value ] # qu최대값에 해당하는 child_id와 value를 dict에 입력 node_id = ids[np.random.choice(len(ids))] # 최대값 중 하나에 해당하는 노드를 선택 # node_id로부터 보드의 현 상태를 생성하고 승패를 판단함 board = utils.get_board(node_id, self.board_size) win_index = utils.check_win(board, self.win_mark) return node_id, win_index
def test_check_win__lose_count_reset(): """If count is not reset, then this will be a false win """ board = [ [0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0], [1, 1, 0, 0, 0, 0, 0], [1, 1, 0, 2, 0, 0, 0], [2, 1, 2, 2, 2, 0, 0], ] assert utils.check_win(board, 2) == []
def _selection(self, root_id): node_id = root_id while self.tree[node_id]['n'] > 0: # if it is leaf node board = utils.get_board(node_id, self.board_size, self.win_mark) win_index = utils.check_win(board, self.win_mark) if win_index != 0: # if the game is over and the current node is not leaf return node_id, win_index qu = {} ids = [] total_n = 0 for action_idx in self.tree[node_id]['child']: edge_id = node_id + (action_idx, ) n = self.tree[edge_id]['n'] total_n += n # the total number of visit of child nodes # PUCT calculation for i, action_index in enumerate(self.tree[node_id]['child']): child_id = node_id + (action_index, ) # history + action visited previously n = self.tree[child_id]['n'] q = self.tree[child_id]['q'] p = self.tree[child_id]['p'] u = self.c_puct * p * np.sqrt(total_n) / (n + 1 ) # 2nd term of PUCT qu[child_id] = q + u max_value = max(qu.values()) ids = [key for key, value in qu.items() if value == max_value] # argmax indices node_id = ids[np.random.choice( len(ids))] # key & value of seleted index among argmax indices board = utils.get_board(node_id, self.board_size, self.win_mark) win_index = utils.check_win(board, self.win_mark) return node_id, win_index
def test_check_win(): logger.debug('Testing check_win() from minimax.py') state = [['X', None, None], ['O', 'X', None], [None, 'O', 'X']] assert (check_win(state, 'X') == True) state = [[None, 'X', 'O'], [None, 'X', None], [None, 'O', 'X']] assert (check_win(state, 'X') == False) state = [['X', 'O', None], [None, 'X', None], [None, 'O', 'X']] assert (check_win(state, 'O') == False) state = [['O', None, 'X'], [None, None, 'X'], [None, 'O', 'X']] assert (check_win(state, 'X') == True) state = [['X', 'O', None], ['X', 'O', None], ['X', 'O', 'X']] assert (check_win(state, 'X') == True) assert (check_win(state, 'O') == True) logger.debug('Passed')
def test_check_win__diagonal_fwd_slash_far_left(): board = [ [0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 1, 0, 0], [0, 0, 2, 1, 1, 0, 0], [0, 0, 1, 1, 2, 0, 0], [0, 1, 2, 2, 2, 0, 0], ] diff = DeepDiff(utils.check_win(board, 2), [[(5, 1), (4, 2), (3, 3), (2, 4)]], ignore_order=True) assert diff == {}
def repl(board: Board) -> Player: """ players - Players list - A list of player objects that represent the players. board - Board - a fresh board to start the game """ game_over, winner = check_win(board.players) while not game_over: p_turn = board.players[board.turn] # print(" Current Turn: ", p_turn.name) # print(" Player's influence ", [p.influence for p in board.players]) # print(" Player's bank ", [p.bank for p in board.players]) # print(" Player's hand size", [len(p.hand) for p in board.players]) if p_turn.influence <= 0: board.end_turn() else: #print("THIS IS P_TURN", p_turn.name) if isinstance(p_turn, RandomPlayer) or isinstance( p_turn, HeuristicPlayer): selected_action = p_turn.select_action() #enable_print() # print(p_turn.name, selected_action) # block_print() process_action(selected_action, p_turn, board) else: print("{} it is your turn".format(p_turn.name)) prompt_user() i = input() while not i.isalnum(): print("{} it is your turn".format(p_turn.name)) prompt_user() i = input() process_input(i, p_turn, board) # End of action game_over, winner = check_win(board.players) print("{} has won the game!".format(winner.name)) return winner
def test_check_win__diagonal_back_slash_middle(): board = [ [0, 0, 0, 0, 0, 0, 0], [0, 1, 0, 0, 0, 0, 0], [0, 2, 1, 0, 0, 0, 0], [0, 1, 1, 1, 0, 0, 0], [0, 2, 2, 1, 1, 0, 0], [0, 1, 2, 1, 2, 0, 0], ] diff = DeepDiff(utils.check_win(board, 3), [[(1, 1), (2, 2), (3, 3), (4, 4)]], ignore_order=True) assert diff == {}
def test_check_win__vertical(): board = [ [0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0], [0, 1, 0, 0, 0, 0, 0], [0, 1, 0, 0, 0, 0, 0], [0, 1, 0, 2, 0, 0, 0], [0, 1, 2, 2, 0, 0, 0], ] diff = DeepDiff(utils.check_win(board, 2), [[(5, 1), (4, 1), (3, 1), (2, 1)]], ignore_order=True) assert diff == {}
def test_check_win__bug_with_vertical(): """The last move was the far right of the win Actual board that said player 1 won Issue: the diagonal was wraping around the top and comming up on the bottom """ board = [ [0, 1, 0, 0, 0, 0, 0], [0, 2, 0, 0, 0, 0, 0], [0, 1, 1, 0, 2, 2, 0], [0, 1, 2, 2, 1, 1, 0], [0, 1, 1, 1, 2, 2, 2], [0, 2, 1, 2, 1, 2, 1], ] assert utils.check_win(board, 2) == []
def test_check_win__horizontal_far_left(): """The last move was the far left of the win """ board = [ [0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0], [0, 0, 2, 0, 0, 2, 0], [0, 0, 2, 1, 1, 1, 1], ] diff = DeepDiff(utils.check_win(board, 4), [[(5, 3), (5, 4), (5, 5), (5, 6)]], ignore_order=True) assert diff == {}
def simulation(self, tree, child_id): state = deepcopy(tree[child_id]['state']) player = deepcopy(tree[child_id]['player']) while True: win = check_win(state, self.win_mark) if win != 0: return win else: actions = valid_actions(state) action = random.choice(actions) if player == 0: player = 1 state[action[0]] = 1 else: player = 0 state[action[0]] = -1
def expansion(self, tree, leaf_id): leaf_state = deepcopy(tree[leaf_id]['state']) is_terminal = check_win(leaf_state, self.win_mark) actions = valid_actions(leaf_state) expand_thres = 10 if leaf_id == (0, ) or tree[leaf_id]['n'] > expand_thres: is_expand = True else: is_expand = False if is_terminal == 0 and is_expand: # expansion for every possible actions childs = [] for action in actions: state = deepcopy(tree[leaf_id]['state']) action_index = action[1] current_player = tree[leaf_id]['player'] if current_player == 0: next_turn = 1 state[action[0]] = 1 else: next_turn = 0 state[action[0]] = -1 child_id = leaf_id + (action_index, ) childs.append(child_id) tree[child_id] = { 'state': state, 'player': next_turn, 'child': [], 'parent': leaf_id, 'n': 0, 'w': 0, 'q': 0 } tree[leaf_id]['child'].append(action_index) child_id = random.sample(childs, 1) return tree, child_id[0] else: # If leaf node is terminal state, # just return MCTS tree return tree, leaf_id
def minimax(board, depth, Max): # Max - True for maximizer , False for minimizer value_board = utils.check_win(board) # printer(board,value_board) if value_board != 2: return value_board # if game-over return winner.. moves = utils.get_moves_left(board) if Max: best = -99 for move in moves: board[move] = 1 val = minimax(board, depth + 1, False) best = max(best, val) board[move] = 9 return best else: best = 99 for move in moves: board[move] = 0 val = minimax(board, depth + 1, True) best = min(best, val) board[move] = 9 return best
def step(self, input_): # Initial settings if self.init is True: self.num_stones = 0 # No stone: 0, Black stone: 1, White stone = -1 self.gameboard = np.zeros([GAMEBOARD_SIZE, GAMEBOARD_SIZE]) # black turn: 0, white turn: 1 self.turn = 0 self.init = False # Key settings mouse_pos = 0 if np.all(input_) == 0 and self.gamemode == 'pygame': # If guide mode of O's turn for event in pygame.event.get(): # event loop if event.type == QUIT: self.terminate() if pygame.mouse.get_pressed()[0]: mouse_pos = pygame.mouse.get_pos() # get action and put stone on the board check_valid_pos = False x_index = 100 y_index = 100 # action = np.reshape(input_, (GAMEBOARD_SIZE, GAMEBOARD_SIZE)) action_index = 0 if mouse_pos != 0: for i in range(len(self.X_coord)): for j in range(len(self.Y_coord)): if ((self.X_coord[i] - 15 < mouse_pos[0] < self.X_coord[i] + 15) and (self.Y_coord[j] - 15 < mouse_pos[1] < self.Y_coord[j] + 15)): check_valid_pos = True x_index = i y_index = j action_index = y_index * GAMEBOARD_SIZE + x_index # If selected spot is already occupied, it is not valid move! if self.gameboard[y_index, x_index] == 1 or self.gameboard[ y_index, x_index] == -1: check_valid_pos = False # If self mode and MCTS works if np.any(input_) != 0: action_index = np.argmax(input_) y_index = int(action_index / GAMEBOARD_SIZE) x_index = action_index % GAMEBOARD_SIZE check_valid_pos = True # If selected spot is already occupied, it is not valid move! if self.gameboard[y_index, x_index] == 1 or self.gameboard[y_index, x_index] == -1: check_valid_pos = False # Change the gameboard according to the stone's index if np.any(input_) != 0: # update state # self.state = update_state(self.state, self.turn, x_index, y_index) if self.turn == 0: self.gameboard[y_index, x_index] = 1 self.turn = 1 self.num_stones += 1 else: self.gameboard[y_index, x_index] = -1 self.turn = 0 self.num_stones += 1 if self.gamemode == 'pygame': # Fill background color DISPLAYSURF.fill(BLACK) # Draw board self.draw_main_board() # Display Information self.title_msg() self.rule_msg() self.score_msg() # Display who's turn self.turn_msg() pygame.display.update() # Check_win 0: playing, 1: black win, 2: white win, 3: draw win_index = check_win(self.gameboard, WIN_STONES) self.display_win(win_index) return self.gameboard, check_valid_pos, win_index, self.turn, action_index
def select(b, n): global a, ai_enabled, player_first, button_dictionary, ttt_board if ttt_board[n] != 9: tkinter.messagebox.showinfo("Error", " Choose some other box") return a = a + 1 if ai_enabled and player_first: # True, and player_first then if (a % 2 == 0): b.configure(image=x) ttt_board[n] = 1 # computer's move done.. if utils.check_win(ttt_board) == 1: reset() tkinter.messagebox.showinfo("COMPUTER WON", " Better Luck next time.. ") elif utils.check_win(ttt_board) == 0: reset() tkinter.messagebox.showinfo("It's a DRAW", " Well played.. ") else: b.configure(image=o) ttt_board[n] = 0 if utils.check_win(ttt_board) == -1: reset() tkinter.messagebox.showinfo("PLAYER WON", " CONGRATULATIONS.... ") elif utils.check_win(ttt_board) == 0: reset() tkinter.messagebox.showinfo("It's a DRAW", " Well played.. ") move = method_ai.best_move(ttt_board) select(button_dictionary[move], move) # call for computer to make a move elif ai_enabled: # player goes second if (a % 2 != 0): b.configure(image=x) ttt_board[n] = 1 # computer's move done.. if utils.check_win(ttt_board) == 1: reset() tkinter.messagebox.showinfo("COMPUTER WON", " Better Luck next time.. ") elif utils.check_win(ttt_board) == 0: reset() tkinter.messagebox.showinfo("It's a DRAW", "Well played .. ") else: b.configure(image=o) ttt_board[n] = 0 if utils.check_win(ttt_board) == -1: reset() tkinter.messagebox.showinfo("Player WON", " CONGRATULATIONS... ") elif utils.check_win(ttt_board) == 0: reset() tkinter.messagebox.showinfo("It's a DRAW", "Well played .. ") move = method_ai.best_move(ttt_board) select(button_dictionary[move], move) # call for computer to make a move else: # double player mode if (a % 2 == 0): b.configure(image=x) ttt_board[n] = 1 else: b.configure(image=o) ttt_board[n] = 0 res = utils.check_win(ttt_board) if res == 0: reset() tkinter.messagebox.showinfo("It's a DRAW", "Well played people.. ") elif res == -1: reset() tkinter.messagebox.showinfo(" RESULTS ", " And the winner is O") elif res == 1: reset() tkinter.messagebox.showinfo(" RESULTS ", " And the winner is X ")
def check_win(self, column): self.win = utils.check_win(self.board, column) return self.win
def one_player(self, board): """ Play with the computer """ keyboardIndexMapping = constants.keyboardIndexMapping computerChar, playerChar, displayWinChance, whichPlayerFirst = utils.getSinglePlayerDetails( ) if whichPlayerFirst == 1: utils.clearScreen() utils.display_board(board) while utils.check_win(board, computerChar, playerChar)[0] == 0: if utils.check_empty(board): tut = [0, 0, 0, 0, 0, 0, 0, 0, 0] else: tut = [ -i for i in self.minimax(board, playerChar, computerChar, playerChar) ] if displayWinChance == 1: utils.clearScreen() utils.display_tutorial_board(board, tut) index = int(input()) if index > 9 or index < 1: utils.clearScreen() utils.display_board(board) if displayWinChance == 1: utils.clearScreen() utils.display_tutorial_board(board, tut) continue index = keyboardIndexMapping[index] # cant use already used index if board[index] != '-': utils.clearScreen() utils.display_board(board) if displayWinChance == 1: utils.clearScreen() utils.display_tutorial_board(board, tut) continue board[index] = playerChar utils.clearScreen() utils.display_board(board) if displayWinChance == 1: utils.clearScreen() utils.display_tutorial_board(board, tut) if utils.check_win(board, computerChar, playerChar)[0] != 0: break ret = self.minimax(board, computerChar, computerChar, playerChar) # chose move for computer board[utils.the_move(board, ret)] = computerChar utils.clearScreen() utils.display_board(board) if utils.check_win(board, computerChar, playerChar)[0] == 1: print("You lost!!") else: print("It's a draw!") if whichPlayerFirst == 2: while utils.check_win(board, computerChar, playerChar)[0] == 0: if utils.check_empty(board): board[random.randrange(0, 9)] = computerChar else: ret = self.minimax(board, computerChar, computerChar, playerChar) # chose move for computer board[utils.the_move(board, ret)] = computerChar utils.clearScreen() utils.display_board(board) if utils.check_win(board, computerChar, playerChar)[0] != 0: break # index already used can't be reused flag = 0 while flag == 0: tut = [ -i for i in self.minimax(board, playerChar, computerChar, playerChar) ] utils.clearScreen() utils.display_board(board) if displayWinChance == 1: utils.clearScreen() utils.display_tutorial_board(board, tut) index = int(input()) if index > 9 or index < 1: utils.clearScreen() utils.display_board(board) if displayWinChance == 1: utils.clearScreen() utils.display_tutorial_board(board, tut) continue index = keyboardIndexMapping[index] if board[index] == '-': flag = 1 board[index] = playerChar utils.clearScreen() utils.display_board(board) if displayWinChance == 1: utils.clearScreen() utils.display_tutorial_board(board, tut) else: utils.clearScreen() utils.display_board(board) if displayWinChance == 1: utils.clearScreen() utils.display_tutorial_board(board, tut) if utils.check_win(board, computerChar, playerChar)[0] == 1: print("You lost!!") else: print("It's a draw!")
def test_move_win(size, board, turn, move, win_conditions): board_copy = board[:] utils.update_board(board_copy, move, turn, size) return False if utils.check_win(win_conditions, board_copy) == -1 else True