def legal_moves(self, player, pieces): if not pieces: return pieces = set(pieces) # Find available corners to play from. points_poly = Poly(p for p, v in self.data.items() if v == player) corners = set(points_poly.corner_adjacencies()) if self.is_first(player): for p in self.start_points: if self.data.get(p) is None: corners.add(p) # Find available space to play into. # Free space must not be occupied or next to a same-color piece. free_space = set() for x in range(self.size): for y in range(self.size): point = x, y if self.data.get(point) is not None: continue if any(self.data.get(adj) == player for adj in adjacent(point)): continue free_space.add(point) corners &= free_space # Starting from the corners, grow successively larger possible plays. # First generation is just the size 1 polyomino on each corner. generations = [{Poly([c]) for c in corners}] max_size = max(len(p) for p in pieces) for gen_num in range(2, max_size + 1): old_gen = generations[-1] new_gen = set() # Add points to each polyomino in the last generation. for poly in old_gen: for adj in poly.adjacencies(): if adj in free_space: new_gen.add(Poly(poly._points + (adj,))) generations.append(new_gen) for gen in generations: for piece in gen: if piece.canonical() not in pieces: continue ### #reason = self._check_place_piece(piece, player, reason=True) #if reason is not None: # self._place_piece(piece, player) # assert False, '%s\n%s' % (reason, self) ### yield piece
def free_corners(board, player, opponent): score = 0 points = [p for p, v in board.data.items() if v == player] # Must be in bounds, unoccupied, and not next to any pieces of the same color. for corner in Poly(points).corner_adjacencies(): if not board.in_bounds(corner): continue if board.data.get(corner): continue if any(board.data.get(adj) == player for adj in adjacent(corner)): continue score += 1 return score