def test_merge_slide_one_side(): """Tests merge slide. Splits a1 to a4 and d1 and then merges to d4. The square c4 will block one path of the merge in superposition. """ b = simulator(u.squares_to_bitboard(["a1", "c3"])) assert b.perform_moves( "a1^a4d1:SPLIT_SLIDE:BASIC", "c3^c4c5:SPLIT_JUMP:BASIC", "a4d1^d4:MERGE_SLIDE:BASIC", ) possibilities = [ u.squares_to_bitboard(["a4", "c4"]), u.squares_to_bitboard(["d4", "c4"]), u.squares_to_bitboard(["d4", "c5"]), ] assert_samples_in(b, possibilities) probs = b.get_probability_distribution(20000) assert_fifty_fifty(probs, qb.square_to_bit("c4")) assert_fifty_fifty(probs, qb.square_to_bit("c5")) assert_prob_about(probs, qb.square_to_bit("a4"), 0.25) assert_prob_about(probs, qb.square_to_bit("d4"), 0.75) board_probs = b.get_board_probability_distribution(20000) assert len(board_probs) == len(possibilities) assert_prob_about(board_probs, possibilities[0], 0.25) assert_prob_about(board_probs, possibilities[1], 0.25) assert_prob_about(board_probs, possibilities[2], 0.5)
def test_split_one_slide(board): """Tests a split slide with one blocked path. a1 will split to a3 and c1 with square a2 blocked in superposition. """ b = board(u.squares_to_bitboard(['a1', 'b2'])) assert b.perform_moves( 'b2^a2c2:SPLIT_JUMP:BASIC', 'a1^a3c1:SPLIT_SLIDE:BASIC', ) samples = b.sample(100) possibilities = [ u.squares_to_bitboard(['c1', 'a2']), u.squares_to_bitboard(['a3', 'c2']), u.squares_to_bitboard(['c1', 'c2']), ] assert (all(sample in possibilities for sample in samples)) probs = b.get_probability_distribution(10000) assert_fifty_fifty(probs, qb.square_to_bit('a2')) assert_fifty_fifty(probs, qb.square_to_bit('c2')) assert_prob_about(probs, qb.square_to_bit('a3'), 0.25) assert_prob_about(probs, qb.square_to_bit('c1'), 0.75) board_probs = b.get_board_probability_distribution(10000) assert len(board_probs) == len(possibilities) assert_prob_about(board_probs, possibilities[0], 0.5) assert_prob_about(board_probs, possibilities[1], 0.25) assert_prob_about(board_probs, possibilities[2], 0.25)
def test_merge_slide_both_side(board): """Tests a merge slide where both paths are blocked. Splits a1 to a4/d1 and merges back to d4. c4 and d3 will block one square on each path. """ b = board.with_state(u.squares_to_bitboard(['a1', 'c2', 'c3'])) assert b.perform_moves( 'a1a4d1:SPLIT_SLIDE:BASIC', 'c3c4c5:SPLIT_JUMP:BASIC', 'c2d2e2:SPLIT_JUMP:BASIC', 'a4d4--d1:MERGE_SLIDE:BASIC', ) possibilities = [ u.squares_to_bitboard(['a4', 'd2', 'c4']), u.squares_to_bitboard(['d1', 'd2', 'c4']), u.squares_to_bitboard(['a4', 'e2', 'c4']), u.squares_to_bitboard(['d4', 'e2', 'c4']), u.squares_to_bitboard(['d1', 'd2', 'c5']), u.squares_to_bitboard(['d4', 'd2', 'c5']), u.squares_to_bitboard(['d4', 'e2', 'c5']), ] assert_samples_in(b, possibilities) probs = b.get_probability_distribution(20000) assert_fifty_fifty(probs, qb.square_to_bit('c4')) assert_fifty_fifty(probs, qb.square_to_bit('c5')) assert_fifty_fifty(probs, qb.square_to_bit('d2')) assert_fifty_fifty(probs, qb.square_to_bit('e2')) assert_fifty_fifty(probs, qb.square_to_bit('d4')) assert_prob_about(probs, qb.square_to_bit('a4'), 0.25) assert_prob_about(probs, qb.square_to_bit('d1'), 0.25)
def test_split_one_slide(): """Tests a split slide with one blocked path. a1 will split to a3 and c1 with square a2 blocked in superposition. """ b = simulator(u.squares_to_bitboard(["a1", "b2"])) assert b.perform_moves( "b2^a2c2:SPLIT_JUMP:BASIC", "a1^a3c1:SPLIT_SLIDE:BASIC", ) samples = b.sample(100) possibilities = [ u.squares_to_bitboard(["c1", "a2"]), u.squares_to_bitboard(["a3", "c2"]), u.squares_to_bitboard(["c1", "c2"]), ] assert all(sample in possibilities for sample in samples) probs = b.get_probability_distribution(10000) assert_fifty_fifty(probs, qb.square_to_bit("a2")) assert_fifty_fifty(probs, qb.square_to_bit("c2")) assert_prob_about(probs, qb.square_to_bit("a3"), 0.25) assert_prob_about(probs, qb.square_to_bit("c1"), 0.75) board_probs = b.get_board_probability_distribution(10000) assert len(board_probs) == len(possibilities) assert_prob_about(board_probs, possibilities[0], 0.5) assert_prob_about(board_probs, possibilities[1], 0.25) assert_prob_about(board_probs, possibilities[2], 0.25)
def test_merge_slide_one_side(board): """Tests merge slide. Splits a1 to a4 and d1 and then merges to d4. The square c4 will block one path of the merge in superposition. """ b = board(u.squares_to_bitboard(['a1', 'c3'])) assert b.perform_moves( 'a1^a4d1:SPLIT_SLIDE:BASIC', 'c3^c4c5:SPLIT_JUMP:BASIC', 'a4d1^d4:MERGE_SLIDE:BASIC', ) possibilities = [ u.squares_to_bitboard(['a4', 'c4']), u.squares_to_bitboard(['d4', 'c4']), u.squares_to_bitboard(['d4', 'c5']), ] assert_samples_in(b, possibilities) probs = b.get_probability_distribution(20000) assert_fifty_fifty(probs, qb.square_to_bit('c4')) assert_fifty_fifty(probs, qb.square_to_bit('c5')) assert_prob_about(probs, qb.square_to_bit('a4'), 0.25) assert_prob_about(probs, qb.square_to_bit('d4'), 0.75) board_probs = b.get_board_probability_distribution(20000) assert len(board_probs) == len(possibilities) assert_prob_about(board_probs, possibilities[0], 0.25) assert_prob_about(board_probs, possibilities[1], 0.25) assert_prob_about(board_probs, possibilities[2], 0.5)
def test_superposition_slide_move2(board): """Tests a basic slide through a superposition of two pieces. Splits b3 and c3 to b2/b1 and c2/c1 then slides a1 to d1. """ b = board.with_state(u.squares_to_bitboard(['a1', 'b3', 'c3'])) assert b.perform_moves( 'b3b2b1:SPLIT_JUMP:BASIC', 'c3c2c1:SPLIT_JUMP:BASIC', 'a1e1:SLIDE:BASIC', ) possibilities = [ u.squares_to_bitboard(['a1', 'b1', 'c1']), u.squares_to_bitboard(['a1', 'b1', 'c2']), u.squares_to_bitboard(['a1', 'b2', 'c1']), u.squares_to_bitboard(['e1', 'b2', 'c2']) ] samples = b.sample(100) assert (all(sample in possibilities for sample in samples)) probs = b.get_probability_distribution(10000) assert_fifty_fifty(probs, u.square_to_bit('b2')) assert_fifty_fifty(probs, u.square_to_bit('b1')) assert_fifty_fifty(probs, u.square_to_bit('c2')) assert_fifty_fifty(probs, u.square_to_bit('c1')) assert_prob_about(probs, u.square_to_bit('a1'), 0.75) assert_prob_about(probs, u.square_to_bit('e1'), 0.25)
def test_superposition_slide_move(board): """Tests a basic slide through a superposition. Sets up superposition of c1 and f1 with a slide from a1 to d1. Valid end state should be a1 and c1 (blocked), state = 5, or d1 and f1 (unblocked), state = 40. """ b = board.with_state(u.squares_to_bitboard(['a1', 'e1'])) b.do_move( move.Move('e1', 'f1', target2='c1', move_type=enums.MoveType.SPLIT_JUMP, move_variant=enums.MoveVariant.BASIC)) b.do_move( move.Move('a1', 'd1', move_type=enums.MoveType.SLIDE, move_variant=enums.MoveVariant.BASIC)) blocked = u.squares_to_bitboard(['a1', 'c1']) moved = u.squares_to_bitboard(['d1', 'f1']) assert_samples_in(b, [blocked, moved]) probs = b.get_probability_distribution(5000) assert_fifty_fifty(probs, 0) assert_fifty_fifty(probs, 2) assert_fifty_fifty(probs, 3) assert_fifty_fifty(probs, 5)
def test_split_move(move_type, board): b = board.with_state(u.squares_to_bitboard(['a1'])) b.do_move( move.Move('a1', 'a3', target2='c1', move_type=move_type, move_variant=enums.MoveVariant.BASIC)) samples = b.sample(100) assert_this_or_that(samples, u.squares_to_bitboard(['a3']), u.squares_to_bitboard(['c1'])) probs = b.get_probability_distribution(5000) assert_fifty_fifty(probs, qb.square_to_bit('a3')) assert_fifty_fifty(probs, qb.square_to_bit('c1')) # Test doing a jump after a split move m = move.Move('c1', 'd1', move_type=enums.MoveType.JUMP, move_variant=enums.MoveVariant.BASIC) did_it_move = b.do_move(m) samples = b.sample(100) assert_this_or_that(samples, u.squares_to_bitboard(['a3']), u.squares_to_bitboard(['d1'])) probs = b.get_probability_distribution(5000) assert_fifty_fifty(probs, u.square_to_bit('a3')) assert_fifty_fifty(probs, u.square_to_bit('d1'))
def test_superposition_slide_move2(): """Tests a basic slide through a superposition of two pieces. Splits b3 and c3 to b2/b1 and c2/c1 then slides a1 to d1. """ b = simulator(u.squares_to_bitboard(["a1", "b3", "c3"])) assert b.perform_moves( "b3^b2b1:SPLIT_JUMP:BASIC", "c3^c2c1:SPLIT_JUMP:BASIC", "a1e1:SLIDE:BASIC", ) possibilities = [ u.squares_to_bitboard(["a1", "b1", "c1"]), u.squares_to_bitboard(["a1", "b1", "c2"]), u.squares_to_bitboard(["a1", "b2", "c1"]), u.squares_to_bitboard(["e1", "b2", "c2"]), ] samples = b.sample(100) assert all(sample in possibilities for sample in samples) probs = b.get_probability_distribution(10000) assert_fifty_fifty(probs, u.square_to_bit("b2")) assert_fifty_fifty(probs, u.square_to_bit("b1")) assert_fifty_fifty(probs, u.square_to_bit("c2")) assert_fifty_fifty(probs, u.square_to_bit("c1")) assert_prob_about(probs, u.square_to_bit("a1"), 0.75) assert_prob_about(probs, u.square_to_bit("e1"), 0.25) board_probs = b.get_board_probability_distribution(10000) assert len(board_probs) == len(possibilities) for possibility in possibilities: assert_prob_about(board_probs, possibility, 0.25)
def test_split_and_use_same_square(board): b = board(u.squares_to_bitboard(["a1"])) assert b.perform_moves( "a1^a2b1:SPLIT_JUMP:BASIC", "b1b2:JUMP:BASIC", "b2a2:JUMP:BASIC", ) assert_sample_distribution(b, { u.squares_to_bitboard(["a2"]): 1 / 2, u.squares_to_bitboard(["b2"]): 1 / 2 }) board_probs = b.get_board_probability_distribution(5000) assert len(board_probs) == 2 assert_fifty_fifty(board_probs, u.squares_to_bitboard(["a2"])) assert_fifty_fifty(board_probs, u.squares_to_bitboard(["b2"]))
def test_pawn_capture(board): """Tests pawn capture with entanglement. Rook on a3 => a4/a5 and rook on c3 => c4/c5. Pawn on b3 attempts to capture both rooks. The first capture should put the pawn in super-position, and the second should force a measurement. """ b = board.with_state(u.squares_to_bitboard(['a3', 'b3', 'c3'])) # Capture and put the pawn in superposition assert b.perform_moves('a3a4a5:SPLIT_JUMP:BASIC', 'b3a4:PAWN_CAPTURE:BASIC') possibilities = [ u.squares_to_bitboard(['a5', 'b3', 'c3']), u.squares_to_bitboard(['a4', 'c3']), ] assert_samples_in(b, possibilities) probs = b.get_probability_distribution(5000) assert_fifty_fifty(probs, qb.square_to_bit('a5')) assert_fifty_fifty(probs, qb.square_to_bit('a4')) assert_fifty_fifty(probs, qb.square_to_bit('b3')) did_it_move = b.perform_moves('c3c4c5:SPLIT_JUMP:BASIC', 'b3c4:PAWN_CAPTURE:BASIC') if did_it_move: possibilities = [ u.squares_to_bitboard(['a5', 'b3', 'c5']), u.squares_to_bitboard(['a5', 'c4']), ] else: possibilities = [ u.squares_to_bitboard(['a4', 'c4']), u.squares_to_bitboard(['a4', 'c5']), ] assert_samples_in(b, possibilities)
def test_merge_slide_both_side(): """Tests a merge slide where both paths are blocked. Splits a1 to a4/d1 and merges back to d4. c4 and d3 will block one square on each path. """ b = simulator(u.squares_to_bitboard(["a1", "c2", "c3"])) assert b.perform_moves( "a1^a4d1:SPLIT_SLIDE:BASIC", "c3^c4c5:SPLIT_JUMP:BASIC", "c2^d2e2:SPLIT_JUMP:BASIC", "a4d1^d4:MERGE_SLIDE:BASIC", ) possibilities = [ u.squares_to_bitboard(["a4", "d2", "c4"]), u.squares_to_bitboard(["d1", "d2", "c4"]), u.squares_to_bitboard(["a4", "e2", "c4"]), u.squares_to_bitboard(["d4", "e2", "c4"]), u.squares_to_bitboard(["d1", "d2", "c5"]), u.squares_to_bitboard(["d4", "d2", "c5"]), u.squares_to_bitboard(["d4", "e2", "c5"]), ] assert_samples_in(b, possibilities) probs = b.get_probability_distribution(20000) assert_fifty_fifty(probs, qb.square_to_bit("c4")) assert_fifty_fifty(probs, qb.square_to_bit("c5")) assert_fifty_fifty(probs, qb.square_to_bit("d2")) assert_fifty_fifty(probs, qb.square_to_bit("e2")) assert_fifty_fifty(probs, qb.square_to_bit("d4")) assert_prob_about(probs, qb.square_to_bit("a4"), 0.25) assert_prob_about(probs, qb.square_to_bit("d1"), 0.25) board_probs = b.get_board_probability_distribution(20000) assert len(board_probs) == len(possibilities) for possibility in possibilities[:6]: assert_prob_about(board_probs, possibility, 0.125) assert_prob_about(board_probs, possibilities[6], 0.25)
def test_split_both_sides(board): """ Tests a split slide move where both paths of the slide are blocked in superposition. The piece will split from a1 to a5/e1. The squares c1 and d1 will block one side of the path in superposition. The square a3 will be blocked on the other path. This will create a lop-sided distribution to test multi-square paths. """ b = board.with_state(u.squares_to_bitboard(['a1', 'b3', 'c3', 'd3'])) assert b.perform_moves( 'b3a3b4:SPLIT_JUMP:BASIC', 'c3c2c1:SPLIT_JUMP:BASIC', 'd3d2d1:SPLIT_JUMP:BASIC', 'a1a5e1:SPLIT_SLIDE:BASIC', ) samples = b.sample(1000) assert len(samples) == 1000 possibilities = [ # a1/a5/e1 a3/b4 c1/c2 d1/d2 u.squares_to_bitboard(['a1', 'a3', 'c1', 'd1']), u.squares_to_bitboard(['a1', 'a3', 'c1', 'd2']), u.squares_to_bitboard(['a1', 'a3', 'c2', 'd1']), u.squares_to_bitboard(['e1', 'a3', 'c2', 'd2']), u.squares_to_bitboard(['a5', 'b4', 'c1', 'd1']), u.squares_to_bitboard(['a5', 'b4', 'c1', 'd2']), u.squares_to_bitboard(['a5', 'b4', 'c2', 'd1']), u.squares_to_bitboard(['a5', 'b4', 'c2', 'd2']), u.squares_to_bitboard(['e1', 'b4', 'c2', 'd2']), ] assert (all(sample in possibilities for sample in samples)) probs = b.get_probability_distribution(25000) assert_fifty_fifty(probs, qb.square_to_bit('a3')) assert_fifty_fifty(probs, qb.square_to_bit('b4')) assert_fifty_fifty(probs, qb.square_to_bit('c1')) assert_fifty_fifty(probs, qb.square_to_bit('c2')) assert_fifty_fifty(probs, qb.square_to_bit('d1')) assert_fifty_fifty(probs, qb.square_to_bit('d2')) assert_prob_about(probs, qb.square_to_bit('a1'), 0.375) assert_prob_about(probs, qb.square_to_bit('e1'), 0.1875) assert_prob_about(probs, qb.square_to_bit('a5'), 0.4375)
def test_pawn_capture(): """Tests pawn capture with entanglement. Rook on a3 => a4/a5 and rook on c3 => c4/c5. Pawn on b3 attempts to capture both rooks. The first capture should put the pawn in super-position, and the second should force a measurement. """ b = simulator(u.squares_to_bitboard(["a3", "b3", "c3"])) # Capture and put the pawn in superposition assert b.perform_moves("a3^a4a5:SPLIT_JUMP:BASIC", "b3a4:PAWN_CAPTURE:BASIC") possibilities = [ u.squares_to_bitboard(["a5", "b3", "c3"]), u.squares_to_bitboard(["a4", "c3"]), ] assert_samples_in(b, possibilities) probs = b.get_probability_distribution(5000) assert_fifty_fifty(probs, qb.square_to_bit("a5")) assert_fifty_fifty(probs, qb.square_to_bit("a4")) assert_fifty_fifty(probs, qb.square_to_bit("b3")) board_probs = b.get_board_probability_distribution(5000) assert len(board_probs) == len(possibilities) assert_fifty_fifty(board_probs, possibilities[0]) assert_fifty_fifty(board_probs, possibilities[1]) did_it_move = b.perform_moves("c3^c4c5:SPLIT_JUMP:BASIC", "b3c4:PAWN_CAPTURE:BASIC") if did_it_move: possibilities = [ u.squares_to_bitboard(["a5", "b3", "c5"]), u.squares_to_bitboard(["a5", "c4"]), ] else: possibilities = [ u.squares_to_bitboard(["a4", "c4"]), u.squares_to_bitboard(["a4", "c5"]), ] assert_samples_in(b, possibilities) board_probs = b.get_board_probability_distribution(5000) assert len(board_probs) == 2 assert_fifty_fifty(board_probs, possibilities[0]) assert_fifty_fifty(board_probs, possibilities[1])
def test_split_both_sides(): """Tests a split slide move where both paths of the slide are blocked in superposition. The piece will split from a1 to a5/e1. The squares c1 and d1 will block one side of the path in superposition. The square a3 will be blocked on the other path. This will create a lop-sided distribution to test multi-square paths. """ b = simulator(u.squares_to_bitboard(["a1", "b3", "c3", "d3"])) assert b.perform_moves( "b3^a3b4:SPLIT_JUMP:BASIC", "c3^c2c1:SPLIT_JUMP:BASIC", "d3^d2d1:SPLIT_JUMP:BASIC", "a1^a5e1:SPLIT_SLIDE:BASIC", ) samples = b.sample(1000) assert len(samples) == 1000 possibilities = [ # a1/a5/e1 a3/b4 c1/c2 d1/d2 u.squares_to_bitboard(["a1", "a3", "c1", "d1"]), u.squares_to_bitboard(["a1", "a3", "c1", "d2"]), u.squares_to_bitboard(["a1", "a3", "c2", "d1"]), u.squares_to_bitboard(["e1", "a3", "c2", "d2"]), u.squares_to_bitboard(["a5", "b4", "c1", "d1"]), u.squares_to_bitboard(["a5", "b4", "c1", "d2"]), u.squares_to_bitboard(["a5", "b4", "c2", "d1"]), u.squares_to_bitboard(["a5", "b4", "c2", "d2"]), u.squares_to_bitboard(["e1", "b4", "c2", "d2"]), ] assert all(sample in possibilities for sample in samples) probs = b.get_probability_distribution(25000) assert_fifty_fifty(probs, qb.square_to_bit("a3")) assert_fifty_fifty(probs, qb.square_to_bit("b4")) assert_fifty_fifty(probs, qb.square_to_bit("c1")) assert_fifty_fifty(probs, qb.square_to_bit("c2")) assert_fifty_fifty(probs, qb.square_to_bit("d1")) assert_fifty_fifty(probs, qb.square_to_bit("d2")) assert_prob_about(probs, qb.square_to_bit("a1"), 0.375) assert_prob_about(probs, qb.square_to_bit("e1"), 0.1875) assert_prob_about(probs, qb.square_to_bit("a5"), 0.4375) board_probs = b.get_board_probability_distribution(25000) assert len(board_probs) == len(possibilities) for possibility in possibilities[:7]: assert_prob_about(board_probs, possibility, 0.125) for possibility in possibilities[7:]: assert_prob_about(board_probs, possibility, 0.0625)
def test_superposition_slide_move(board): """Tests a basic slide through a superposition. Sets up superposition of c1 and f1 with a slide from a1 to d1. Valid end state should be a1 and c1 (blocked), state = 5, or d1 and f1 (unblocked), state = 40. """ b = board(u.squares_to_bitboard(["a1", "e1"])) b.do_move( move.Move( "e1", "f1", target2="c1", move_type=enums.MoveType.SPLIT_JUMP, move_variant=enums.MoveVariant.BASIC, )) b.do_move( move.Move( "a1", "d1", move_type=enums.MoveType.SLIDE, move_variant=enums.MoveVariant.BASIC, )) blocked = u.squares_to_bitboard(["a1", "c1"]) moved = u.squares_to_bitboard(["d1", "f1"]) assert_samples_in(b, [blocked, moved]) probs = b.get_probability_distribution(5000) assert_fifty_fifty(probs, 0) assert_fifty_fifty(probs, 2) assert_fifty_fifty(probs, 3) assert_fifty_fifty(probs, 5) board_probs = b.get_board_probability_distribution(5000) assert len(board_probs) == 2 assert_fifty_fifty(board_probs, blocked) assert_fifty_fifty(board_probs, moved)
def test_split_move(move_type, board): b = board(u.squares_to_bitboard(["a1"])) b.do_move( move.Move( "a1", "a3", target2="c1", move_type=move_type, move_variant=enums.MoveVariant.BASIC, )) samples = b.sample(100) assert_this_or_that(samples, u.squares_to_bitboard(["a3"]), u.squares_to_bitboard(["c1"])) probs = b.get_probability_distribution(5000) assert_fifty_fifty(probs, qb.square_to_bit("a3")) assert_fifty_fifty(probs, qb.square_to_bit("c1")) board_probs = b.get_board_probability_distribution(5000) assert len(board_probs) == 2 assert_fifty_fifty(board_probs, u.squares_to_bitboard(["a3"])) assert_fifty_fifty(board_probs, u.squares_to_bitboard(["c1"])) # Test doing a jump after a split move m = move.Move("c1", "d1", move_type=enums.MoveType.JUMP, move_variant=enums.MoveVariant.BASIC) assert b.do_move(m) samples = b.sample(100) assert_this_or_that(samples, u.squares_to_bitboard(["a3"]), u.squares_to_bitboard(["d1"])) probs = b.get_probability_distribution(5000) assert_fifty_fifty(probs, u.square_to_bit("a3")) assert_fifty_fifty(probs, u.square_to_bit("d1")) board_probs = b.get_board_probability_distribution(5000) assert len(board_probs) == 2 assert_fifty_fifty(board_probs, u.squares_to_bitboard(["a3"])) assert_fifty_fifty(board_probs, u.squares_to_bitboard(["d1"]))