def test_get_probability_distribution_split_jump_first_move_pre_cached(board): b = board(u.squares_to_bitboard(['a1', 'b1'])) # Cache a split jump in advance. cache_key = CacheKey(enums.MoveType.SPLIT_JUMP, 100) b.cache_results(cache_key) m1 = move.Move('b1', 'c1', target2='d1', move_type=enums.MoveType.SPLIT_JUMP, move_variant=enums.MoveVariant.BASIC) b.do_move(m1) b.clear_debug_log() # Expected probability with the cache applied expected_probs = [0] * 64 expected_probs[square_to_bit('a1')] = 1 expected_probs[square_to_bit('b1')] = 0 expected_probs[square_to_bit('c1')] = b.cache[cache_key]["target"] expected_probs[square_to_bit('d1')] = b.cache[cache_key]["target2"] # Get probability distribution should apply the cache without rerunning _generate_accumulations. probs = b.get_probability_distribution(100, use_cache=True) full_squares = b.get_full_squares_bitboard(100, use_cache=True) empty_squares = b.get_empty_squares_bitboard(100, use_cache=True) assert probs == expected_probs # Check that the second run and getting full and empty bitboards did not trigger any new logs. assert len(b.debug_log) == 0 # Check bitboard updated correctly assert not nth_bit_of(square_to_bit('b1'), full_squares) assert not nth_bit_of(square_to_bit('c1'), full_squares) assert not nth_bit_of(square_to_bit('d1'), full_squares) assert nth_bit_of(square_to_bit('b1'), empty_squares)
def cache_results(self, cache_key: CacheKey): if cache_key in self.cache: return if cache_key.move_type == enums.MoveType.SPLIT_JUMP: helper_board = CirqBoard( DEFAULT_CHESS_INIT_STATE, self.sampler, self.device, self.error_mitigation, self.noise_mitigation, self.transformer if self.device else None, ) sample_jump_move = move.Move( "b1", "c3", target2="a3", move_type=enums.MoveType.SPLIT_JUMP, move_variant=enums.MoveVariant.BASIC, ) helper_board.do_move(sample_jump_move) probs = helper_board.get_probability_distribution( cache_key.repetitions, use_cache=False) self.cache[cache_key] = { "source": 0, "target": probs[square_to_bit(sample_jump_move.target)], "target2": probs[square_to_bit(sample_jump_move.target2)], } self.debug_log += helper_board.debug_log
def test_jump_with_successful_measurement_outcome(board): b = board.with_state(u.squares_to_bitboard(['b1', 'c2'])) b.do_move( move.Move('b1', 'a3', target2='c3', move_type=enums.MoveType.SPLIT_JUMP, move_variant=enums.MoveVariant.BASIC)) b.do_move( move.Move('c2', 'c3', move_type=enums.MoveType.JUMP, move_variant=enums.MoveVariant.EXCLUDED, measurement=1)) samples = b.sample(100) assert_samples_in(b, [u.squares_to_bitboard(['c3', 'a3'])])
def test_merge_move(board): """Splits piece on a1 to b1 and c1 and then merges back to a1.""" b = board.with_state(u.squares_to_bitboard(['a1'])) b.do_move( move.Move('a1', 'b1', target2='c1', move_type=enums.MoveType.SPLIT_JUMP, move_variant=enums.MoveVariant.BASIC)) b.do_move( move.Move('b1', 'a1', source2='c1', move_type=enums.MoveType.MERGE_JUMP, move_variant=enums.MoveVariant.BASIC)) assert_samples_in(b, [u.squares_to_bitboard(['a1'])]) assert b.get_full_squares_bitboard() == 1
def test_unblocked_blackqueenside_castle(board): """Tests classical queenside black castling move.""" b = board.with_state(u.squares_to_bitboard(['e8', 'a8'])) m = move.Move('e8', 'c8', move_type=enums.MoveType.QS_CASTLE, move_variant=enums.MoveVariant.BASIC) assert b.do_move(m) assert_samples_in(b, [u.squares_to_bitboard(['d8', 'c8'])])
def test_unentangled_pawn_capture(board): """Classical pawn capture.""" b = board.with_state(u.squares_to_bitboard(['a4', 'b3', 'c3'])) m = move.Move('b3', 'a4', move_type=enums.MoveType.PAWN_CAPTURE, move_variant=enums.MoveVariant.BASIC) assert b.do_move(m) assert_samples_in(b, [u.squares_to_bitboard(['a4', 'c3'])])
def test_classical_jump_move(board): """Tests a jump move in a classical position.""" b = board.with_state(u.squares_to_bitboard(['a1', 'c1'])) m = move.Move('a1', 'b1', move_type=enums.MoveType.JUMP, move_variant=enums.MoveVariant.BASIC) b.do_move(m) assert_samples_in(b, [u.squares_to_bitboard(['b1', 'c1'])])
def test_classical_ep2(board): """Fully classical en passant.""" b = board.with_state(u.squares_to_bitboard(['e4', 'd4'])) m = move.Move('e4', 'd3', move_type=enums.MoveType.PAWN_EP, move_variant=enums.MoveVariant.BASIC) b.do_move(m) assert_samples_in(b, [u.squares_to_bitboard(['d3'])])
def test_classical_jump_move(board): """Tests a jump move in a classical position.""" b = board(u.squares_to_bitboard(["a1", "c1"])) m = move.Move("a1", "b1", move_type=enums.MoveType.JUMP, move_variant=enums.MoveVariant.BASIC) b.do_move(m) assert_samples_in(b, [u.squares_to_bitboard(["b1", "c1"])])
def test_unblocked_white_castle(board): """Tests classical kingside white castling move.""" b = board.with_state(u.squares_to_bitboard(['e1', 'h1'])) m = move.Move('e1', 'g1', move_type=enums.MoveType.KS_CASTLE, move_variant=enums.MoveVariant.BASIC) assert b.do_move(m) assert_samples_in(b, [u.squares_to_bitboard(['f1', 'g1'])])
def test_from_string(): assert move.Move.from_string('a1b4:JUMP:BASIC') == move.Move( 'a1', 'b4', move_type=enums.MoveType.JUMP, move_variant=enums.MoveVariant.BASIC) assert move.Move.from_string('a1b4.m0:JUMP:BASIC') == move.Move( 'a1', 'b4', move_type=enums.MoveType.JUMP, move_variant=enums.MoveVariant.BASIC, measurement=0) assert move.Move.from_string('a1b4.m1:JUMP:BASIC') == move.Move( 'a1', 'b4', move_type=enums.MoveType.JUMP, move_variant=enums.MoveVariant.BASIC, measurement=1)
def test_unblocked_whitequeenside_castle(board): """Tests classical queenside white castling move.""" b = board(u.squares_to_bitboard(['e1', 'a1'])) m = move.Move('e1', 'c1', move_type=enums.MoveType.QS_CASTLE, move_variant=enums.MoveVariant.BASIC) assert b.do_move(m) assert_samples_in(b, [u.squares_to_bitboard(['d1', 'c1'])])
def test_unblocked_black_castle(board): """Tests classical kingside black castling move.""" b = board(u.squares_to_bitboard(['e8', 'h8'])) m = move.Move('e8', 'g8', move_type=enums.MoveType.KS_CASTLE, move_variant=enums.MoveVariant.BASIC) assert b.do_move(m) assert_samples_in(b, [u.squares_to_bitboard(['f8', 'g8'])])
def test_jump_with_successful_measurement_outcome(board): b = board(u.squares_to_bitboard(["b1", "c2"])) b.do_move( move.Move( "b1", "a3", target2="c3", move_type=enums.MoveType.SPLIT_JUMP, move_variant=enums.MoveVariant.BASIC, )) b.do_move( move.Move( "c2", "c3", move_type=enums.MoveType.JUMP, move_variant=enums.MoveVariant.EXCLUDED, measurement=1, )) assert_samples_in(b, [u.squares_to_bitboard(["c3", "a3"])])
def test_blocked_slide_capture_through(): success = 0 for trials in range(100): b = qb.CirqBoard(u.squares_to_bitboard(['a8', 'c6'])) b.do_move( move.Move('c6', 'b8', target2='d8', move_type=enums.MoveType.SPLIT_JUMP, move_variant=enums.MoveVariant.BASIC)) did_it_move = b.do_move( move.Move('a8', 'd8', move_type=enums.MoveType.SLIDE, move_variant=enums.MoveVariant.CAPTURE)) if did_it_move: success += 1 assert success > 25 assert success < 75
def test_simple_slide_move(board): """Tests a basic slide that is totally unblocked.""" b = board.with_state(u.squares_to_bitboard(['a1'])) b.do_move( move.Move('a1', 'd1', move_type=enums.MoveType.SLIDE, move_variant=enums.MoveVariant.BASIC)) samples = b.sample(10) assert all(sample == u.squares_to_bitboard(['d1']) for sample in samples)
def test_1block_ks_castle(board): """Kingside castling move blocked by 1 piece in superposition.""" b = board.with_state(u.squares_to_bitboard(['e1', 'f3', 'h1'])) b.do_move( move.Move('f3', 'f2', target2='f1', move_type=enums.MoveType.SPLIT_JUMP, move_variant=enums.MoveVariant.BASIC)) did_it_move = b.do_move( move.Move('e1', 'g1', move_type=enums.MoveType.KS_CASTLE, move_variant=enums.MoveVariant.BASIC)) if did_it_move: expected = u.squares_to_bitboard(['f1', 'f2', 'g1']) else: expected = u.squares_to_bitboard(['e1', 'f1', 'h1']) assert_samples_in(b, [expected])
def test_capture(board): """Splits piece from b1 to c1 and d1 then attempts a capture on a1.""" b = board.with_state(u.squares_to_bitboard(['a1', 'b1'])) b.do_move( move.Move('b1', 'c1', target2='d1', move_type=enums.MoveType.SPLIT_JUMP, move_variant=enums.MoveVariant.BASIC)) did_it_move = b.do_move( move.Move('c1', 'a1', move_type=enums.MoveType.JUMP, move_variant=enums.MoveVariant.CAPTURE)) if did_it_move: expected = u.squares_to_bitboard(['a1']) else: expected = u.squares_to_bitboard(['a1', 'd1']) assert_samples_in(b, [expected])
def test_classical_ep2(board): """Fully classical en passant.""" b = board(u.squares_to_bitboard(["e4", "d4"])) m = move.Move( "e4", "d3", move_type=enums.MoveType.PAWN_EP, move_variant=enums.MoveVariant.BASIC, ) b.do_move(m) assert_samples_in(b, [u.squares_to_bitboard(["d3"])])
def test_unentangled_pawn_capture(board): """Classical pawn capture.""" b = board(u.squares_to_bitboard(["a4", "b3", "c3"])) m = move.Move( "b3", "a4", move_type=enums.MoveType.PAWN_CAPTURE, move_variant=enums.MoveVariant.BASIC, ) assert b.do_move(m) assert_samples_in(b, [u.squares_to_bitboard(["a4", "c3"])])
def test_unblocked_white_castle(board): """Tests classical kingside white castling move.""" b = board(u.squares_to_bitboard(["e1", "h1"])) m = move.Move( "e1", "g1", move_type=enums.MoveType.KS_CASTLE, move_variant=enums.MoveVariant.BASIC, ) assert b.do_move(m) assert_samples_in(b, [u.squares_to_bitboard(["f1", "g1"])])
def test_unblocked_blackqueenside_castle(board): """Tests classical queenside black castling move.""" b = board(u.squares_to_bitboard(["e8", "a8"])) m = move.Move( "e8", "c8", move_type=enums.MoveType.QS_CASTLE, move_variant=enums.MoveVariant.BASIC, ) assert b.do_move(m) assert_samples_in(b, [u.squares_to_bitboard(["d8", "c8"])])
def test_caching_accumulations_same_repetition_cached(board): b = board.with_state(u.squares_to_bitboard(['a1', 'b1'])) b.do_move( move.Move('b1', 'c1', target2='d1', move_type=enums.MoveType.SPLIT_JUMP, move_variant=enums.MoveVariant.BASIC)) probs1 = b.get_probability_distribution(100) probs2 = b.get_probability_distribution(100) assert probs1 == probs2
def test_merge_move(board): """Splits piece on a1 to b1 and c1 and then merges back to a1.""" b = board(u.squares_to_bitboard(["a1"])) b.do_move( move.Move( "a1", "b1", target2="c1", move_type=enums.MoveType.SPLIT_JUMP, move_variant=enums.MoveVariant.BASIC, )) b.do_move( move.Move( "b1", "a1", source2="c1", move_type=enums.MoveType.MERGE_JUMP, move_variant=enums.MoveVariant.BASIC, )) assert_samples_in(b, [u.squares_to_bitboard(["a1"])]) assert b.get_full_squares_bitboard() == 1
def test_exclusion(board): """Splits piece b1 to c1 and d1 then tries a excluded move from a1 to c1.""" b = board.with_state(u.squares_to_bitboard(['a1', 'b1'])) b.do_move( move.Move('b1', 'c1', target2='d1', move_type=enums.MoveType.SPLIT_JUMP, move_variant=enums.MoveVariant.BASIC)) did_it_move = b.do_move( move.Move('a1', 'c1', move_type=enums.MoveType.JUMP, move_variant=enums.MoveVariant.EXCLUDED)) samples = b.sample(20) if did_it_move: expected = u.squares_to_bitboard(['c1', 'd1']) assert all(sample == expected for sample in samples) else: expected = u.squares_to_bitboard(['a1', 'c1']) assert all(sample == expected for sample in samples)
def test_simple_slide_move(board): """Tests a basic slide that is totally unblocked.""" b = board(u.squares_to_bitboard(["a1"])) b.do_move( move.Move( "a1", "d1", move_type=enums.MoveType.SLIDE, move_variant=enums.MoveVariant.BASIC, )) samples = b.sample(10) assert all(sample == u.squares_to_bitboard(["d1"]) for sample in samples)
def test_get_probability_distribution_split_jump_pre_cached(board): b = board(u.squares_to_bitboard(["a1", "b1"])) # Cache a split jump in advance. cache_key = CacheKey(enums.MoveType.SPLIT_JUMP, 100) b.cache_results(cache_key) m1 = move.Move("a1", "a2", move_type=enums.MoveType.JUMP, move_variant=enums.MoveVariant.BASIC) m2 = move.Move( "b1", "c1", target2="d1", move_type=enums.MoveType.SPLIT_JUMP, move_variant=enums.MoveVariant.BASIC, ) b.do_move(m1) probs = b.get_probability_distribution(100) b.do_move(m2) b.clear_debug_log() # Expected probability with the cache applied probs[square_to_bit("b1")] = 0 probs[square_to_bit("c1")] = b.cache[cache_key]["target"] probs[square_to_bit("d1")] = b.cache[cache_key]["target2"] # Get probability distribution should apply the cache without rerunning _generate_accumulations. probs2 = b.get_probability_distribution(100, use_cache=True) full_squares = b.get_full_squares_bitboard(100, use_cache=True) empty_squares = b.get_empty_squares_bitboard(100, use_cache=True) assert probs == probs2 # Check that the second run and getting full and empty bitboards did not trigger any new logs. assert len(b.debug_log) == 0 # Check bitboard updated correctly assert not nth_bit_of(square_to_bit("b1"), full_squares) assert not nth_bit_of(square_to_bit("c1"), full_squares) assert not nth_bit_of(square_to_bit("d1"), full_squares) assert nth_bit_of(square_to_bit("b1"), empty_squares)
def test_entangled_qs_castle(board): """Queenside castling move with b-square blocked by superposition. This should entangle the castling rook/king with the piece. """ b = board.with_state(u.squares_to_bitboard(['e1', 'b3', 'a1'])) b.do_move( move.Move('b3', 'b2', target2='b1', move_type=enums.MoveType.SPLIT_SLIDE, move_variant=enums.MoveVariant.BASIC)) assert b.do_move( move.Move('e1', 'c1', move_type=enums.MoveType.QS_CASTLE, move_variant=enums.MoveVariant.BASIC)) possibilities = [ u.squares_to_bitboard(['a1', 'b1', 'e1']), u.squares_to_bitboard(['c1', 'b2', 'd1']) ] assert_samples_in(b, possibilities)
def test_blocked_slide_move(board): """Tests a basic slide that is blocked. Slide from a1 to d1 is blocked by a piece on b1. """ b = board.with_state(u.squares_to_bitboard(['a1', 'b1'])) m = move.Move('a1', 'd1', move_type=enums.MoveType.SLIDE, move_variant=enums.MoveVariant.BASIC) b.do_move(m) samples = b.sample(10) expected = u.squares_to_bitboard(['a1', 'b1']) assert all(sample == expected for sample in samples)
def test_blocked_slide_blocked(board): """Blocked slide with 0% success Position: re5, rf5. Moves: rf5d5 """ b = board.with_state(u.squares_to_bitboard(['e5', 'f5'])) m = move.Move('f5', 'd5', move_type=enums.MoveType.SLIDE, move_variant=enums.MoveVariant.BASIC) b.do_move(m) samples = b.sample(100) expected = u.squares_to_bitboard(['e5', 'f5']) assert all(sample == expected for sample in samples)