DEV Community

Cover image for Chess Engine in C #6: Attacked Squares
Victor Chigbo
Victor Chigbo

Posted on

Chess Engine in C #6: Attacked Squares

In the last post, I wrote about assertions. Today, I will talk about how the engine detects attacked squares.

An attacked square is a square that a piece can move to and capture a piece, whether a piece is on that square or not. In military terms, it is the attack radius of a piece. Each piece has a way of moving around the chess board, and is determines whether a square is attacked, or not.

Examples of piece movements are as seen below:

Knight Moves

Knight Moves

 
 

Queen Moves

Queen Moves

 
 

Rook Moves

Rook Moves

 

Square Attacked By

Square Attacked By determines whether a square is being attacked by an opposing piece. First of all, we need to determine the movement of each piece on the board. Let's look at the 12*10 mailbox:

The 12*10 mailbox

The 12*10 mailbox

 

Using square 55 as the reference square, if a black knight wants to move, it will land at squares 34, 36, 43, 47, 63, 67, 74, & 76, and if a white piece is on any of these squares, the square is attacked and the piece is captured by the black knight. In order to repeat this when the piece is in another square, we store the number of (consecutive) squares it is going to land in arrays for each of the pieces.

// attack.c
const int KnightDirection[8] = {-8, -19, -21, -12, 8, 19, 21, 12};
const int RookDirection[4] = {-1, -10, 1, 10};
const int BishopDirection[4] = {-11, -9, 11, 9};
const int KingDirection[8] = {-1, -10, 1, 10, -11, -9, 11, 9};
Enter fullscreen mode Exit fullscreen mode

 

Next is the SqAttacked function:

int SqAttacked(const int sq, const int side, const S_BOARD *pos) {
    int piece, index, temp_sq, dir;

    // Check for pawns
    if (side == WHITE) {
        if (pos->pieces[sq - 11] == wP || pos->pieces[sq - 9] == wP) {
            return TRUE;
        }
    } else {
        if (pos->pieces[sq + 11] == bP || pos->pieces[sq + 9] == bP) {
            return TRUE;
        }
    }

    // Check for knights
    for (index = 0; index < 8; index++) {
        piece = pos->pieces[sq + KnightDirection[index]];

        if (IsKnight(piece) && PieceColour[piece] == side) {
            return TRUE;
        }
    }

    // Check for rooks and queens
    for (index = 0; index < 4; index++) {
        dir = RookDirection[index];
        temp_sq = sq + dir;
        piece = pos->pieces[temp_sq];

        while (piece != OFFBOARD) {
            if (piece != EMPTY) {
                if (IsRookQueen(piece) && PieceColour[piece] == side) {
                    return TRUE;
                }
                break;
            }

            temp_sq += dir;
            piece = pos->pieces[temp_sq];
        }
    }

    // Check for bishops and queens
    for (index = 0; index < 4; index++) {
        dir = BishopDirection[index];
        temp_sq = sq + dir;
        piece = pos->pieces[temp_sq];

        while (piece != OFFBOARD) {
            if (piece != EMPTY) {
                if (IsBishopQueen(piece) && PieceColour[piece] == side) {
                    return TRUE;
                }
                break;
            }

            temp_sq += dir;
            piece = pos->pieces[temp_sq];
        }
    }

    // Check for kings
    for (index = 0; index < 8; index++) {
        piece = pos->pieces[sq + KingDirection[index]];

        if (IsKing(piece) && PieceColour[piece] == side) {
            return TRUE;
        }
    }

    return FALSE;
}
Enter fullscreen mode Exit fullscreen mode

 

For top to bottom....

  1. Pawns: If the side is WHITE, the square looks down(-), and if the side is BLACK, the square looks up(+). The next condition is to check the 11th or 9th square in that direction. If a pawn of that colour is in the position to attack the sq, then it is TRUE.

  2. Knights: For each value per its index on the KnightDirection array, we got the piece on that square. Then, the engine checks whether the piece is a knight and if the colour of the piece is the same with the attacking side. If it passes the check, then it is TRUE.

  3. Rooks and Queens: This is now different because they are sliding pieces and they need to keep going until they find the piece with the right colour. The dir is the RookDirection[index], the temp_sq is the square gotten after counting dir from sq, and piece is what is on temp_sq. While the piece is not OFFBOARD, if it's not EMPTY(empty square), the engine checks whether it's a rook or queen of the attacking side. If it passes the check, then it is TRUE, and the loop is broken. If not, the temp_sq goes to another square by adding the value of dir, and check the piece on that square.

  4. Bishops and Queens: Same as Rooks and Queens, but uses BishopDirection and isBishopQueen instead.

  5. Kings: Because of how the king moves, the target sq checks whether a king is within one square of it's position in all directions. Basically, it's the same thing as the Knights loop.

If all these checks are not true, then the function returns FALSE.

To test this function, the following instructions are written in the engine's main file:

#include <stdio.h>
#include <stdlib.h>
#include "defs.h"

#define FEN_1 "8/3q1p2/8/5P2/4Q3/8/8/8 w - - 0 1"

void ShowSQAttackedBySide(const int side, const S_BOARD *pos) {
    int rank = 0;
    int file = 0;
    int sq = 0;

    printf("\n\nSquares attacked by: %c\n", SideChar[side]);

    for (rank = RANK_8; rank >= RANK_1; --rank) {
        for (file = FILE_A; file <= FILE_H; file++) {
            sq = FR2SQ(file, rank);

            if (SqAttacked(sq, side, pos) == TRUE) {
                printf("X");
            } else {
                printf("-");
            }
        }

        printf("\n");
    }

    printf("\n\n");
}

int main() {
    S_BOARD board[1];

    ParseFen(FEN_1, board);

    PrintBoard(board);

    printf("\nSquares attacked by White:\n");
    ShowSQAttackedBySide(WHITE, board);

    printf("\nSquares attacked by Black:\n");
    ShowSQAttackedBySide(BLACK, board);

    return 0;

}
Enter fullscreen mode Exit fullscreen mode

Once you compile the program and run it, it will give you this:

Squares attacked by WHITE & BLACK

Squares attacked by WHITE & BLACK

 

So yeah. That's it for now

If you haven't read the previous article, click here so that you can follow along and if you want to see the code, you can click here to view the Github repo.

Until the next commit....bye 👋

Top comments (0)