Reputation: 23
So I have a chess board represented as an array of size 64 with top-left square being 0 and bottom-right square being 63. I have this function which gives all possible moves of King.
current_pos = i
arr = np.array([i-9, i-8, i-7, i-1, i+1, i+7, i+8, 1+9])
return arr
.
.
.
if selected position is in arr:
move king
Where i is the number of the square on which king currently is.
This works if the king is not on edges of the chessboard.
BUT if king is on the bottom-right square, that is number 63, the function gives bottom-left square that is number 56 as a valid position for a king to move.
Is there any efficient way to know that the king is going to the other edge and is not a valid move?
I'm having same problems with almost all my pieces where the function will allow piece to go on the other side of board but i figured king's movement was the simplest to ask.
Upvotes: 0
Views: 501
Reputation: 1856
A 1D list is way faster than a 2D 8x8 list so I like that you are using this approach.
The way this is handled is to use a 10x12 board where you have an extra 2 rows on bottom and top, and an extra column on the left and right:
Then in your generate move function you simple check if the square you are looking at is within the board. If it is not, you skip to the next square in your loop.
Please read more about it on https://www.chessprogramming.org/10x12_Board. It is also a great site for information about chess programming in general.
Upvotes: 1
Reputation: 5024
Here is one approach using table lookup.
piece_offsets = {
'n': [-17, -15, -10, -6, 6, 10, 15, 17],
'b': [ -9, -7, 9, 7],
'r': [ -8, -1, 8, 1],
'q': [ -9, -8, -7, -1, 9, 8, 7, 1],
'k': [ -9, -8, -7, -1, 9, 8, 7, 1]
}
sqdist = [[0 for x in range(64)] for y in range(64)]
pseudo_legal = {
'n': [[] for y in range(64)],
'b': [[] for y in range(64)],
'r': [[] for y in range(64)],
'q': [[] for y in range(64)],
'k': [[] for y in range(64)],
}
def distance(sq1, sq2):
file1 = sq1 & 7
file2 = sq2 & 7
rank1 = sq1 >> 3
rank2 = sq2 >> 3
rank_distance = abs(rank2 - rank1)
file_distance = abs(file2 - file1)
return max(rank_distance, file_distance)
def print_board():
for i in range(64):
print(f'{i:02d} ', end='')
if (i+1)%8 == 0:
print()
def on_board(s):
return s >= 0 and s < 64
def init_board():
for sq1 in range(64):
for sq2 in range(64):
sqdist[sq1][sq2] = distance(sq1, sq2)
for pt in ['n', 'b', 'r', 'q', 'k']:
for s in range(64):
for offset in piece_offsets[pt]:
to = s + offset
if pt in ['k', 'n']:
if on_board(to) and sqdist[s][to] < 4:
pseudo_legal[pt][s].append(to)
else: # sliders
s1 = s
while True:
to1 = s1 + offset
if on_board(to1) and sqdist[s1][to1] < 4:
pseudo_legal[pt][s].append(to1)
s1 = to1
else:
break
def main():
init_board() # build sqdist and pseudo_legal_to tables
print_board()
print()
for pt in ['n', 'b', 'r', 'q', 'k']:
for s in [0, 63, 36]:
print(f'pt: {pt}, from: {s}: to: {pseudo_legal[pt][s]}')
print()
# pseudo_legal_sq = pseudo_legal['b'][61]
# print(pseudo_legal_sq)
main()
00 01 02 03 04 05 06 07
08 09 10 11 12 13 14 15
16 17 18 19 20 21 22 23
24 25 26 27 28 29 30 31
32 33 34 35 36 37 38 39
40 41 42 43 44 45 46 47
48 49 50 51 52 53 54 55
56 57 58 59 60 61 62 63
pt: n, from: 0: to: [10, 17]
pt: n, from: 63: to: [46, 53]
pt: n, from: 36: to: [19, 21, 26, 30, 42, 46, 51, 53]
pt: b, from: 0: to: [9, 18, 27, 36, 45, 54, 63]
pt: b, from: 63: to: [54, 45, 36, 27, 18, 9, 0]
pt: b, from: 36: to: [27, 18, 9, 0, 29, 22, 15, 45, 54, 63, 43, 50, 57]
pt: r, from: 0: to: [8, 16, 24, 32, 40, 48, 56, 1, 2, 3, 4, 5, 6, 7]
pt: r, from: 63: to: [55, 47, 39, 31, 23, 15, 7, 62, 61, 60, 59, 58, 57, 56]
pt: r, from: 36: to: [28, 20, 12, 4, 35, 34, 33, 32, 44, 52, 60, 37, 38, 39]
pt: q, from: 0: to: [9, 18, 27, 36, 45, 54, 63, 8, 16, 24, 32, 40, 48, 56, 1, 2, 3, 4, 5, 6, 7]
pt: q, from: 63: to: [54, 45, 36, 27, 18, 9, 0, 55, 47, 39, 31, 23, 15, 7, 62, 61, 60, 59, 58, 57, 56]
pt: q, from: 36: to: [27, 18, 9, 0, 28, 20, 12, 4, 29, 22, 15, 35, 34, 33, 32, 45, 54, 63, 44, 52, 60, 43, 50, 57, 37, 38, 39]
pt: k, from: 0: to: [9, 8, 1]
pt: k, from: 63: to: [54, 55, 62]
pt: k, from: 36: to: [27, 28, 29, 35, 45, 44, 43, 37]
Upvotes: 1