Search code examples
pythonchess

Row number in 0x88 chess board representation.


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.


Solution

  • 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]:
        (...)
    

    Edit (response to comment):

    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.