DEV Community

Cover image for Chess Engine in C #1: The 10x12 Mailbox
Victor Chigbo
Victor Chigbo

Posted on

Chess Engine in C #1: The 10x12 Mailbox

While going through the video, I came across this illustration:

10*12 board representation
 

So I paused, went further to do some research and discovered that the picture illustrated a 10x12 mailbox board representation. Let's go this rabbit hole together and understand what is going on here.
 

So What is Board Representation?

Board representation is simply a way for the chess engine to represent the chessboard(of course), the pieces on the board, and their movements. It also helps to track other important pieces of game states like which side to move, castling rights, possible en passant moves, and The Fifty Move amongst others.

There are many ways to represent a chessboard in a chess engine but they can be classified into two types of board representation methods, namely:

  1. Piece-centric Representation: They use an array, list or set to keep track of all the pieces on the chessboard, where they are on the board and other related information. Representation methods under this category include piece lists, piece sets, and bitboards.
  2. Square-centric Representation: This category focuses on the board rather than the pieces. They use arrays to represent the number of squares on the board, and whether it is emptied or occupied(and that's why they are called 'mailboxes'). They are very helpful in determining off-board movements. In this category, you can find 8x8 boards, 10x12 boards, 0x88(16x8) boards, etc.

And of course, they can be mixed together to create better results too.
 

My Experience

Looking at the code so far, the board representation technique used here employed a combination of the 10x12 mailbox, a bitboard using the 64bit integer and a 13 by 10 piece list. I have not gone far enough to explain the bitboard and the piece list, but I can fully understand how the mailbox works.

It works by encompassing the 64-square board inside a 120-element array(10x12), containing the real chessboard for the engine. There is the possibility of a chess piece going off board, and that is where the extra squares come in. They form a protective border around the chessboard and can be given a value of offBoard, such that when the engine is generating moves and a move goes off the board, the move generation stops there.

 
 

A 10X12 Chess Game Grids Offset Representation

A 10X12 Chess Game Grids Offset Representation

 
 

The 8x8 chessboard with all 32 pieces on it

The 8x8 chessboard with all 32 pieces on it

 
 

If you noticed, there are two extra ranks in the first image. This is because of how the knight moves.

 
The knight's moves

The knight's moves

 
 

If there were only one extra rank top and bottom and a knight is at g1, the chess engine won't be able to account for the extra two steps that are placed above or below the single border. That's why there's an extra one. For the horizontal borders, assuming that knight is at h3, the extra steps can go over to the other side.
 

Code

In order to represent the board, two arrays are needed; one for converting a number from the 120-square board into its 64-board equivalent and vice-versa.

extern int Sq120ToSq64[BOARD_SQ_NUMBER]; // BOARD_SQ_NUMBER = 120
extern int Sq64ToSq120[64]; 
Enter fullscreen mode Exit fullscreen mode

 

Then a macro is created to return the 120-based equivalent of a position when it's file and rank are given.

#define FR2SQ(f, r) ( (21 + (f) ) + ( (r) * 10 ) ) // f is file, r is rank
Enter fullscreen mode Exit fullscreen mode

 

A function will be used to initialize the board and fill the arrays.

void InitSq120ToSq64() {
    int index = 0;
    int file = FILE_A;
    int rank = RANK_1;
    int sq = A1;
    int sq64 = 0;

    for (index = 0; index < BOARD_SQ_NUMBER; ++index) {
        Sq120ToSq64[index] = 65;
    }

    for (index = 0; index < 64;  ++index) {
        Sq64ToSq120[index] = 120;
    }

    for (rank = RANK_1; rank <= RANK_8; ++rank) {
        for (file = FILE_A; file <= FILE_H; ++file) {
            sq = FR2SQ(file, rank);
            Sq120ToSq64[sq] = sq64;
            Sq64ToSq120[sq64] = sq;
            sq64++;
        }
    }
}
Enter fullscreen mode Exit fullscreen mode

 

First of all, the arrays Sq120ToSq64 and Sq64ToSq120 are filled with the integers 65 and 120 respectively which are impossible values in the games. Then the function runs a nested loop, for each rank, and for each file inside a rank.

The sq is initially set to A1, representing the first file inside the first rank. Using the FR2SQ1 function, the sq is set to the 120-based equivalent of it's position. Basically, if the position is A1, then sq is equal to (21 + 0) + (2 * 0) which is 21. After that, the integer at Sq120toSq64[sq] is set to the value of sq64 and integer at Sq64toSq120[sq64] is set to the value of sq. Then the value of sq64 is increased by 1 and the loop continues until all the files and ranks are iterated.

In the main function of the chess engine, the chess representation technique can be printed on the console like this:

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

int Sq120ToSq64[BOARD_SQ_NUMBER];
int Sq64ToSq120[64];

int main() {
    AllInit(); 

    /* int index = 0;

    for (index = 0; index < BOARD_SQ_NUMBER; ++index) {
        if (index % 10 == 0) {
            printf("\n");
        }

        printf("%5d", Sq120ToSq64[index]);
    }

    printf("\n\n");

    for (index = 0; index < 64; ++index) {
        if (index % 8 == 0) {
            printf("\n");
        }

        printf("%5d", Sq64ToSq120[index]);
    }

    return 0;
}
Enter fullscreen mode Exit fullscreen mode

 

Once you compile and run the whole program, you are going to get this:

A console representation of the 10x12 mailbox, showing the 10x12 box and the 8x8 box

As you can see, the console printed out the Sq120ToSq64 array and the Sq64ToSq120 array, each containing the respective values of the chessboard inside the 120 square array, marked from 0 to 63 and it's 120-based equivalent, marked from 21 to 98.

This was a long one 😅, but I believe you were able to learn something new 😊
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)