I'm making a function that returns True if a move is pseudo legal. The problem is that, in order to find out if the pawn is at it's starting position, i have to loop all the squares in this row and see if the square the pawn is at, is in that range. Is there a better way to do this ? Can i somehow calculate the row number at which the pawn is on or something ?
# Pawn.
if piece == PAWN:
if not from_piece & 8: # White pawn.
if start_point < end_point: # Can't move backwards.
return False
elif diff == 32 and start_point in range(96, 104) and not board[start_point - 16] and not board[end_point]:
pass # Valid case, skip next elif statement. Can move 2 spaces at the starting position.
elif diff != 16:
return False
else: # Black pawn.
if start_point > end_point: # Can't move backwards.
return False
elif diff == 32 and start_point in range(16, 24) and not board[end_point + 16] and not board[end_point]:
pass # Valid case, skip next elif statement. Can move 2 spaces at the starting position.
elif diff != 16:
return False
if diff == 16 and board[end_point]: # Can't move ahead one square if there's already a piece.
return False
elif (diff == 15 or diff == 17) and board[end_point]: # Can't move one step diagonal when there's no enemy piece.
return False
return True
I made the program so that white pawn has the value 1 and black pawn has the value 9. Empty square is represented by 0.
Thank you very much.
You might want to rethink your model, it looks a bit unnecessarily complicated to me. Instead of looping however, you could to integer division:
(...)
elif diff == 32 and start_point / 16 == 6 and not board[end_point + 16] and not board[end_point]:
(...)
elif diff == 32 and start_point / 16 == 1 and not board[end_point + 16] and not board[end_point]:
(...)
Personally, I think your code looks like a typical C approach to representing data, done in Python. There's nothing wrong with that, but I suspect most pythonistas would do something like defining a board
class or providing a few utility methods:
board = [...]
def xy288(field):
"""Converts from (col, row) to [0...127]"""
return field[0] * 16 + field[1]
def is_white(field):
board[xy288(field)] <=8
def row(field):
return field[0]
def col(field):
return field[1]
def is_pawn(field):
return board[xy288(field)] % 8 == PAWN
def is_empty(field):
return board[xy288(field)] == 0
def valid_move(start, end):
# use tuples for encoding start and end, ie. start = (4,7)
if is_pawn(start):
direction = 1 if is_white(start) else -1
if col(start) == col(end) and \
row(start) == row(end) + 2*direction and \
is_empty(end) and \
is_empty((row(start) + direction, col(start)):
pass
The idea is to make the code semantic and self-contained, i.e. I don't have to look up how the board is defined to understand how valid_move works. Please beware that variables with global scopes in Python can be very tricky - ie. in this example it works, but if you change or assign a variable in a function, it will automatically assume local scope.