![]() |
|
This is part of my Minesweeper dev log.
We started building more complex logic for autosolving. I won't give full detail here, because the basic idea was outlined in the first blog.
As we started, we realized we had to fix a couple of things:
By adding these lines, I was able to see the animation move slowly.
ms().tk.update()
time.sleep(0.5)
By adding a random seed to the main, I was able to check consistent boards.
After spending so much time rearranging code, I was starting to worry that this was progressing too slowly. (And in retrospect, I might have spent a little less time on cleanup.). But the autosolver bit progressed very quickly.
On the variable solver: Rather than implementing a backtracking approach, I just looped through the full power set of possible solutions, viewing a backtracker as an over-optimization. The resulting code is very sleek.
def solve_pair_of_constraints(x: Coord, y: Coord) -> List[Action]:
vx, cx = get_variables_constraint(x)
vy, cy = get_variables_constraint(y)
v = list(set(vx) | set(vy))
# We can make this part more efficient later if we need to
valid = []
for s in powerset(v):
# s represents all the 1s, or mines
meet_x = len([t for t in vx if t in s]) == cx
meet_y = len([t for t in vy if t in s]) == cy
if meet_x and meet_y:
valid.append(s)
result = []
for t in v:
if all([t in s for s in valid]):
result.append(Action(type=ActionType.FLAG, coord=t))
if not any([t in s for s in valid]):
result.append(Action(type=ActionType.CLEAR, coord=t))
return result
def solve_variable(coord: Coord) -> List[Action]:
result = []
constraint_neighbors = list(get_neighbors(coord).filter(lambda c: ms().grid[c].state == State.CLICKED))
for x, y in itertools.combinations(constraint_neighbors, 2):
result += solve_pair_of_constraints(x, y)
return result
It's surprising how easy it'd be to generalize this to solve triple-constraints (perhaps easier than limiting to pairs). However, I don't think this is something I'd do as a human player, so I want to continue to have that not implemented.
And I'm happy to report, it's working as expected. This board was generated from a single click in the top-left.

When I look at this board, I don't see any squares that I could click or flag deterministically. This brings me to the point of probabilistic decision-making, as desired.