def test_find_moves(): for board_s, parser, exp_moves_non_sym in FIND_MOVES_CASES: board = parse_board(board_s, parser) yield _verify_find_moves, board, exp_moves_non_sym for num_moves in range(1, (len(exp_moves_non_sym) * 2) + 1): yield (_verify_find_moves_with_stop, board, exp_moves_non_sym, num_moves)
def test_nulls(): board_s = dedent("""\ | | R | R | | Y | | G | | Y | R | | """) parser = create_board_parser(side=3) eq_(re.sub('\s', '', board_s), re.sub('\s', '', unparse_board(parse_board(board_s, parser))))
def test_ensure_playable_board(): rand_state = random.getstate() try: random.seed(100) board_s = dedent("""\ | Y | G | BL | P | | R | Y | BL | R | | G | P | BK | G | | Y | G | BK | P | """) board = parse_board(board_s, FOUR_SIDE_PARSER) offense = TestPlayer(strategy=first_move_strat) defense = TestPlayer(strategy=first_move_strat) game = Game(board=board, offense=offense, defense=defense, stop_condition=_allow_one_move()) game.play() eq_( re.sub( '\s', '', dedent("""\ | P | G | G | R | | BK | BK | BL | BL | | R | P | G | P | | Y | Y | P | Y | """)), re.sub('\s', '', unparse_board(game.board))) # it takes 3 shuffles with this seed to get a playable board with no # matches expected_swaps = [ (3, 3, 0, 0), (3, 2, 2, 2), (3, 1, 3, 2), (3, 0, 0, 1), (2, 3, 0, 3), (2, 2, 2, 0), (2, 1, 3, 0), (2, 0, 3, 3), (1, 3, 0, 2), (1, 2, 1, 0), (1, 1, 2, 3), (1, 0, 1, 3), (0, 3, 1, 2), (0, 2, 1, 1), (0, 1, 2, 1), (0, 0, 3, 1), (3, 3, 0, 0), (3, 2, 1, 1), (3, 1, 1, 3), (3, 0, 3, 3), (2, 3, 1, 0), (2, 2, 2, 2), (2, 1, 0, 1), (2, 0, 2, 0), (1, 3, 3, 2), (1, 2, 1, 2), (1, 1, 2, 1), (1, 0, 2, 3), (0, 3, 0, 2), (0, 2, 3, 1), (0, 1, 3, 0), (0, 0, 0, 3), (3, 3, 2, 1), (3, 2, 3, 2), (3, 1, 0, 3), (3, 0, 1, 3), (2, 3, 0, 0), (2, 2, 0, 1), (2, 1, 2, 3), (2, 0, 3, 0), (1, 3, 1, 0), (1, 2, 0, 2), (1, 1, 1, 2), (1, 0, 3, 1), (0, 3, 2, 0), (0, 2, 1, 1), (0, 1, 2, 2), (0, 0, 3, 3), (0, 0, 1, 0) ] eq_(expected_swaps, offense.update_tiles_swapped_calls) eq_(expected_swaps, defense.update_tiles_swapped_calls) finally: random.setstate(rand_state)
def test_color(): board_s = dedent("""\ | C | C | Y | | T | T | T | | P | P | P | """) board = parse_board(board_s, THREE_SIDE_PARSER) cases = [ (right_match(3)(0, 0), 'Y'), (right_match(3)(1, 0), 'T'), (right_match(3)(2, 0), 'P'), ] for match, exp_color in cases: yield _verify_color, match, exp_color, board
def test_critical_as_second_match_tile(): """ It would be easy to mistakenly call: | C | Y | R | or the like a match, if you were to only use matches() against the first tile in the potential match. Test against that. """ board_s = dedent("""\ | C | Y | R | Y | | R | R | R | Y | | Y | G | G | G | | | | | | """) board = parse_board(board_s, FOUR_SIDE_PARSER) eq_(None, find_right_match_at(0, 0, board))
def test_find_up_match_at(): board_s = dedent("""\ | Y | Y | G | | | Y | R | G | | | Y | R | G | | | Y | R | | | """) board = parse_board(board_s, FOUR_SIDE_PARSER) expected = [ [None, None, None, None], [None, None, None, None], [up_match(3), None, up_match(3), None], [up_match(4), up_match(3), None, None], ] for row in range(board.side): for col in range(board.side): yield (_verify_find_single_match, board, row, col, expected[row][col], find_up_match_at)
def test_find_matches_at(): board_s = dedent("""\ | Y | Y | Y | | | Y | Y | | | | Y | Y | | | | Y | R | R | R | """) board = parse_board(board_s, FOUR_SIDE_PARSER) expected = [ [[down_match(4), right_match(3)], [down_match(3)], [left_match(3)], []], [[down_match(3)], [], [], []], [[up_match(3)], [up_match(3)], [], []], [[up_match(4)], [right_match(3)], [], [left_match(3)]], ] for row in range(board.side): for col in range(board.side): yield (_verify_find_single_match, board, row, col, expected[row][col], find_matches_at)
def test_ensure_playable_board(): rand_state = random.getstate() try: random.seed(100) board_s = dedent("""\ | Y | G | BL | P | | R | Y | BL | R | | G | P | BK | G | | Y | G | BK | P | """) board = parse_board(board_s, FOUR_SIDE_PARSER) offense = TestPlayer(strategy=first_move_strat) defense = TestPlayer(strategy=first_move_strat) game = Game(board=board, offense=offense, defense=defense, stop_condition=_allow_one_move()) game.play() eq_(re.sub('\s', '', dedent("""\ | P | G | G | R | | BK | BK | BL | BL | | R | P | G | P | | Y | Y | P | Y | """)), re.sub('\s', '', unparse_board(game.board))) # it takes 3 shuffles with this seed to get a playable board with no # matches expected_swaps = [(3, 3, 0, 0), (3, 2, 2, 2), (3, 1, 3, 2), (3, 0, 0, 1), (2, 3, 0, 3), (2, 2, 2, 0), (2, 1, 3, 0), (2, 0, 3, 3), (1, 3, 0, 2), (1, 2, 1, 0), (1, 1, 2, 3), (1, 0, 1, 3), (0, 3, 1, 2), (0, 2, 1, 1), (0, 1, 2, 1), (0, 0, 3, 1), (3, 3, 0, 0), (3, 2, 1, 1), (3, 1, 1, 3), (3, 0, 3, 3), (2, 3, 1, 0), (2, 2, 2, 2), (2, 1, 0, 1), (2, 0, 2, 0), (1, 3, 3, 2), (1, 2, 1, 2), (1, 1, 2, 1), (1, 0, 2, 3), (0, 3, 0, 2), (0, 2, 3, 1), (0, 1, 3, 0), (0, 0, 0, 3), (3, 3, 2, 1), (3, 2, 3, 2), (3, 1, 0, 3), (3, 0, 1, 3), (2, 3, 0, 0), (2, 2, 0, 1), (2, 1, 2, 3), (2, 0, 3, 0), (1, 3, 1, 0), (1, 2, 0, 2), (1, 1, 1, 2), (1, 0, 3, 1), (0, 3, 2, 0), (0, 2, 1, 1), (0, 1, 2, 2), (0, 0, 3, 3), (0, 0, 1, 0)] eq_(expected_swaps, offense.update_tiles_swapped_calls) eq_(expected_swaps, defense.update_tiles_swapped_calls) finally: random.setstate(rand_state)
def test_aimulator(): for desc, board_s, parser, colors, exp_move in CASES: board = parse_board(board_s, parser) yield _verify_aimulator, desc, board, colors, exp_move
def test_one_turn_game(): rand_state = random.getstate() try: random.seed(100) board_s = dedent("""\ | Y | G | BL | P | | Y | R | BL | R | | G | G | BK | G | | Y | G | BL | P | """) board = parse_board(board_s, FOUR_SIDE_PARSER) offense = TestPlayer(strategy=first_move_strat) defense = TestPlayer(strategy=first_move_strat) game = Game(board=board, offense=offense, defense=defense, stop_condition=_allow_one_move()) game.play() eq_(1, game.move_count) eq_(1, game.turn_count) eq_(1, offense.moves) eq_(0, defense.moves) eq_([(0, 1, 1, 1)], offense.update_tiles_swapped_calls) eq_([(0, 1, 1, 1)], defense.update_tiles_swapped_calls) eq_([(0, 1, 3, 1)], offense.update_tile_position_calls) eq_([(0, 1, 3, 1)], defense.update_tile_position_calls) eq_([(1, 1, True), (2, 1, True), (3, 1, True)], offense.update_destroyed_tile_calls) eq_([(1, 1, False), (2, 1, False), (3, 1, False)], defense.update_destroyed_tile_calls) eq_(dict(G=3), offense.ap) eq_(dict(), defense.ap) eq_( re.sub( '\s', '', dedent("""\ | Y | G | BL | P | | Y | P | BL | R | | G | BL | BK | G | | Y | R | BL | P | """)), re.sub('\s', '', unparse_board(game.board))) game.stop_condition = _allow_one_move() offense.reset_calls() defense.reset_calls() game.play() eq_(2, game.move_count) eq_(2, game.turn_count) eq_(1, offense.moves) eq_(1, defense.moves) eq_([(2, 0, 3, 0)], offense.update_tiles_swapped_calls) eq_([(2, 0, 3, 0)], defense.update_tiles_swapped_calls) eq_([], offense.update_tile_position_calls) eq_([], defense.update_tile_position_calls) eq_([(0, 0, False), (1, 0, False), (2, 0, False)], offense.update_destroyed_tile_calls) eq_([(0, 0, True), (1, 0, True), (2, 0, True)], defense.update_destroyed_tile_calls) eq_(dict(G=3), offense.ap) eq_(dict(Y=3), defense.ap) eq_( re.sub( '\s', '', dedent("""\ | P | G | BL | P | | G | P | BL | R | | R | BL | BK | G | | G | R | BL | P | """)), re.sub('\s', '', unparse_board(game.board))) finally: # be friendly to other downstream tests that actually want some # randomness random.setstate(rand_state)
def test_find_matches(): for (board_s, parser, expected) in FIND_MATCHES_CASES: board = parse_board(board_s, parser) yield _verify_find_matches, board, expected
def test_rand_move_strat(): for board_s, parser, exp_moves_non_sym in FIND_MOVES_CASES: board = parse_board(board_s, parser) for _ in range(10): yield _verify_rand_move_strat, board, exp_moves_non_sym
def test_find_matches_with_stop_after(): for (board_s, parser, expected) in FIND_MATCHES_CASES: board = parse_board(board_s, parser) for stop_after in range(1, len(expected) + 1): yield (_verify_find_matches_with_stop_after, board, expected, stop_after)
def test_no_move_strat(): for board_s, parser, exp_moves_non_sym in FIND_MOVES_CASES: board = parse_board(board_s, parser) yield _verify_no_move_strat, board
def test_apply_gravity(): for board_s, parser, exp_board_s, exp_moved in TEST_CASES: board = parse_board(board_s, parser) yield _verify_apply_gravity, board, exp_board_s, exp_moved
def _verify_destroy_tiles(board_s, parser, e_new_board_s, e_destroyed): board = parse_board(board_s, parser) new_board, destroyed = destroy_tiles(board) eq_(sorted(list(set(e_destroyed))), destroyed) eq_(re.sub('\s', '', e_new_board_s), re.sub('\s', '', unparse_board(new_board)))
def _verify_parse_and_unparse(board_s): eq_(board_s, unparse_board(parse_board(board_s)))
def test_one_turn_game(): rand_state = random.getstate() try: random.seed(100) board_s = dedent("""\ | Y | G | BL | P | | Y | R | BL | R | | G | G | BK | G | | Y | G | BL | P | """) board = parse_board(board_s, FOUR_SIDE_PARSER) offense = TestPlayer(strategy=first_move_strat) defense = TestPlayer(strategy=first_move_strat) game = Game(board=board, offense=offense, defense=defense, stop_condition=_allow_one_move()) game.play() eq_(1, game.move_count) eq_(1, game.turn_count) eq_(1, offense.moves) eq_(0, defense.moves) eq_([(0, 1, 1, 1)], offense.update_tiles_swapped_calls) eq_([(0, 1, 1, 1)], defense.update_tiles_swapped_calls) eq_([(0, 1, 3, 1)], offense.update_tile_position_calls) eq_([(0, 1, 3, 1)], defense.update_tile_position_calls) eq_([(1, 1, True), (2, 1, True), (3, 1, True)], offense.update_destroyed_tile_calls) eq_([(1, 1, False), (2, 1, False), (3, 1, False)], defense.update_destroyed_tile_calls) eq_(dict(G=3), offense.ap) eq_(dict(), defense.ap) eq_(re.sub('\s', '', dedent("""\ | Y | G | BL | P | | Y | P | BL | R | | G | BL | BK | G | | Y | R | BL | P | """)), re.sub('\s', '', unparse_board(game.board))) game.stop_condition = _allow_one_move() offense.reset_calls() defense.reset_calls() game.play() eq_(2, game.move_count) eq_(2, game.turn_count) eq_(1, offense.moves) eq_(1, defense.moves) eq_([(2, 0, 3, 0)], offense.update_tiles_swapped_calls) eq_([(2, 0, 3, 0)], defense.update_tiles_swapped_calls) eq_([], offense.update_tile_position_calls) eq_([], defense.update_tile_position_calls) eq_([(0, 0, False), (1, 0, False), (2, 0, False)], offense.update_destroyed_tile_calls) eq_([(0, 0, True), (1, 0, True), (2, 0, True)], defense.update_destroyed_tile_calls) eq_(dict(G=3), offense.ap) eq_(dict(Y=3), defense.ap) eq_(re.sub('\s', '', dedent("""\ | P | G | BL | P | | G | P | BL | R | | R | BL | BK | G | | G | R | BL | P | """)), re.sub('\s', '', unparse_board(game.board))) finally: # be friendly to other downstream tests that actually want some # randomness random.setstate(rand_state)
def test_ap_seeking_strat(): for desc, board_s, parser, colors, exp_move in AP_SEEKING_CASES: board = parse_board(board_s, parser) yield _verify_ap_seeking_strat, desc, board, colors, exp_move