def __init__(self, player_num, size, max_time=1, num_samples=100): super(MonteCarloPlayer, self).__init__(player_num) # the amount of time given for searching. self.max_time = max_time # the number of rollouts to perform on a leaf node self.num_samples = num_samples # a list of board states, their visit count, and their children self.search_tree = {HexBoard(size).hashable(): [1, 0, set()]} # tunable exploration parameter for UCB self.C = 1
def show_answers_hex(trie, input_str): row_letters, row_starts = parse_letters_hex(input_str) board = HexBoard(row_letters, row_starts) print board results = board_search(board, trie) answers = Answers() answers.add(results) print answers
def text_get_rules(default=0): size = -1 while size < 1: try: if not default: size = int(input('Board size: ')) else: size = DEFAULTS[default]['size'] except ValueError: pass swap = False while swap not in ('y', 'n'): if not default: swap = input('allow swap rule? (y/n): ') else: swap = DEFAULTS[default]['swap'] swap = (swap == 'y') if not default: player = [None] * 3 else: player = DEFAULTS[default]['players'] for i in (1, -1): if player[i] is not None: continue player_type = -1 while not (0 <= player_type <= 5): try: player_type = int(input( '0 - Text\n1 - Gui\n2 - Random (AI)\n3 - Alpha-Beta Search (AI)\n' '4 - Monte-Carlo Search (AI)\n5 - Charge Heuristic (AI)\nplayer %d type?: ' % ( i % 3))) except ValueError: pass if player_type == 0: player[i] = TextPlayer(i) elif player_type == 1: player[i] = GuiPlayer(i) elif player_type == 2: player[i] = RandomPlayer(i) elif player_type == 3: player[i] = build_alpha_beta_player(i, size) elif player_type == 4: player[i] = build_monte_carlo_player(i, size) elif player_type == 5: player[i] = ChargeHeuristicPlayer(i, size) board = HexBoard(size, swap) return board, player
def solve_board(board, expanded_colors, verbose=False): # Identify the input colors and mixing rules used based on the level. input_colors = HARD_INPUT_COLORS if expanded_colors else EASY_INPUT_COLORS mixing_rules = HARD_MIXING_RULES if expanded_colors else EASY_MIXING_RULES try: if RectBoard.is_rect_board(board): RectBoard.validate(board) else: HexBoard.validate(board) validate_colors(board, input_colors, mixing_rules) except ValueError as err: print('Board validation failed: %s' % err) return # Create the solver. solver = pywrapcp.Solver('algemy') start = time.time() grid = {} for r, row in enumerate(board): for c, el in enumerate(row): if el.strip() == '': # A solvable position. grid[(r, c)] = solver.IntVar(0, len(input_colors), '<Row %i, Col %i>' % (r, c)) else: grid[(r, c)] = None # crystal position if RectBoard.is_rect_board(board): b = RectBoard(grid) else: b = HexBoard(grid) # Helper: converts an input color to the int var space. color_i = lambda c: input_colors.index(c) + 1 # Helper: converts an int var to the input color string. i_color = lambda i: input_colors[i - 1] # CONSTRAINT - crystal illumination for (r, c), el in grid.items(): if el is not None: continue # only look at crystals sight_points = list(b.find_point_sightlines(r, c)) or_rules = [] for mix_rule in mixing_rules[board[r][c]]: pos_colors = [s[1:] for s in mix_rule if s[0] == '+'] def get_pos_rules(): for color in pos_colors: yield solver.Sum(p == color_i(color) for p in sight_points) >= 1 neg_colors = [s[1:] for s in mix_rule if s[0] == '-'] def get_neg_rules(): for color in neg_colors: yield solver.Sum(p == color_i(color) for p in sight_points) == 0 comb_rules = list(get_pos_rules()) + list(get_neg_rules()) final_rule = solver.Sum(comb_rules) == len(comb_rules) # ALL or_rules.append(final_rule) solver.Add(solver.Sum(or_rules) > 0) # ANY # CONSTRAINT - board sightlines for sightline in b.find_board_sightlines(): # At one item can be set (non-zero) in a sightline. solver.Add(solver.Sum(x > 0 for x in sightline) <= 1) # CONSTRAINT - all points solved for (r, c), el in grid.items(): if el is None: continue # ignore crystals # Either the point is non-empty or a point in its sightline is non-empty. solver.Add(el + solver.Sum(b.find_point_sightlines(r, c)) > 0) all_vars = list(filter(None, grid.values())) vars_phase = solver.Phase(all_vars, solver.INT_VAR_DEFAULT, solver.INT_VALUE_DEFAULT) if verbose: print("Time setting up constraints: %.2fms" % ((time.time() - start) * 1000)) solution = solver.Assignment() solution.Add(all_vars) collector = solver.FirstSolutionCollector(solution) start = time.time() solver.Solve(vars_phase, [collector]) if verbose: print("Solve time: %.2fms" % (1000 * (time.time() - start))) if collector.SolutionCount() < 1: print("\nNO SOLUTION FOUND") return None # TODO iterate over all solutions instead of using collector. # Allow finding first one then prompt to find next or maybe all. def lookup(r, c): el = grid[(r, c)] if el is None: return ' ' s = int(collector.Value(0, el)) if not s: return ' ' return i_color(s) solution = [] for r, row in enumerate(board): solution.append([lookup(r, c) for c in range(len(row))]) return solution