我正在为国际象棋编程。尝试计算主教的所有可能对角线移动时遇到问题。我认为问题出在函数内部:reverse_bits()。我认为我在程序中无法正确处理负二进制数,但是我可能错了。
# ranks
rank1 = int("0000000000000000000000000000000000000000000000000000000011111111", 2)
rank2 = int("0000000000000000000000000000000000000000000000001111111100000000", 2)
rank3 = int("0000000000000000000000000000000000000000111111110000000000000000", 2)
rank4 = int("0000000000000000000000000000000011111111000000000000000000000000", 2)
rank5 = int("0000000000000000000000001111111100000000000000000000000000000000", 2)
rank6 = int("0000000000000000111111110000000000000000000000000000000000000000", 2)
rank7 = int("0000000011111111000000000000000000000000000000000000000000000000", 2)
rank8 = int("1111111100000000000000000000000000000000000000000000000000000000", 2)
# files
filea = int("1000000010000000100000001000000010000000100000001000000010000000", 2)
fileb = int("0100000001000000010000000100000001000000010000000100000001000000", 2)
filec = int("0010000000100000001000000010000000100000001000000010000000100000", 2)
filed = int("0001000000010000000100000001000000010000000100000001000000010000", 2)
filee = int("0000100000001000000010000000100000001000000010000000100000001000", 2)
filef = int("0000010000000100000001000000010000000100000001000000010000000100", 2)
fileg = int("0000001000000010000000100000001000000010000000100000001000000010", 2)
fileh = int("0000000100000001000000010000000100000001000000010000000100000001", 2)
# diagonals
d0 = int("0000000100000000000000000000000000000000000000000000000000000000", 2)
d1 = int("0000001000000001000000000000000000000000000000000000000000000000", 2)
d2 = int("0000010000000010000000010000000000000000000000000000000000000000", 2)
d3 = int("0000100000000100000000100000000100000000000000000000000000000000", 2)
d4 = int("0001000000001000000001000000001000000001000000000000000000000000", 2)
d5 = int("0010000000010000000010000000010000000010000000010000000000000000", 2)
d6 = int("0100000000100000000100000000100000000100000000100000000100000000", 2)
d7 = int("1000000001000000001000000001000000001000000001000000001000000001", 2)
d8 = int("0000000010000000010000000010000000010000000010000000010000000010", 2)
d9 = int("0000000000000000100000000100000000100000000100000000100000000100", 2)
d10 = int("0000000000000000000000001000000001000000001000000001000000001000", 2)
d11 = int("0000000000000000000000000000000010000000010000000010000000010000", 2)
d12 = int("0000000000000000000000000000000000000000100000000100000000100000", 2)
d13 = int("0000000000000000000000000000000000000000000000001000000001000000", 2)
d14 = int("0000000000000000000000000000000000000000000000000000000010000000", 2)
# anti-diagonal
ad0 = int("1000000000000000000000000000000000000000000000000000000000000000", 2)
ad1 = int("0100000010000000000000000000000000000000000000000000000000000000", 2)
ad2 = int("0010000001000000100000000000000000000000000000000000000000000000", 2)
ad3 = int("0001000000100000010000001000000000000000000000000000000000000000", 2)
ad4 = int("0000100000010000001000000100000010000000000000000000000000000000", 2)
ad5 = int("0000010000001000000100000010000001000000100000000000000000000000", 2)
ad6 = int("0000001000000100000010000001000000100000010000001000000000000000", 2)
ad7 = int("0000000100000010000001000000100000010000001000000100000010000000", 2)
ad8 = int("0000000000000001000000100000010000001000000100000010000001000000", 2)
ad9 = int("0000000000000000000000010000001000000100000010000001000000100000", 2)
ad10 = int("0000000000000000000000000000000100000010000001000000100000010000", 2)
ad11 = int("0000000000000000000000000000000000000001000000100000010000001000", 2)
ad12 = int("0000000000000000000000000000000000000000000000010000001000000100", 2)
ad13 = int("0000000000000000000000000000000000000000000000000000000100000010", 2)
ad14 = int("0000000000000000000000000000000000000000000000000000000000000001", 2)
# masks
rankmask = [rank1, rank2, rank3, rank4, rank5, rank6, rank7, rank8]
filemask = [filea, fileb, filec, filed, filee, filef, fileg, fileh]
diagonal = [d14, d13, d12, d11, d10, d9, d8, d7, d6, d5, d4, d3, d2, d1, d0]
antidiagonal = [ad14, ad13, ad12, ad11, ad10, ad9, ad8, ad7, ad6, ad5, ad4, ad3, ad2, ad1, ad0]
last_black_pm = [53, 45]
# bitboards
wp = 0
wr = 0
wn = 0
wb = 0
wq = 0
wk = 0
bp = 0
br = 0
bn = 0
bb = 0
bq = 0
bk = 0
def print_bitboard(bitboard):
board = '{:064b}'.format(bitboard)
for i in range(8):
print(board[8*i+0] + " " + board[8*i+1] + " " + board[8*i+2] + " " + board[8*i+3] + " " + board[8*i+4] + " " + board[8*i+5] + " " + board[8*i+6] + " " + board[8*i+7])
def print_chess_board(bitboard):
board = bitboard
for i in range(8):
print(board[8*i+0] + " " + board[8*i+1] + " " + board[8*i+2] + " " + board[8*i+3] + " " + board[8*i+4] + " " + board[8*i+5] + " " + board[8*i+6] + " " + board[8*i+7])
def integer_to_bitboard(integer):
bitboard = '{:064b}'.format(integer)
return bitboard
def create_starting_bitboards():
global last_black_pm, wp, wr, wn, wb, wq, wk, bp, bn, bb, bq, bk, br
bitboard_all_pieces = "rnbqkbnrpppppppp0000000000B000000000000000000000PPPPPPPPRNBQKBNR"
print_chess_board(bitboard_all_pieces)
for i in range(64):
if bitboard_all_pieces[i] == "P":
wp += 2**(63-i)
if bitboard_all_pieces[i] == "R":
wr += 2**(63-i)
if bitboard_all_pieces[i] == "N":
wn += 2**(63-i)
if bitboard_all_pieces[i] == "B":
wb += 2**(63-i)
if bitboard_all_pieces[i] == "Q":
wq += 2**(63-i)
if bitboard_all_pieces[i] == "K":
wk += 2**(63-i)
if bitboard_all_pieces[i] == "p":
bp += 2**(63-i)
if bitboard_all_pieces[i] == "r":
br += 2**(63-i)
if bitboard_all_pieces[i] == "n":
bn += 2**(63-i)
if bitboard_all_pieces[i] == "b":
bb += 2**(63-i)
if bitboard_all_pieces[i] == "q":
bq += 2**(63-i)
if bitboard_all_pieces[i] == "k":
bk += 2**(63-i)
occupied = wp | wr | wn | wb | wq | wk | bp | br | bn | bb | bq | bk
# g_white_pawn_moves(wp, wr, wn, wb, wq, wk, bp, br, bn, bb, bq, bk)
g_white_bishop_moves(wp, wr, wn, wb, wq, wk, occupied)
def reverse_bits(num):
num = '{:064b}'.format(num)[::-1]
if num[-1] == "-":
num = num[:-1]
return int(num, 2)
def vertical_horizontal_moves(s, occupied):
global rankmask, filemask
ranknum = int(s/8)
filenum = 7 - int(s % 8)
slider = 1 << s
horizontal = ((occupied - 2*slider) ^ reverse_bits(reverse_bits(occupied)-2*reverse_bits(slider))) & rankmask[ranknum]
vertical = (((occupied & filemask[filenum]) - 2 * slider) ^ reverse_bits(reverse_bits(occupied & filemask[filenum]) - 2 * reverse_bits(slider))) & filemask[filenum]
print_bitboard(vertical ^ horizontal)
return vertical ^ horizontal
def diagonal_antidiagonal_moves(s, occupied):
global diagonal, antidiagonal
diagonalnum = 7 - int(s % 8) + int(s/8)
antidiagonalnum = int(s / 8) + int(s % 8)
slider = 1 << s
diag1 = (((occupied & diagonal[diagonalnum]) - 2 * slider) ^ reverse_bits(reverse_bits(occupied & diagonal[diagonalnum]) - 2 * reverse_bits(slider))) & diagonal[diagonalnum]
diag2 = (((occupied & antidiagonal[antidiagonalnum]) - 2 * slider) ^ reverse_bits(reverse_bits(occupied & antidiagonal[antidiagonalnum]) - 2 * reverse_bits(slider))) & antidiagonal[antidiagonalnum]
return diag1 ^ diag2
def g_white_bishop_moves(wp, wr, wn, wb, wq, wk, occupied):
white_pieces = wp | wr | wn | wb | wq | wk
moves_list = []
for i in range(64):
if (wb >> i) & 1 == 1:
moves = diagonal_antidiagonal_moves(i, occupied) & ~white_pieces
for j in range(64):
if (moves >> j) & 1 == 1:
moves_list.extend((i, j))
print("")
print_bitboard(moves)
def g_white_pawn_moves(wp, wr, wn, wb, wq, wk, bp, br, bn, bb, bq, bk):
global rank8, rank4, rank5, fileh, filea, filemask
empty = ~(wp | wr | wn | wb| wq | wk | bp | br | bn | bb | bq | bk)
black = bp | br | bn | bb | bq
moves_list = []
# pawn 1 forward
moves = (wp << 8) & empty & ~ rank8
for i in range(64):
if (moves >> i) & 1 == 1:
moves_list.extend((i-8, i, ""))
# pawn 2 forward
moves = (wp << 16) & empty & (empty << 8) & rank4
for i in range(64):
if (moves >> i) & 1 == 1:
moves_list.extend((i-16, i, ""))
# pawn left capture
moves = (wp << 9) & black & ~ rank8 & ~ fileh
for i in range(64):
if (moves >> i) & 1 == 1:
moves_list.extend((i - 9, i, ""))
# pawn right capture
moves = (wp << 7) & black & ~ rank8 & ~ filea
for i in range(64):
if (moves >> i) & 1 == 1:
moves_list.extend((i - 9, i, ""))
# en passant
if last_black_pm[0] - last_black_pm[1] == 16:
filenum = 7 - int(last_black_pm[1] % 8)
# en passant left
moves = (wp << 1) & black & rank5 & ~fileh & filemask[filenum] # pawn_capture_right
for i in range(64):
if (moves >> i) & 1 == 1:
moves_list.extend((i - 1, i + 8, "E")) # store piece field/ and move field 0-63
# en passant right
moves = (wp >> 1) & black & rank5 & ~filea & filemask[filenum] # pawn_capture_left
for i in range(64):
if (moves >> i) & 1 == 1:
moves_list.extend((i + 1, i + 8, "E")) # store piece field/ and move field 0-63
# pawn promotion
# pawn 1 forward
moves = (wp << 8) & empty & rank8
for i in range(64):
if (moves >> i) & 1 == 1:
moves_list.extend((i - 8, i, "P"))
# pawn left capture
moves = (wp << 9) & black & rank8 & ~ fileh
for i in range(64):
if (moves >> i) & 1 == 1:
moves_list.extend((i - 9, i, "P"))
# pawn right capture
moves = (wp << 7) & black & rank8 & ~ filea
for i in range(64):
if (moves >> i) & 1 == 1:
moves_list.extend((i - 9, i, "P"))
print(moves_list)
create_starting_bitboards()
例如,在这种情况下,它会正确计算所有可能的主教移动:
r n b q k b n r
p p p p p p p p
0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0
0 0 B 0 0 0 0 0
0 0 0 0 0 0 0 0
P P P P P P P P
R N B Q K B N R
0 0 0 0 0 0 0 0
0 0 0 0 0 1 0 0
1 0 0 0 1 0 0 0
0 1 0 1 0 0 0 0
0 0 0 0 0 0 0 0
0 1 0 1 0 0 0 0
0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0
但是当我将主教移动到另一个广场时,会发生这种情况:
r n b q k b n r
p p p p p p p p
0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0
0 B 0 0 0 0 0 0
0 0 0 0 0 0 0 0
P P P P P P P P
R N B Q K B N R
0 0 0 0 0 1 0 0
0 0 0 0 1 0 0 0
0 0 0 0 0 0 0 0
1 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0
0 0 1 0 0 0 0 0
0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0
当我检查函数中对角线(对角线/反对角线的移动)时,发现对角线/反对角线的所有代码时,我开始打印出不同的位板。我注意到某些位板在其上带有“-”号。例如,我采取了以下方法:reverse_bits(已占用和antidiagonal [antidiagonalnum])-2 *来自* p的reverse_bits(slider)
diag2 = (((occupied & antidiagonal[antidiagonalnum]) - 2 * slider) ^ reverse_bits(reverse_bits(occupied & antidiagonal[antidiagonalnum]) - 2 * reverse_bits(slider))) & antidiagonal[antidiagonalnum]
并打印出位板。结果是:
- 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 1
1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1
1 1 1 0 1 1 1 1
1 1 1 0 0 0 0 0
这就是为什么我认为当我在reverse_bits函数中对负整数进行反向运算时肯定有问题。
有趣的是,例如用于查找所有可能的后叉移动的功能vertical_horizontal_moves()似乎工作正常。
我希望有人能给我一个思路,以了解我的代码到底出了什么问题。
答案 0 :(得分:0)
reverse_bits
is indeed wrong, as you suspect. This is easy to prove with an example: reverse_bits(-1)
returns the value 0x4000000000000000.
The current implementation of reverse_bits
already works for non-negative numbers, so it can be repaired by masking the input to turn it non-negative while retaining all the bits relevant in this context (the lowest 64):
def reverse_bits(num):
num = num & 0xffffffffffffffff
num = '{:064b}'.format(num)[::-1]
return int(num, 2)