How to develop a chess program from scratch (for total beginners) Ep. 4

[Previous episode]

Overview

In the previous chapter we saw how the program scans through all the chessboard to find its own pieces.

The next step is to think for all the possible moves for each one of these pieces. This small chapter shows exactly how this is done.

Scanning all possible moves

In the previous chapter it was shown how a nested for-loop was used to scan through the chessboard for the computer pieces. A second nested for-loop is then used to generate all possible target squares for each of the computer pieces detected.

C# code

if (((Who_Is_Analyzed.CompareTo("HY") == 0) && ((((Skakiera_Thinking[(iii), (jjj)].CompareTo("White King") == 0) || (Skakiera_Thinking[(iii), (jjj)].CompareTo("White Queen") == 0) || (Skakiera_Thinking[(iii), (jjj)].CompareTo("White Rook") == 0) || (Skakiera_Thinking[(iii), (jjj)].CompareTo("White Knight") == 0) || (Skakiera_Thinking[(iii), (jjj)].CompareTo("White Bishop") == 0) || (Skakiera_Thinking[(iii), (jjj)].CompareTo("White Pawn") == 0)) && (m_PlayerColor.CompareTo("Black") == 0)) || (((Skakiera_Thinking[(iii), (jjj)].CompareTo("Black King") == 0) || (Skakiera_Thinking[(iii), (jjj)].CompareTo("Black Queen") == 0) || (Skakiera_Thinking[(iii), (jjj)].CompareTo("Black Rook") == 0) || (Skakiera_Thinking[(iii), (jjj)].CompareTo("Black Knight") == 0) || (Skakiera_Thinking[(iii), (jjj)].CompareTo("Black Bishop") == 0) || (Skakiera_Thinking[(iii), (jjj)].CompareTo("Black Pawn") == 0)) && (m_PlayerColor.CompareTo("White") == 0)))) || ((Who_Is_Analyzed.CompareTo("Hu") == 0) && ((((Skakiera_Thinking[(iii), (jjj)].CompareTo("White King") == 0) || (Skakiera_Thinking[(iii), (jjj)].CompareTo("White Queen") == 0) || (Skakiera_Thinking[(iii), (jjj)].CompareTo("White Rook") == 0) || (Skakiera_Thinking[(iii), (jjj)].CompareTo("White Knight") == 0) || (Skakiera_Thinking[(iii), (jjj)].CompareTo("White Bishop") == 0) || (Skakiera_Thinking[(iii), (jjj)].CompareTo("White Pawn") == 0)) && (m_PlayerColor.CompareTo("White") == 0)) || (((Skakiera_Thinking[(iii), (jjj)].CompareTo("Black King") == 0) || (Skakiera_Thinking[(iii), (jjj)].CompareTo("Black Queen") == 0) || (Skakiera_Thinking[(iii), (jjj)].CompareTo("Black Rook") == 0) || (Skakiera_Thinking[(iii), (jjj)].CompareTo("Black Knight") == 0) || (Skakiera_Thinking[(iii), (jjj)].CompareTo("Black Bishop") == 0) || (Skakiera_Thinking[(iii), (jjj)].CompareTo("Black Pawn") == 0)) && (m_PlayerColor.CompareTo("Black") == 0)))))
                            {

                                for (int w = 0; w <= 7; w++)
                                {
                                    for (int r = 0; r <= 7; r++)
                                    {
                                        // v0.992 - Initialization (if we don't, the target piece value from the previous run
                                        // will be still in the variables if in the next pass there is no target piece at the
                                        // target square, thus leading to problems - activate the logs to see the difference
                                        // if the initialization does not happen)
                                        ProsorinoKommati = "";
                                        ValueOfMovingPiece = 0;
                                        ValueOfTargetPiece = 0;

                                        //v0.980: Removed. It was not used.
                                        //Danger_penalty = false;
                                        MovingPiece = Skakiera_Thinking[(iii), (jjj)];
                                        m_StartingColumnNumber = iii + 1;
                                        m_FinishingColumnNumber = w + 1;
                                        m_StartingRank = jjj + 1;
                                        m_FinishingRank = r + 1;
                                        // v0.992
                                        ProsorinoKommati = Skakiera_Thinking[(m_FinishingColumnNumber - 1), (m_FinishingRank - 1)];

BASIC code

    'Scan the chessboard...
    FOR i = 1 TO 8
        FOR j = 1 TO 8

            'If you find a piece of the computer...
            IF ((MID$(chessboard$(i, j), 1, 1) = "w" AND playerColor$ = "b") OR (MID$(chessboard$(i, j), 1, 1) = "b" AND playerColor$ = "w")) THEN

                'Scan all possible destination squares...
                FOR ii = 1 TO 8
                    FOR jj = 1 TO 8

Java code

        for (iii = 0; iii <= 7; iii++)
        {
                for (jjj = 0; jjj <= 7; jjj++)
                {
                        //v0.980: Reduce all texts ("WK" for "Wh King", "WN" for "Wh Knight" and so on...)
                        if (((Who_Is_Analyzed.equals("HY")) && ((((Skakiera_Thinking[(iii)][(jjj)].equals("WK")) || (Skakiera_Thinking[(iii)][(jjj)].equals("WQ")) || (Skakiera_Thinking[(iii)][(jjj)].equals("WR")) || (Skakiera_Thinking[(iii)][(jjj)].equals("WN")) || (Skakiera_Thinking[(iii)][(jjj)].equals("WB")) || (Skakiera_Thinking[(iii)][(jjj)].equals("WP"))) && (m_PlayerColor.equals("b"))) || (((Skakiera_Thinking[(iii)][(jjj)].equals("BK")) || (Skakiera_Thinking[(iii)][(jjj)].equals("BQ")) || (Skakiera_Thinking[(iii)][(jjj)].equals("BR")) || (Skakiera_Thinking[(iii)][(jjj)].equals("BN")) || (Skakiera_Thinking[(iii)][(jjj)].equals("BB")) || (Skakiera_Thinking[(iii)][(jjj)].equals("BP"))) && (m_PlayerColor.equals("w"))))) || ((Who_Is_Analyzed.equals("Human")) && ((((Skakiera_Thinking[(iii)][(jjj)].equals("WK")) || (Skakiera_Thinking[(iii)][(jjj)].equals("WQ")) || (Skakiera_Thinking[(iii)][(jjj)].equals("WR")) || (Skakiera_Thinking[(iii)][(jjj)].equals("WN")) || (Skakiera_Thinking[(iii)][(jjj)].equals("WB")) || (Skakiera_Thinking[(iii)][(jjj)].equals("WP"))) && (m_PlayerColor.equals("w"))) || (((Skakiera_Thinking[(iii)][(jjj)].equals("BK")) || (Skakiera_Thinking[(iii)][(jjj)].equals("BQ")) || (Skakiera_Thinking[(iii)][(jjj)].equals("BR")) || (Skakiera_Thinking[(iii)][(jjj)].equals("BN")) || (Skakiera_Thinking[(iii)][(jjj)].equals("BB")) || (Skakiera_Thinking[(iii)][(jjj)].equals("BP"))) && (m_PlayerColor.equals("b"))))))
                        {

                                for (int w = 0; w <= 7; w++)
                                {
                                        for (int r = 0; r <= 7; r++)
                                        {
                                                //v0.980: Removed. It was not used.
                                                //Danger_penalty = false;
                                                MovingPiece = Skakiera_Thinking[(iii)][(jjj)];
                                                m_StartingColumnNumber = iii + 1;
                                                m_FinishingColumnNumber = w + 1;
                                                m_StartingRank = jjj + 1;
                                                m_FinishingRank = r + 1;

The code above does the following:

For each piece that the program recognizes as a computer piece, the next nested for-loop for (int w = 0; w <= 7; w++) – for (int r = 0; r <= 7; r++) (this refers to the C# code, look for the equivalent loops in BASIC and Java) is initiated.

This loop then generates all possible target squares for the piece detected, i.e. all the other possible squares of the chessboard. The initial square is obviously the square of the piece detected in the first for-loop.

m_StartingColumnNumber = iii + 1;
m_FinishingColumnNumber = w + 1;
m_StartingRank = jjj + 1;
m_FinishingRank = r + 1;

Important note: Remember that the numbering of the arrays in the C# version starts from 0, not 1. So in arrays we have the numbers 0-7, but in all other rows of the program we use the more intuitive numbers 1-8 that correspond to the actual numbers of the rows of the chessboard.

Additionally, the moving piece is stored in a separate variable, as the piece existing in the target square as well.

MovingPiece = Skakiera_Thinking[(iii), (jjj)];

ProsorinoKommati = Skakiera_Thinking[(m_FinishingColumnNumber - 1), (m_FinishingRank - 1)];

We will use this information later, to restore the chessboard in its initial state, so as to move to thinking for the next piece.

All moves?

But are all the possible moves actually possible moves?!

No!

That is why the next step is to examine the legality of the moves we just generated.

Coming soon: Check the legality of chess moves! The heart of a chess program!

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

%d bloggers like this: