Akshar Patel
Akshar Patel

Reputation: 23

How do I know all valid positions for a King to move on chess board without going to the opposite side

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

Answers (2)

eligolf
eligolf

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:

enter image description here

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

ferdy
ferdy

Reputation: 5024

Here is one approach using table lookup.

Code

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()

Output

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

Related Questions