patternpythonMinor
Finding all legal bishop moves
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))
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:
And then just call it 4 times:
Full solution:
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:
breakAnd 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_squaresCode 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:
breakfor 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_squaresContext
StackExchange Code Review Q#105273, answer score: 2
Revisions (0)
No revisions yet.