Search code examples
chess

How to determine valid chess moves?


I am trying to understand the algorithms behind determining valid moves for each chess piece. The specific issue I am having is determining when a piece cannot move past a certain point because it is being blocked by a piece of its own colour or is able to take a piece of the opposite colour but cannot move past that point.

The simple algorithms I have for each piece are:

Valid King move, if the piece moves from (X1, Y1) to (X2, Y2), the move is valid if and only if |X2-X1|<=1 and |Y2-Y1|<=1.

Valid Bishop move, if the piece moves from (X1, Y1) to (X2, Y2), the move is valid if and only if |X2-X1|=|Y2-Y1|.

Valid Rook move, if the piece moves from (X1, Y1) to (X2, Y2), the move is valid if and only if X2=X1 or Y2=Y1.

Valid Queen move, a queen's move is valid if it is either a valid bishop or rook move.

Valid Knight move, if the piece moves from (X1, Y1) to (X2, Y2), the move is valid if and only if (|X2-X1|=1 and |Y2-Y1|=2) or (|X2-X1|=2 and |Y2-Y1|=1).

Valid Pawn move, if the piece moves from (X1, Y1) to (X2, Y2), the move is valid if and only if X2=X1 and Y2-Y1=1 (only for a white pawn).

Any advice would be appreciated.


Solution

  • You need to take the board state into account for that. I think the common way to do it would be checking if each cell on the path is empty or not.

        public enum PieceColor { Black, White }
        public interface IBoard
        {
            bool IsEmpty(int x, int y);
            PieceColor GetPieceColor(int x, int y);
        }
    
        IBoard board;
    
        bool BishopCanMove(PieceColor bishopColor, int fromX, int fromY, int toX, int toY)
        {
            int pathLength = Mathf.Abs(toX - fromX);
            if (pathLength != Mathf.Abs(toY - fromY)) return false; // Not diagonal
            // Also validate if the coordinates are in the 0-7 range
    
            // Check all cells before the target
            for (int i = 1; i < pathLength; i++)
            {
                int x = fromX + i;
                int y = fromY + i;
    
                if(board.IsEmpty(x, y)) continue; // No obstacles here: keep going
                else return false; // Obstacle found before reaching target: the move is invalid
            }
    
            // Check target cell
            if (board.IsEmpty(toX, toY)) return true; // No piece: move is valid
    
            // There's a piece here: the move is valid only if we can capture
            return board.GetPieceColor(toX, toY) == bishopColor;
        }
    

    The IBoard interface is there just to show the point. You should have a board state exposing those informations in some way.