Search code examples
pythonpython-2.7chess

How would I place validations on chess pieces in python using ascii


I started to work on a command line chess for python. I have managed to create a table like so:

def setup_grid():
    grid = [[' ' for i in range(gridsize)] for i in range(gridsize)]    # Creates a grid of 0 of the size set by user
    return(grid)

# Displaying the grid to the user
def show_grid(grid):
    gridsize = len(grid)
    horizontal = '   '+4*gridsize*'-'+'-'           # This prints the horizontal borders of the grid


    #####################################################
    toplabel = '     '                                  #
    for i in string.ascii_lowercase[:gridsize]:         # This creates the letters according 
        toplabel = toplabel+i+'   '                     # to how big the grid is. This prints the top letters
    print '\n'+toplabel+'\n'+horizontal                 #
    #####################################################


    #########################################
    for idx,i in enumerate(grid):           #
        row = '{0:2} |'.format(idx+1)       #
        for j in i:                         # This creates the numbers
            row = row+' '+j+' |'            # for the left side of the grid
        print row+'\n'+horizontal           #
    print ''                                #
    #########################################

def play_game():
    gridsize = 8
    currgrid = [[' ' for i in range(gridsize)] for i in range(gridsize)]
    show_grid(currgrid)
    grid = []

play_game()

Now I am trying to be able to define pieces like wq for the white queen. The way the player will choose which piece to move is by choosing co-ordinates on the grid and moving the piece y inputting new co-ordinates. What I do not know is how to make sure the pieces move as required. I don not know how I would validate their movement.


Solution

  • Move validation is somewhat complex, however, below is a possibility for how to validate the moves of the queen. First, you may want to move your game layout to a class for simpler board and piece access. Then, create a method to move a piece. The method can be wrapped by a decorator that will validate the coordinates passed to the method:

    def validate_move(f):
      def wrapper(cls, name, x, y):
        methods = {'q':cls.__class__.queen_moves} #build dictionary of move accumulators
        full_moves = list(methods[name[:-1]](getattr(cls, 'board'), color = name[-1]))
        if [x, y] not in full_moves:
          print("invalid move")
        else:
          f(cls, x, y)
      return wrapper
    
    class Chess:
      pieces = [['r', 'kn', 'b', 'k', 'q', 'b', 'kn', 'r'], ['p']*8]
      def __init__(self):
        self.board = [[i+'b' for i in b] for b in Chess.pieces]+([['-']*8]*8)+[[i+'w' for i in b] for b in Chess.pieces]
      @validate_move
      def move_piece(_name, x, y):
        a1, b1 = [(i, b) for i in range(8) for b in range(8) if self.board[i][b] == _name]
        self.board[x][y] = _name
        self.board[a1][b1] = '-'        
      @staticmethod
      def queen_moves(board, color = 'w'):
         c1, c2 = [(i, b) for i in range(8) for b in range(8) if board[i][b] == 'q'+color]
         _c2, _c1 = c2, c1
         while c2 < 8: #check vertically
           c2 += 1
           if board[c1][c2] != '-':
             c2 = _c2
             break
           yield [c1, c2]
         while c2 >= 0: #check vertically
            c2 -= 1
            if board[c1][c2] != '-':
               c2 = _c2
               break
            yield [c1, c2]
         while c1 < 8: #check horizontally
           c1 += 1
           if board[c1][c2] != '-':
               c1 = _c1
               break
            yield [c1, c2]
         while c1 >= 0: #check horizontally
           c1 -= 1
           if board[c1][c2] != '-':
               c1 = _c1
               break
            yield [c1, c2]
    

    Thus, there are two things left for you to do:

    1. Create a full listing of staticmethods to get the full moves of all pieces on the board.

    2. build up methods dictionary in wrapper to store the move finder function objects.