HiveBrain v1.2.0
Get Started
← Back to all entries
patternpythonMinor

Finding all legal bishop moves

Submitted by: @import:stackexchange-codereview··
0
Viewed 0 times
movesbishopalllegalfinding

Problem

I am trying to create a two player Chess game. To do this I want to generate a list of legal moves. I am having trouble with the brevity of the code to generate the moves for the rooks and bishops.

The code I have pasted below works (i.e. shows legal bishop moves) but there is a lot of repetition, which is not ideal. To make this work for both black and white bishops I would need to add even more repetitive lines.

Is there a better way to do this? I do not want to use any 'chess modules' as this is a learning exercise for me; as you can tell, I am a beginner.

```
import numpy as np

# chess board is a numpy array
# white pieces are capitalised, black pieces are not
board = np.zeros((8,8),dtype=str)

# example piece positions
white_bishop = (4,5)
white_pawn = (6,7)
black_knight = (0,1)
board[white_bishop] = 'B'
board[white_pawn] = 'P'
board[black_knight] = 'n'

def bishop(insquare):
'''
Gets all legal moves for bishop on insquare
output is a list (outsquares) of indices of possible squares
'''
out_squares = []
y,x = insquare

y1 = y-1 # these are steps in one of the four directions bishops can go
x1 = x-1
while (x1 > -1) and (y1 > -1): # edge of the board
if not board[(y1,x1)].isupper(): # if not a white piece...
out_squares.append((y1,x1)) # square is legal
if board[(y1,x1)].islower(): # if black piece...
y1 = -1 # look no further in this direction
else: # if white piece...
y1 = -1 # look no further in this direction
y1 -= 1 # check next square
x1 -= 1

# check all other directions
y1 = y+1
x1 = x+1
while (x1 -1) and (y1 -1):
if not board[(y1,x1)].isupper():
out_squares.append((y1,x1))
if board[(y1,x1)].islower():
y1 = -1
else:
y1 = -1
y1 = y1 - 1
x1 = x1 + 1
return out_squares

# Get all legal moves for the white bishop
print bishop((4,5))

Solution

When you find yourself having a lot of duplicate code, you should factor out the commonalities. In this case, we have four separate directions we need to consider. So let's write one function that considers one direction:

def append(dx, dy):
    for i in itertools.count(start=1):
        newx = x + dx*i
        newy = y + dy*i
        sq = (newy, newx)

        if 0 <= newx < 8 and 0 <= newy < 8:
            if not board[sq].isupper():
                out_squares.append(sq)
                if board[sq].islower():
                    break
            else:
                break
        else:
            break


And then just call it 4 times:

for dx in (-1, 1):
    for dy in (-1, 1):
        append(dx, dy)


Full solution:

def bishop(insquare):
    ''' 
    Gets all legal moves for bishop on insquare
    output is a list (outsquares) of indices of possible squares
    '''
    out_squares = []
    y,x = insquare

    def append(dx, dy):
        for i in itertools.count(start=1):
            newx = x + dx*i
            newy = y + dy*i

            if 0 <= newx < 8 and 0 <= newy < 8:
                sq = (newy, newx)
                if not board[sq].isupper():
                    out_squares.append(sq)
                    if board[sq].islower():
                        break
                else:
                    break
            else:
                break

    for dx in (-1, 1):
        for dy in (-1, 1):
            append(dx, dy) 

    return out_squares

Code Snippets

def append(dx, dy):
    for i in itertools.count(start=1):
        newx = x + dx*i
        newy = y + dy*i
        sq = (newy, newx)

        if 0 <= newx < 8 and 0 <= newy < 8:
            if not board[sq].isupper():
                out_squares.append(sq)
                if board[sq].islower():
                    break
            else:
                break
        else:
            break
for dx in (-1, 1):
    for dy in (-1, 1):
        append(dx, dy)
def bishop(insquare):
    ''' 
    Gets all legal moves for bishop on insquare
    output is a list (outsquares) of indices of possible squares
    '''
    out_squares = []
    y,x = insquare

    def append(dx, dy):
        for i in itertools.count(start=1):
            newx = x + dx*i
            newy = y + dy*i

            if 0 <= newx < 8 and 0 <= newy < 8:
                sq = (newy, newx)
                if not board[sq].isupper():
                    out_squares.append(sq)
                    if board[sq].islower():
                        break
                else:
                    break
            else:
                break

    for dx in (-1, 1):
        for dy in (-1, 1):
            append(dx, dy) 

    return out_squares

Context

StackExchange Code Review Q#105273, answer score: 2

Revisions (0)

No revisions yet.