def search_point(board, gen_pattern, color, point): """Search for a 1d pattern on a 2d board including the given point.""" (x, y) = point side = board.shape[0] pattern = get_pattern(gen_pattern, color) length = pattern.size matches = [] for d in range(NUM_DIRECTIONS): (row_inc, col_inc) = increments(d) (s_min, s_max) = index_bounds_incl(side, length, x, y, row_inc, col_inc) for h in range(s_min, s_max): (i, j) = (x + row_inc * h, y + col_inc * h) for k in range(length): if not pattern[k] & board[i + row_inc * k, j + col_inc * k]: break else: # Store Ordered Line Segment, a -> b, where the pattern lies. a = (i, j) b = (i + row_inc * (length - 1), j + col_inc * (length - 1)) matches.append((a, b)) dedupe_matches(matches) return matches
def subtest_search_fns(gen_pattern, color, own_sqs, defcon): pattern = get_pattern(gen_pattern, color) length = pattern.size for i in range(SIDE_LEN): for j in range(SIDE_LEN): for d in range(NUM_DIRECTIONS): board = new_board() if apply_pattern(board, pattern, (i, j), d): (row_inc, col_inc) = increments(d) start = (i, j) end = (i + row_inc * (length - 1), j + col_inc * (length - 1)) subtest_search_board(board, gen_pattern, color, start, end) subtest_search_point(board, gen_pattern, color, start, end) subtest_search_point_own(board, gen_pattern, color, own_sqs, start, end) subtest_search_board_next_sq(board, gen_pattern, color, own_sqs, defcon, start, end) subtest_search_point_next_sq(board, gen_pattern, color, own_sqs, defcon, start, end) subtest_search_point_own_next_sq(board, gen_pattern, color, own_sqs, defcon, start, end)
def search_board(board, gen_pattern, color): """Search for a 1d pattern on a 2d board.""" side = board.shape[0] pattern = get_pattern(gen_pattern, color) length = pattern.size matches = [] for d in range(NUM_DIRECTIONS): (row_inc, col_inc) = increments(d) (row_min, row_max) = index_bounds(side, length, row_inc) (col_min, col_max) = index_bounds(side, length, col_inc) for i in range(row_min, row_max): for j in range(col_min, col_max): for k in range(length): if not pattern[k] & board[i + row_inc * k, j + col_inc * k]: break else: # Store Ordered Line Segment, a -> b, where the pattern lies. a = (i, j) b = (i + row_inc * (length - 1), j + col_inc * (length - 1)) matches.append((a, b)) dedupe_matches(matches) return matches
def apply_pattern(board, pattern, point, d): """Apply given pattern at given point in given direction. Returns True if application was succesful. Else, returns False. If application fails then board is unchanged. We only check that the length fits at that point. We will apply a non-standard element as it is, including overwriting a wall with any element whatsoever. Useful for testing purposes. """ (x, y) = point side = board.shape[0] length = pattern.size (row_inc, col_inc) = increments(d) can_apply = True for k in range(length): (i, j) = (x + row_inc * k, y + col_inc * k) if i not in range(side) or j not in range(side): can_apply = False break if can_apply: for k in range(length): # NOTE: If it's a non-standard element, we just apply it as is. board[x + row_inc * k, y + col_inc * k] = pattern[k] return can_apply
def search_point_own(board, gen_pattern, color, point, own_sqs): """Search for a 1d pattern on a 2d board including the given point as an own_sq.""" (x, y) = point side = board.shape[0] pattern = get_pattern(gen_pattern, color) length = pattern.size matches = [] # We are searching for patterns including the given point as an "own_sq". if board[point] == color: for d in range(NUM_DIRECTIONS): (row_inc, col_inc) = increments(d) (s_min, s_max) = index_bounds_incl(side, length, x, y, row_inc, col_inc) for own_sq in own_sqs: if s_min <= -own_sq < s_max: (i, j) = (x - row_inc * own_sq, y - col_inc * own_sq) for k in range(length): if not pattern[k] & board[i + row_inc * k, j + col_inc * k]: break else: # Store Ordered Line Segment, a -> b, where the pattern lies. a = (i, j) b = (i + row_inc * (length - 1), j + col_inc * (length - 1)) matches.append((a, b)) dedupe_matches(matches) return matches
def search_point_own_next_sq(board, gen_pattern, color, point, own_sqs): """Search for a 1d pattern on a 2d board including the given point as an own_sq. Returns "next_sq"s and the corresponding pattern matches (as in above functions) as a list of (next_sq, match) pairs. In existing terminology, "point" is a "rest" square, and "next_sq" is the "gain" square. """ (x, y) = point side = board.shape[0] pattern = get_pattern(gen_pattern, color) length = pattern.size next_sq_match_pairs = [] # We are searching for patterns including the given point as an "own_sq". if board[point] == color: for d in range(NUM_DIRECTIONS): (row_inc, col_inc) = increments(d) (s_min, s_max) = index_bounds_incl(side, length, x, y, row_inc, col_inc) for own_sq in own_sqs: if s_min <= -own_sq < s_max: (i, j) = (x - row_inc * own_sq, y - col_inc * own_sq) found_next_sq = False k_next_sq = -1 for k in range(length): p_val = pattern[k] b_val = board[i + row_inc * k, j + col_inc * k] if not p_val & b_val: if not found_next_sq and p_val == color and b_val == EMPTY: found_next_sq = True k_next_sq = k else: break else: if found_next_sq: # Store Ordered Line Segment, a -> b, where the pattern lies. a = (i, j) b = (i + row_inc * (length - 1), j + col_inc * (length - 1)) next_sq = (i + row_inc * k_next_sq, j + col_inc * k_next_sq) next_sq_match_pairs.append((next_sq, (a, b))) dedupe_next_sq_match_pairs(next_sq_match_pairs) return next_sq_match_pairs
def search_board_next_sq(board, gen_pattern, color): """Search for a 1d pattern on a 2d board. Returns "next_sq"s and the corresponding pattern matches (as in above functions) as a list of (next_sq, match) pairs. In existing terminology, "point" is a "rest" square, and "next_sq" is the "gain" square. """ side = board.shape[0] pattern = get_pattern(gen_pattern, color) length = pattern.size next_sq_match_pairs = [] for d in range(NUM_DIRECTIONS): (row_inc, col_inc) = increments(d) (row_min, row_max) = index_bounds(side, length, row_inc) (col_min, col_max) = index_bounds(side, length, col_inc) for i in range(row_min, row_max): for j in range(col_min, col_max): found_next_sq = False k_next_sq = -1 for k in range(length): p_val = pattern[k] b_val = board[i + row_inc * k, j + col_inc * k] if not p_val & b_val: if not found_next_sq and p_val == color and b_val == EMPTY: found_next_sq = True k_next_sq = k else: break else: if found_next_sq: # Store Ordered Line Segment, a -> b, where the pattern lies. a = (i, j) b = (i + row_inc * (length - 1), j + col_inc * (length - 1)) next_sq = (i + row_inc * k_next_sq, j + col_inc * k_next_sq) next_sq_match_pairs.append((next_sq, (a, b))) dedupe_next_sq_match_pairs(next_sq_match_pairs) return next_sq_match_pairs