def get_next_move(board, token): available_moves = game.available_moves(board) preferred_locaitons = [3, 2, 4, 1, 5, 0, 6] best_value = float('-inf') best_move = random.choice(available_moves) other_token = 'X' if token == 'O' else 'O' for move in available_moves: new_board = copy_board(board) game.make_move(new_board, move, token) if game.check_winner(new_board): return move for move in available_moves: new_board = copy_board(board) game.make_move(new_board, move, other_token) if game.check_winner(new_board): return move for move in preferred_locaitons: if move not in available_moves: continue return move # move_value = minimax(new_board, 0, False, token, other_token) # if move_value > best_value: # best_move = move return best_move
def get_next_move(board, token): available_moves = game.available_moves(board) available_positions = list( zip(available_moves, available_rows(available_moves, board))) other_token = define_other_token(token) #TODO pre-calculate those as part of the setup() available_lines_of_4 = [ line for line in game.LINES_OF_4 if not set(available_positions).isdisjoint(line) ] outcome = dict() smallest_tokens_missing = 5 for line_of_4 in available_lines_of_4: token_missing = get_nb_token_missing(board, line_of_4) if smallest_tokens_missing > token_missing: outcome = defaultdict( list) #was int in tournament but allows better debugging smallest_tokens_missing = token_missing if token_missing == smallest_tokens_missing and smallest_tokens_missing < 5: the_moves = list(set(line_of_4) & set(available_positions)) for move in the_moves: outcome[move[0]].append(list) #Format changed for Clarity proposals = [ Proposal(col=i, row=board[i].index('.'), nb=len(j)) for i, j in outcome.items() ] if "DEBUG" in os.environ: print(f"==>From Athanase playing {token}") print( f"===>I had {len(available_moves)} available moves {available_moves}" ) print( f"===>Those were part of {len(available_lines_of_4)} lines of 4:") print(f"====>{available_lines_of_4}") print( f"===>I have select {len(proposals)} of then that have {smallest_tokens_missing} missing:" ) print(f"====>{proposals}") try: outputs = [ e.col for e in proposal if cut_fn(e) == max( cut_fn(x) for x in proposal) ] output = random.choice(outputs) except: output = random.choice(available_moves) return output
def get_next_move(board, token): available_moves = game.available_moves(board) preferred_locations = [3, 2, 4, 1, 5, 0, 6] priority_locations = get_columns_with_space(board, token, preferred_locations) avoid_locations = [] moves_played = get_moves_played(board) # best_value = float('-inf') # best_move = random.choice(available_moves) other_token = 'X' if token == 'O' else 'O' for move in available_moves: new_board = copy_board(board) game.make_move(new_board, move, token) if game.check_winner(new_board): return move for move in available_moves: new_board = copy_board(board) game.make_move(new_board, move, other_token) if game.check_winner(new_board): return move for move in available_moves: try: new_board = copy_board(board) game.make_move(new_board, move, token) game.make_move(new_board, move, other_token) if game.check_winner(new_board): avoid_locations.append(move) except: continue if moves_played == 1: # Don't go on top of the previous player avoid_locations.append(find_enemy_location(board, other_token)) for move in priority_locations: if move not in available_moves or move in avoid_locations: continue return move for move in preferred_locations: if move not in available_moves or move in avoid_locations: continue return move return random.choice(available_moves)
def minimax(board, depth, maxplayer, token, other_token): if depth == 0: return get_board_value(board, token) if maxplayer: value = float('-inf') for move in game.available_moves(board): new_board = copy_board(board) game.make_move(new_board, move, token) if game.check_winner(new_board): return float('inf') value = max( value, minimax(new_board, depth - 1, False, token, other_token)) return value else: value = float('inf') for move in game.available_moves(board): new_board = copy_board(board) game.make_move(new_board, move, other_token) if game.check_winner(new_board): return float('-inf') value = min( value, minimax(new_board, depth - 1, True, token, other_token)) return value
def get_next_move(board, token): available_moves = game.available_moves(board) available_position = [(a, board[a].index('.')) for a in available_moves] available_play = available_position if token == 'X': other_token = 'O' else: other_token = 'X' possible = [ line for line in game.LINES_OF_4 if not set(available_position).isdisjoint(line) ] outcome = dict() best = 5 for line in possible: remaining, letter = remaining_to_win(board, line, token) if remaining == 5: continue if best > remaining: outcome = defaultdict(int) outcome_assign = defaultdict() best = remaining if best == remaining: the_moves = list(set(line) & set(available_play)) for move in the_moves: outcome[move[0]] += 1 if letter == token: outcome_assign[move[0]] = letter #tuple number of line_4, row, cols proposals = list((j, board[i].index('.'), i) for i, j in outcome.items()) if best == 1: return select_for_victory(board, outcome_assign, proposals, token) traps = get_traps(board, game.LINES_OF_4, best, token) proposals_minus_traps = [ prop for prop in proposals if not any((prop[2], prop[1] + 1) in trap for trap in traps) ] outputs = [ e[2] for e in proposals_minus_traps if cut_fn(e) == max( cut_fn(x) for x in proposals_minus_traps) ] outputs = outputs or [ avail[0] for avail in available_play if not any( (avail[0], avail[1] + 1) in trap for trap in traps) ] if len(outputs) == 0: deadly_traps = get_his_deadly_traps(board, game.LINES_OF_4, best, token) outputs = [ avail[0] for avail in available_play if not any( (avail[0], avail[1] + 1) in trap for trap in deadly_traps) ] outputs = outputs or available_moves try: output = random.choice(outputs) except: output = random.choice(available_moves) return output
def get_next_move(board, token): available_moves = game.available_moves(board) available_position = [(a, board[a].index('.')) for a in available_moves] available_play = available_position if token == 'X': other_token = 'O' else: other_token = 'X' possible = [ line for line in game.LINES_OF_4 if not set(available_position).isdisjoint(line) ] outcome = dict() best = 5 for line in possible: remaining, letter = remaining_to_win(board, line, token) if remaining == 5: continue if best > remaining: outcome = defaultdict(int) outcome_assign = defaultdict() best = remaining if best == remaining: the_moves = list(set(line) & set(available_play)) for move in the_moves: outcome[move[0]] += 1 if letter == token: outcome_assign[move[0]] = letter #tuple number of line_4, row, cols proposals = [(i, board[i].index('.'), 0, 0, j) for i, j in outcome.items()] if best == 1: return select_for_victory(board, outcome_assign, proposals, token) traps = get_traps(board, game.LINES_OF_4, best, token) #Do not fall in a trap. proposals_minus_traps = [ prop for prop in proposals if not any((prop[0], prop[1] + 1) in trap for trap in traps) ] #We have a choice, let's see if we can set a trap if len(proposals_minus_traps) > 1: friendly_traps = get_his_deadly_traps(board, game.LINES_OF_4, best, other_token) available_traps = set(pos for trap in friendly_traps for pos in trap if get_letter_of_pos(pos, board) == ".") trap_columns = set(pos[0] for pos in available_traps) the_existing = [ e[0] for e in proposals_minus_traps if (e[0], e[1]) in available_traps ] board1 = copy.deepcopy(board) improved_proposals = list() for col, row, _, _, remaining in proposals_minus_traps: board1[col][row] = token new_friendly_traps = get_his_deadly_traps(board1, (traps + possible), best, other_token) all_new_traps = set(pos for trap in new_friendly_traps for pos in trap if get_letter_of_pos(pos, board1) == ".") new_traps = all_new_traps - available_traps above_each_other = len( [trap for trap in new_traps if trap[0] in trap_columns]) improved_proposals.append( (col, row, above_each_other, len(new_traps), remaining)) board1[col][row] = '.' if len(improved_proposals): proposals_minus_traps = improved_proposals outputs = [ e[0] for e in proposals_minus_traps if cut_fn(e) == max( cut_fn(x) for x in proposals_minus_traps) ] outputs = outputs or [ avail[0] for avail in available_play if not any( (avail[0], avail[1] + 1) in trap for trap in traps) ] if len(outputs) == 0: deadly_traps = get_his_deadly_traps(board, game.LINES_OF_4, best, token) outputs = [ avail[0] for avail in available_play if not any( (avail[0], avail[1] + 1) in trap for trap in deadly_traps) ] outputs = outputs or available_moves try: output = random.choice(outputs) except: output = random.choice(available_moves) return output
def get_next_move(board, token): board_columns_used = get_board_columns_used(board) available_moves = game.available_moves(board) preferred_locations = [3, 2, 4, 1, 5, 0, 6] preferred_locations = [x for x in preferred_locations if x in available_moves] priority_locations = get_columns_with_space(board, token, preferred_locations) opcode_limit = get_opcode_limit() losing_locations = set() skip_moves = set() # if state is None: # state = {'opening_trap': False} moves_played = get_moves_played(board) other_token = 'X' if token == 'O' else 'O' for move in available_moves: board[move][board_columns_used[move]] = token if check_winner(board, move, board_columns_used[move]): print('MOVE: winning move') return move board[move][board_columns_used[move]] = '.' for move in available_moves: board[move][board_columns_used[move]] = other_token if check_winner(board, move, board_columns_used[move]): print('MOVE: blocking enemy win') return move board[move][board_columns_used[move]] = '.' for move in available_moves: if board_columns_used[move] > 4: continue board[move][board_columns_used[move]] = token board[move][board_columns_used[move] + 1] = other_token if check_winner(board, move, board_columns_used[move] + 1): losing_locations.add(move) board[move][board_columns_used[move]] = '.' board[move][board_columns_used[move] + 1] = '.' # Opening book if moves_played == 1: if board[3][0] == other_token: losing_locations.add(3) if moves_played == 2: if board[3][1] == other_token: # state['opening_trap'] = True return 2 if board[2][0] == other_token: return 2 if board[4][0] == other_token : return 4 if moves_played == 4: if board[3][1] == other_token and board[1][0] == '.' and board[4][0] == '.': return 4 # Take the move if you see a open-ended 3 way opportunity for move in available_moves: if move in losing_locations: continue if move_makes_3_horizontal_with_spaces(board, move, board_columns_used[move], token): print('MOVE: 3-way opportunity') return move # Block 2 adjacent tokens for the enemy for move in available_moves: if move_makes_3_horizontal_with_spaces(board, move, board_columns_used[move], other_token): print('MOVE: block 3-way opportunity') return move for move in available_moves: if move in losing_locations or board_columns_used[move] > 4: continue board[move][board_columns_used[move]] = token board[move][board_columns_used[move] + 1] = token if check_winner(board, move, board_columns_used[move] + 1, ignore_vertical=True): skip_moves.add(move) board[move][board_columns_used[move]] = '.' board[move][board_columns_used[move] + 1] = '.' print(get_opcode_count()) # Look for forced wins for move in skip_moves: if move in losing_locations or board_columns_used[move] > 2: continue board[move][board_columns_used[move]] = token board[move][board_columns_used[move] + 1] = other_token board[move][board_columns_used[move] + 2] = token if check_winner(board, move, board_columns_used[move] + 2): print('MOVE: Force WIN') return move board[move][board_columns_used[move] + 2] = '.' board[move][board_columns_used[move] + 1] = '.' board[move][board_columns_used[move]] = '.' # # Look for a sure win: # for move in available_moves: # print(f'sure {move}') # if move in losing_locations or board_columns_used[move] > 2: # continue # copy_board = [x[:] for x in board] # copy_board_columns_used = board_columns_used[:] # copy_board[move][copy_board_columns_used[move]] = token # # copy_board[move][copy_board_columns_used[move] + 1] = token # # # if not check_winner(copy_board, move, board_columns_used[move] + 1): # # continue # # # copy_board[move][copy_board_columns_used[move] + 1] = '.' # copy_board_columns_used[move] += 1 # # result = results_in_a_winner(copy_board, copy_board_columns_used, token, other_token) # print(f'sure result: {result}') # # if result == token: # print('MOVE: Sure WIN') # return move # elif result == other_token: # losing_locations.add(move) # Look for opening opportunities for move in preferred_locations: move_score = {} if move in skip_moves or move in losing_locations or board_columns_used[move] == 0: continue score = move_opens_opportunities(board, move, board_columns_used[move], token) if score > 0: move_score[move] = score if move_score: sorted_score = sorted(move_score.items(), key=itemgetter(1)) print('MOVE: making opportunities') return sorted_score[0][0] # Look for blocking opening opportunities for move in available_moves: move_score = {} if move in losing_locations: continue score = move_opens_opportunities(board, move, board_columns_used[move], other_token) if score > 0: move_score[move] = score if move_score: sorted_score = sorted(move_score.items(), key=itemgetter(1)) print('MOVE: blocking enemy opportunities') return sorted_score[0][0] sorted_friendly_neighbours_score = None friendly_neighbours_score = {} for move in preferred_locations: if move in skip_moves or move in losing_locations or board_columns_used[move] == 0 or board_columns_used[move] == 0: continue friendly_neighbours = get_friendly_neighbours(board, move, board_columns_used[move], token) if friendly_neighbours > 1: friendly_neighbours_score[move] = friendly_neighbours if friendly_neighbours_score: sorted_friendly_neighbours_score = sorted(friendly_neighbours_score.items(), key=itemgetter(1)) if sorted_friendly_neighbours_score[0][1] >= 3: print('MOVE: good friendlies') return sorted_friendly_neighbours_score[0][0] for move in preferred_locations: if move in skip_moves or move in losing_locations or board_columns_used[move] == 0 or board_columns_used[move] > 3: continue if not can_make_4_horizontal(board, move, board_columns_used[move], token): continue if move > 0: if board[move - 1][board_columns_used[move]] == token: print('MOVE: pair left') return move if move < 6: if board[move + 1][board_columns_used[move]] == token: print('MOVE: pair right') return move if sorted_friendly_neighbours_score: print('MOVE: weak neighbours') return sorted_friendly_neighbours_score[0][0] print(get_opcode_count()) for move in priority_locations: if move not in available_moves or move in losing_locations or move in skip_moves: continue return move for move in preferred_locations: if move not in available_moves or move in losing_locations or move in skip_moves: continue return move for move in priority_locations: if move not in available_moves or move in losing_locations: continue return move for move in preferred_locations: if move not in available_moves or move in losing_locations: continue return move return random.choice(available_moves)
def get_next_move(board, token): available_moves = game.available_moves(board) available_positions = list( zip(available_moves, available_rows(available_moves, board))) other_token = define_other_token(token) #TODO pre-calculate those as part of the setup() available_lines_of_4 = [ line for line in game.LINES_OF_4 if not set(available_positions).isdisjoint(line) ] outcome = dict() smallest_tokens_missing = 5 for line_of_4 in available_lines_of_4: token_missing = get_nb_token_missing(board, line_of_4) if smallest_tokens_missing > token_missing: outcome = defaultdict( list) #was int in tournament but allows better debugging smallest_tokens_missing = token_missing if token_missing == smallest_tokens_missing and smallest_tokens_missing < 5: the_moves = list(set(line_of_4) & set(available_positions)) for move in the_moves: outcome[move[0]].append(list) #Format changed for Clarity proposals = [ Proposal(col=i, row=board[i].index('.'), nb=len(j)) for i, j in outcome.items() ] if smallest_tokens_missing > 1: #TODO include in initial loop to avoid going over game.LINES_OF_4 again? traps = get_traps(board, game.LINES_OF_4, smallest_tokens_missing) else: traps = list() if "DEBUG" in os.environ: print(f"==>From Athanase 'No Traps' playing {token}") print( f"===>I had {len(available_moves)} available moves {available_moves}" ) print( f"===>Those were part of {len(available_lines_of_4)} lines of 4:") print(f"====>{available_lines_of_4}") print( f"===>I have select {len(proposals)} of then that have {smallest_tokens_missing} missing:" ) print(f"====>{proposals}") print(f"===>There were also {len(traps)} traps:") print(f"====>{traps}") try: proposals_not_traps = [ prop for prop in proposals if not any((prop.col, prop.row + 1) in trap for trap in traps) ] outputs = [ e.col for e in proposals_not_traps if cut_fn(e) == max( cut_fn(x) for x in proposals_not_traps) ] if "DEBUG" in os.environ: print( f"===>I had {len(proposals_not_traps)} proposals after filtering the traps out:" ) print(f"====>{proposals_not_traps}") print(f"===>And those are the potential moves to select from:") print(f"====>{outputs}") outputs = outputs or [ avail[0] for avail in available_play if not any( (avail, avail[1] + 1) in trap for trap in traps) ] if "DEBUG" in os.environ: print( f"===>If the previous selection was empty, I filter out traps from available moves:" ) print(f"====>{outputs}") outputs = outputs or available_moves if "DEBUG" in os.environ: print( f"===>If the previous selection was empty, I just select from available moves:" ) print(f"====>{outputs}") output = random.choice(outputs) except: output = random.choice(available_moves) if "DEBUG" in os.environ: print(f"===>Exception occured, select from available moves:") print(f"====>{outputs}") return output
def get_next_move(board, token): available_moves = game.available_moves(board) available_position = [(a, board[a].index('.')) for a in available_moves] available_play = available_position if token == 'X': other_token = 'O' else: other_token = 'X' possible = [ line for line in game.LINES_OF_4 if not set(available_position).isdisjoint(line) ] outcome = dict() best = 5 for line in possible: remaining, letter = remaining_to_win(board, line, token) if remaining == 5: continue if best > remaining: outcome = defaultdict(list) outcome_assign = defaultdict() best = remaining if best == remaining: the_moves = list(set(line) & set(available_play)) for move in the_moves: outcome[move[0]].append(list) if letter == token: outcome_assign[move[0]] = letter #tuple number of line_4, row, cols proposals = [(i, board[i].index('.'), 9, 0, 0, len(j)) for i, j in outcome.items()] if best == 1: return select_for_victory(board, outcome_assign, proposals, token) traps = get_traps(board, game.LINES_OF_4, best, token) #Do not fall in a trap. proposals_minus_traps = [ prop for prop in proposals if not any((prop[0], prop[1] + 1) in trap for trap in traps) ] friendly_traps = get_his_deadly_traps(board, game.LINES_OF_4, best, other_token) available_traps = set(pos for trap in friendly_traps for pos in trap if get_letter_of_pos(pos, board) == ".") enemy_traps = get_his_deadly_traps(board, game.LINES_OF_4, best, token) available_enemy_traps = set(pos for trap in enemy_traps for pos in trap if get_letter_of_pos(pos, board) == ".") print("outcome", outcome, outcome_assign, best) print("athanase => proposals ==>", proposals) print("athanase => traps ======>", traps) print("athanase => proposals_minus_traps =>", proposals_minus_traps) for move in available_moves: sequence_play = set([ a[1] - board[a[0]].index('.') for a in available_traps if a[0] == move ]) separation = len(set(a % 2 for a in sequence_play)) no_enemy = True if len( set([ a[1] - board[a[0]].index('.') for a in available_enemy_traps if a[0] == move ])): first_enemy = min( set([ a[1] - board[a[0]].index('.') for a in available_enemy_traps if a[0] == move ])) print("+++++++++=+=>", min(sequence_play), first_enemy) print(enemy_traps) print("==============>", sequence_play) print(game.render_text(board)) if min(sequence_play) == first_enemy: no_enemy = False if len(sequence_play) > 1 and separation == 2 and no_enemy: print("nailing it=======>", available_traps) print(enemy_traps) print("nailing it=======>", token, move) print("==============>", sequence_play) print(game.render_text(board)) return move #We have a choice, let's see if we can set a trap if len(traps) > 1: board1 = copy.deepcopy(board) improved_proposals = list() only_him = set((row, col) for row, col in available_play if not any( (row, col + 1) in trap for trap in traps)) - set( (row, col) for row, col, _, _, _, _ in proposals) if len(enemy_traps) > 0 and len(friendly_traps) == 0: for col, row in only_him: board1[col][row] = other_token new_enemy_traps = get_his_deadly_traps( board1, (enemy_traps + possible), best, token) all_new_traps = set(pos for trap in new_enemy_traps for pos in trap if get_letter_of_pos(pos, board1) == ".") new_traps = all_new_traps - available_enemy_traps if len(new_traps) > 0: potential_traps = ( all_new_traps.union(available_enemy_traps)) sequence_play = [ a[1] - board[a[0]].index('.') for a in potential_traps ] if len(potential_traps) > 0: next_one = min(sequence_play) else: next_one = 9 order = len(set(a % 2 for a in sequence_play)) improved_proposals.append( (col, row, next_one, order, len(new_traps), 0)) board1[col][row] = '.' for col, row, _, _, _, remaining in proposals_minus_traps: board1[col][row] = token new_friendly_traps = get_his_deadly_traps(board1, (traps + possible), best, other_token) all_new_traps = set(pos for trap in new_friendly_traps for pos in trap if get_letter_of_pos(pos, board1) == ".") new_traps = all_new_traps - available_traps potential_traps = (all_new_traps.union(available_traps)) sequence_play = [ a[1] - board[a[0]].index('.') for a in potential_traps ] if len(potential_traps) > 0: next_one = min(sequence_play) else: next_one = 9 order = len(set(a % 2 for a in sequence_play)) improved_proposals.append( (col, row, next_one, order, len(new_traps), remaining)) board1[col][row] = '.' if len(improved_proposals): proposals_minus_traps = improved_proposals outputs = list() if len(proposals_minus_traps): outputs = [ e[0] for e in proposals_minus_traps if e == max(proposals_minus_traps, key=cut_fn) ] if len(outputs) == 0: outputs = available_moves outputs = [ move for move in outputs if not any( (move, board[move].index('.') + 1) in trap for trap in enemy_traps) ] print("athanase => outputs =>", outputs) try: output = random.choice(outputs) except: output = random.choice(available_moves) return output
def get_next_move(board, token): board_columns_used = get_board_columns_used(board) available_moves = game.available_moves(board) preferred_locations = [3, 2, 4, 1, 5, 0, 6] preferred_locations = [ x for x in preferred_locations if x in available_moves ] priority_locations = get_columns_with_space(board, token, preferred_locations) opcode_limit = get_opcode_limit() losing_locations = set() # if state is None: # state = {'opening_trap': False} moves_played = get_moves_played(board) other_token = 'X' if token == 'O' else 'O' for move in available_moves: board[move][board_columns_used[move]] = token if check_winner(board, move, board_columns_used[move]): return move board[move][board_columns_used[move]] = '.' for move in available_moves: board[move][board_columns_used[move]] = other_token if check_winner(board, move, board_columns_used[move]): return move board[move][board_columns_used[move]] = '.' for move in available_moves: if board_columns_used[move] > 4: continue board[move][board_columns_used[move]] = token board[move][board_columns_used[move] + 1] = other_token if check_winner(board, move, board_columns_used[move] + 1): losing_locations.add(move) board[move][board_columns_used[move]] = '.' board[move][board_columns_used[move] + 1] = '.' # Opening book if moves_played == 1: if board[3][0] == other_token: losing_locations.add(3) if moves_played == 2: if board[3][1] == other_token: # state['opening_trap'] = True return 2 if board[2][0] == other_token: return 2 if board[4][0] == other_token: return 4 if moves_played == 4: if board[3][1] == other_token and board[1][0] == '.' and board[4][ 0] == '.': return 4 skip_moves = set() for move in available_moves: if board_columns_used[move] > 4: continue board[move][board_columns_used[move]] = token board[move][board_columns_used[move] + 1] = token if check_winner(board, move, board_columns_used[move] + 1, ignore_vertical=True): skip_moves.add(move) board[move][board_columns_used[move]] = '.' board[move][board_columns_used[move] + 1] = '.' print(get_opcode_count()) for move in preferred_locations: if move in skip_moves or move in losing_locations or board_columns_used[ move] == 0 or board_columns_used[move] > 3: continue if move > 0: if board[move - 1][board_columns_used[move]] == token: return move if move < 6: if board[move + 1][board_columns_used[move]] == token: return move print(get_opcode_count()) for move in priority_locations: if move not in available_moves or move in losing_locations or move in skip_moves: continue return move for move in preferred_locations: if move not in available_moves or move in losing_locations or move in skip_moves: continue return move for move in priority_locations: if move not in available_moves or move in losing_locations: continue return move for move in preferred_locations: if move not in available_moves or move in losing_locations: continue return move return random.choice(available_moves)
def get_next_move(board, token): board_columns_used = get_board_columns_used(board) available_moves = game.available_moves(board) preferred_locations = [3, 2, 4, 1, 5, 0, 6] preferred_locations = [ x for x in preferred_locations if x in available_moves ] priority_locations = get_columns_with_space(board, token, preferred_locations) opcode_limit = get_opcode_limit() losing_locations = set() skip_moves = set() # if state is None: # state = {'opening_trap': False} moves_played = get_moves_played(board) other_token = 'X' if token == 'O' else 'O' for move in available_moves: board[move][board_columns_used[move]] = token if check_winner(board, move, board_columns_used[move]): return move board[move][board_columns_used[move]] = '.' for move in available_moves: board[move][board_columns_used[move]] = other_token if check_winner(board, move, board_columns_used[move]): return move board[move][board_columns_used[move]] = '.' for move in available_moves: if board_columns_used[move] > 4: continue board[move][board_columns_used[move]] = token board[move][board_columns_used[move] + 1] = other_token if check_winner(board, move, board_columns_used[move] + 1): losing_locations.add(move) board[move][board_columns_used[move]] = '.' board[move][board_columns_used[move] + 1] = '.' # Opening book if moves_played == 1: if board[3][0] == other_token: losing_locations.add(3) if moves_played == 2: if board[3][1] == other_token: # state['opening_trap'] = True return 2 if board[2][0] == other_token: return 2 if board[4][0] == other_token: return 4 if moves_played == 4: if board[3][1] == other_token and board[1][0] == '.' and board[4][ 0] == '.': return 4 # Take the move if you see a open-ended 3 way opportunity for move in available_moves: if move_makes_3_horizontal_with_spaces(board, move, board_columns_used[move], token): return move # Block 2 adjacent tokens for the enemy for move in available_moves: if move_makes_3_horizontal_with_spaces(board, move, board_columns_used[move], other_token): return move for move in available_moves: if board_columns_used[move] > 4: continue board[move][board_columns_used[move]] = token board[move][board_columns_used[move] + 1] = token if check_winner(board, move, board_columns_used[move] + 1, ignore_vertical=True): skip_moves.add(move) board[move][board_columns_used[move]] = '.' board[move][board_columns_used[move] + 1] = '.' print(get_opcode_count()) for move in preferred_locations: if move in skip_moves or move in losing_locations or board_columns_used[ move] == 0 or board_columns_used[move] > 3: continue if not can_make_4_horizontal(board, move, board_columns_used[move], token): continue if move > 0: if board[move - 1][board_columns_used[move]] == token: return move if move < 6: if board[move + 1][board_columns_used[move]] == token: return move for move in preferred_locations: move_score = {} if move in skip_moves or move in losing_locations or board_columns_used[ move] == 0 or board_columns_used[move]: continue friendly_neighbours = get_friendly_neighbours(board, move, board_columns_used[move], token) if friendly_neighbours > 1: move_score[move] = friendly_neighbours if move_score: sorted_score = sorted(move_score.items(), key=itemgetter(1)) return sorted_score[0][0] print(get_opcode_count()) for move in priority_locations: if move not in available_moves or move in losing_locations or move in skip_moves: continue return move for move in preferred_locations: if move not in available_moves or move in losing_locations or move in skip_moves: continue return move for move in priority_locations: if move not in available_moves or move in losing_locations: continue return move for move in preferred_locations: if move not in available_moves or move in losing_locations: continue return move return random.choice(available_moves)
def get_next_move(board, token): test_board = test_make_board_from_string() print(f'Before check_winner:{get_opcode_count()}') game.check_winner(test_board) print(f'After check_winner:{get_opcode_count()}') board_columns_used = get_board_columns_used(board) print(f'Before available moves:{get_opcode_count()}') all_available_moves = game.available_moves(board) print(f'After available moves:{get_opcode_count()}') preferred_locations = [3, 2, 4, 1, 5, 0, 6] print(f'Before preferred locations:{get_opcode_count()}') priority_locations = get_columns_with_space(board, token, preferred_locations) print(f'After preferred locations:{get_opcode_count()}') losing_locations = set() # if state is None: # state = {'opening_trap': False} print(f'Before board walk: {get_opcode_count()}') board[3][board_columns_used[3]] = token board[3][board_columns_used[3]] = '.' print(f'After board walk: {get_opcode_count()}') new_board = game.new_board() new_board[0][0] = 'X' new_board[1][1] = 'X' new_board[2][2] = 'X' new_board[3][3] = 'X' print(f'Before game.check_winner:{get_opcode_count()}') game.check_winner(new_board) print(f'After game.check_winner:{get_opcode_count()}') print(f'Before check_winner:{get_opcode_count()}') check_winner(board, 3, 3) print(f'After check_winner:{get_opcode_count()}') rO = re.compile(r'OOOO|O.{6}O.{6}O.{6}O|O.{7}O.{7}O.{7}O|O.{8}O.{8}O.{8}O') rX = re.compile(r'XXXX|X.{6}X.{6}X.{6}X|X.{7}X.{7}X.{7}X|X.{8}X.{8}X.{8}X') board_string = make_string_from_board(board) print(f'Before check_winner_regex:{get_opcode_count()}') board_string = board_string[:2 * 7 + 2] + 'X' + board_string[2 * 7 + 2:] check_winner_regex(board_string, 'X', r=rX) print(f'After check_winner_regex:{get_opcode_count()}') moves_played = get_moves_played(board) # best_value = float('-inf') # best_move = random.choice(available_moves) other_token = 'X' if token == 'O' else 'O' for move in all_available_moves: board[move][board_columns_used[move]] = token if check_winner(board, move, board_columns_used[move]): return move board[move][board_columns_used[move]] = '.' print(get_opcode_count()) for move in all_available_moves: board[move][board_columns_used[move]] = other_token if check_winner(board, move, board_columns_used[move]): return move board[move][board_columns_used[move]] = '.' print(get_opcode_count()) available_moves = set(all_available_moves) for move in all_available_moves: if board_columns_used[move] > 4: continue board[move][board_columns_used[move]] = token board[move][board_columns_used[move] + 1] = other_token if check_winner(board, move, board_columns_used[move] + 1): losing_locations.add(move) board[move][board_columns_used[move]] = '.' board[move][board_columns_used[move] + 1] = '.' print(get_opcode_count()) skip_moves = set() for move in all_available_moves: if board_columns_used[move] > 4: continue board[move][board_columns_used[move]] = token board[move][board_columns_used[move] + 1] = token if check_winner(board, move, board_columns_used[move] + 1, ignore_vertical=True): skip_moves.add(move) board[move][board_columns_used[move]] = '.' board[move][board_columns_used[move] + 1] = '.' # for move in all_available_moves: # board[move][board_columns_used[move]] = token # if move_makes_opportunity(board, move, board_columns_used[move], token): # return move print(get_opcode_count()) if moves_played == 1: # Don't go on top of the previous player losing_locations.add(find_enemy_location(board, other_token)) if moves_played == 2: if board[3][1] == other_token: return 2 if moves_played == 4: if board[3][1] == other_token and board[1][0] == '.' and board[4][0] == '.': return 4 priority_locations = [x for x in priority_locations if x not in skip_moves] for move in priority_locations: if move in losing_locations: continue return move for move in preferred_locations: if move in losing_locations: continue return move return random.choice(all_available_moves)
def get_next_move(board, token, state): board_columns_used = get_board_columns_used(board) available_moves = game.available_moves(board) preferred_locations = [3, 2, 4, 1, 5, 0, 6] priority_locations = get_columns_with_space(board, token, preferred_locations) losing_locations = set() if state is None: state = {'opening_trap': False} moves_played = get_moves_played(board) other_token = 'X' if token == 'O' else 'O' for move in available_moves: board[move][board_columns_used[move]] = token if check_winner(board, move, board_columns_used[move]): return move, state board[move][board_columns_used[move]] = '.' for move in available_moves: board[move][board_columns_used[move]] = other_token if check_winner(board, move, board_columns_used[move]): return move, state board[move][board_columns_used[move]] = '.' for move in available_moves: if board_columns_used[move] > 4: continue board[move][board_columns_used[move]] = token board[move][board_columns_used[move] + 1] = other_token if check_winner(board, move, board_columns_used[move] + 1): losing_locations.add(move) board[move][board_columns_used[move]] = '.' board[move][board_columns_used[move] + 1] = '.' skip_moves = set() for move in available_moves: if board_columns_used[move] > 4: continue board[move][board_columns_used[move]] = token board[move][board_columns_used[move] + 1] = token if check_winner(board, move, board_columns_used[move] + 1, ignore_vertical=True): skip_moves.add(move) board[move][board_columns_used[move]] = '.' board[move][board_columns_used[move] + 1] = '.' print(get_opcode_count()) if moves_played == 1: # Don't go on top of the previous player losing_locations.add(find_enemy_location(board, other_token)) if moves_played == 2: if board[3][1] == other_token: state['opening_trap'] = True return 2, state if moves_played == 4: if state['opening_trap']: if board[1][0] == '.' and board[4][0] == '.': return 4, state for move in priority_locations: if move not in available_moves or move in losing_locations or move in skip_moves: continue return move, state for move in preferred_locations: if move not in available_moves or move in losing_locations or move in skip_moves: continue return move, state for move in priority_locations: if move not in available_moves or move in losing_locations: continue return move, state for move in preferred_locations: if move not in available_moves or move in losing_locations: continue return move, state return random.choice(available_moves), state
def get_next_move(board, token): return random.choice(game.available_moves(board))