def test_get_oplimit_count(self): self.assertIsNone(tracer.get_opcode_limit()) with tracer.limited_opcodes(100): self.assertEqual(tracer.get_opcode_limit(), 100) self.assertIsNone(tracer.get_opcode_limit())
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]): 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): 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)