Chess Program thought process analysis article

The goal of this paper is to analyze in a simple way the thought process of a chess program, so as to facilitate understanding among chess programming enthusiasts and to bolster potential improvements in that process.

Huo Chess thinking algorithm (simple)

A new article “Chess Program thought process analysis (Simple) – The Huo Chess example” has been published.

There the thinking process of a chess program is presented in high level in order to help chess programming enthusiasts gain an initial understanding of the general way a chess program works.

One can find the relative article here at Academia.

A new article with more advanced subjects of chess programming will follow.

One can also download the file from below.

Programming a chess application in QBasic (QB64)

Interested in chess programming? You are interested in philosophy too! What is thinking? Can AI be conscious? What does it mean to do something? Can the AI understand that it does play chess? Explore the AI related articles in Harmonia Philosophica and understand why you are already a philosopher!

Other Related articles

News

  • 2022-05-06: Huo Chess v0.7 in QBasic with graphics is released. The version addresses Out of Memory issues with the logs of the application.
  • 2021-11-14: Created a GitHub repository of the Huo Chess Quick Basic edition.
  • 2021-03-14: Updated thinking in levels 4 and 5; now extra analysis at these levels only happens if the move entails the capturing of a piece. Updated CountScore to include positional elements in the evaluation. Introduced the notions of mate and stalemate in the thinking process.
  • 2020-12-16: Fixed issue with en passant move.

This is an article on how one can develop a chess program in QBasic.

It is based on Huo Chess that was developed by me and is available as open source in multiple programming languages (C#, Java, older versions in C++ and Visual Basic).

Parts of the article have been posted as separate tutorials (check here). They are all gathered here in a unique article that can provide an overall understanding of the chess programming complexity.

The tutorial is at the point at a very simple/ high level but it will be enriched as time passes by. The initial goal was to have at least a starting point for someone who needs to delve into the chess programming cosmos and this I believe I have managed to achieve.

Why in QBasic?

Well, BASIC is simple and fun!

Do you need more reasons?

Well…

Here is another one:

10 PRINT "Why not?!"
20 GOTO 10

That’s what happens when you mess with BASIC. Seriously now, at the end, the goal here is to present the algorithm. The specific language of the implementation does not play a particular role. When you are at a level to develop the next Stockfish be sure to remember that it was here from where you started your journey…

The tutorial should be read in conjunction with the source code of Huo Chess offered here. The code itself is written in a simple and structured way and it is heavily commented so that even without any prior knowledge one can easily understand how thw algorithm works.

Let’s not waste any more time!

Happy coding!

I. Beginning

Let us begin from the… beginning. And one step at a time, try to see how we can develop our chess program.

Important Notes

  • Refer to QB64 site for questions regarding how QBasic commands work. Essentially they are simple, but in case your are stuck with an error you cannot resolve, this is the place where you will find your answers.
  • Always have the source code open in a separate window. Although the tutorial only goes throug portions of the code to explain how it works, it is always beneficial to have the whole source code of the working program in front of you.
  • A note about the source code versions: Chapter I to IV refer to the version 0.3 of the code. Chapter V refers to the version 0.6 of the code.
  • The Huo Chess Quick Basic edition is available for download either from here or from the relevant Huo Chess QB64 GitHub repository.

And don’t forget: Coding is about experimenting!

Do not wait everything from this tutorial or from any other tutorial! Just open the QBasic editor and write code! Change things! See what they do! At the end it is YOU who is learning, not me teaching you!

Programming is fun.

Want to learn? Why not start now?

And what better way there is than to develop an advanced program that makes the computer “think” how to play chess?! Forget about those silly beginners’ example programs which print “Hello world”. Who in his right mind ever spends time to write a program which prints “Hello world” on the screen?

BASIC is fun.

A very easy language for kids to start learning programming. So we will use it here. (Not in the mood for BASIC? Search for the Java and C# relevant tutorials in Harmonia Philosophica!)

And in one day, you will have learnt the basic of how to program a chess program in BASIC! The actual implementation could take a bit longer but in general in some days you will have the knowledge of how the program works, thus being in a position to improve it or write your own!

The BASIC programming language is one of the simplest ones. Especially designed for simplicity, it uses simple commands to perform operations. The commands are easy to learn and use, since they are utilizing English language words which are easily recognizable. Want to print something on the screen? Use the command PRINT! Want to determine what will happen if something else happens? Use the command IF! See what I mean?

IF YOU_UNDERSTAND = "Yes" THEN PRINT "Yes I understand!"

Did you understand the above command? Great!

The only thing that might trouble you if you are new to programming is the notion of variables. A variable is an element which holds values. This element is used in various places of the program. The values could be of different types – the ones we will use are integers (1, 4, 10…) and strings/ characters (e.g. “white pawn”).

Variables could be stored also in arrays. An array is a collection of variables in one or more dimensions. It is also known as a “table”. And yes, you guessed right: we will use an array (table) to store the chessboard. Could you guess the dimensions of that table? Spot on again.

DIM SHARED chessboard$(8, 8)

The command DIM defines a variable. We do all the variable declarations in the beginning of the program. The above command declares an 8×8 array which holds the… you guessed it right: The chessboard!

By the way, we are using QBasic64, a version of Quick Basic that is available for free and pretty popular as well. Check https://www.qb64.org/portal/ to get it. The site also contains excellent tutorials and training material. You will have it as a reference throughout the whole process, so make sure you create a bookmark out of it.

After you download QBasic64 from the site, just click on the QB64.exe file and execute it. You will be presented with the IDE (programming interface) of QBasic where you will write your program. I do not need to explain the “Create new”, “Save” or “Save as” functions…

Just start writing the commands and then press “Save as”. Executing the program is easy as well. Just select Run > Start.

As said above, what is the first thing to do? (Besides the “Create new program” part and saving it in a folder of your choosing with a name of your choosing as well)

Some of the first things to do we already mentioned.

First, declare the variables. BASIC is really simple in the sense that it is not so strict in requiring you to declare all the variables before using them, in contrast to other high level languages like C#. However this is also a downside of the language. Leaving the programmer with some slack makes the programmer careless.

So we will declare all the variables we use…

DEFINT A-Z
OPTION BASE 1 'Make tables dimensions start from 1
DIM SHARED chessboard$(8, 8)
COMMON SHARED startingRank, startingColumn
COMMON SHARED finishingRank, finishingColumn
COMMON SHARED startingRankText$, startingColumnText$
COMMON SHARED finishingRankText$, finishingColumnText$
COMMON SHARED Move$
COMMON SHARED MovingPiece$
COMMON SHARED debugMode

There you go. (Read the QB64 Wiki for what DEFINT A-Z and OPTION BASE 1 commands do – Remember, learning entails the process of… learning)

What is next?

What else?

Ask the user for input!

And what else to ask than his first move! For simplicity purposes we will present the main command which tells the user to put his move. The drawing of the board on the screen will be done by the drawBoard() function. A function is an independent set of code that you can call to perform an action. In our case we call the drawBoard function (with the command… CALL DRAWBOARD – I told you it was simple). For the time being forget how the function works. (Even though reading through it and trying to understand how it works would be a lesson on its own…)

So how would you ask for the user input?

Simple by the command… INPUT!

There you go:

INPUT "Enter your move: ", Move$

This command tells the computer to wait for the user to enter something and press Enter. When this happens, the text entered by the user is saved in the Move$ variable. The dollar sign ($) indicates that the variable is a string (text) and not a number.

Let’s stay there.

For now you have learnt how to…

  • Create a new program.
  • Declare the variables you will use (including the chessboard).
  • Ask from the user to enter his first move.

You have also been acquainted with the notions of variables and functions and with some basic BASIC (get the joke?) commands, like IF… THEN or INPUT and PRINT. Don’t worry if you don’t get everything yet. You will as you program more and more every day.

Next lessons will include the next logical steps:

  • Validate that the user move is valid and legal.
  • Redraw the chessboard with the move of the user.
  • Make the computer think of an answer.

You would be surprised how the last part (the thinking of the computer) is a rather simple one. In essence the computer thinks of all possible moves, validates them (in the same way we will validate the move entered by the user) and then for the valid ones it will calculate a score of the position. The move with the best score will be the move of the computer.

II. Check legality of a move

In the previous chapter we managed to create our program in BASIC (QB64) and write the first lines of code to ask for input from the user for his move.

Now we will perform the next and one of the most important steps in a chess program: Checking the legality and validity of a move!

Remember that we asked from the user his move by the command…

INPUT "Enter your move: ", Move$

With this command the computer asks for input by the user and then stores what the user entered (after he presses Enter) into the Move$ variable. As we said in the previous lesson, the $ sign in a variable name denotes that the variable stores a string (text) value and not a number.

Now that we have the move into a single text variable, we should first of all “break it down” into four specific elements:

  • Starting column
  • Starting rank
  • Finishing column
  • Finishing rank

In that way we will have the starting and finishing coordinates of the user’s move, which we will use for the checking of the legality of the move later on.

How do we “break up” the text? By using the MID$ built-in function of BASIC which returns a specific character from a text. So if the user entered the move “g2g4” (which is Grob opening by the way, one of my favorites), then the command…

MID$(Move$, 2, 1)

will return the character “2”, since it will start from character 2 of the Move$ variable and will get 1 character.

Without further delay, here is the code which breaks up the move the user entered into the four numbers we are looking for.

INPUT "Enter your move: ", Move$
startingColumnText$ = MID$(Move$, 1, 1)
startingRankText$ = MID$(Move$, 2, 1)
finishingColumnText$ = MID$(Move$, 3, 1)
finishingRankText$ = MID$(Move$, 4, 1)
SELECT CASE startingRankText$
CASE "1"
startingRank = 1
CASE "2"
startingRank = 2
CASE "3"
startingRank = 3
CASE "4"
startingRank = 4
CASE "5"
startingRank = 5
CASE "6"
startingRank = 6
CASE "7"
startingRank = 7
CASE "8"
startingRank = 8
END SELECT
SELECT CASE finishingRankText$
CASE "1"
finishingRank = 1
CASE "2"
finishingRank = 2
CASE "3"
finishingRank = 3
CASE "4"
finishingRank = 4
CASE "5"
finishingRank = 5
CASE "6"
finishingRank = 6
CASE "7"
finishingRank = 7
CASE "8"
finishingRank = 8
END SELECT
SELECT CASE startingColumnText$
CASE "A", "a"
startingColumn = 1
CASE "B", "b"
startingColumn = 2
CASE "C", "c"
startingColumn = 3
CASE "D", "d"
startingColumn = 4
CASE "E", "e"
startingColumn = 5
CASE "F", "f"
startingColumn = 6
CASE "G", "g"
startingColumn = 7
CASE "H", "h"
startingColumn = 8
END SELECT
SELECT CASE finishingColumnText$
CASE "A", "a"
finishingColumn = 1
CASE "B", "b"
finishingColumn = 2
CASE "C", "c"
finishingColumn = 3
CASE "D", "d"
finishingColumn = 4
CASE "E", "e"
finishingColumn = 5
CASE "F", "f"
finishingColumn = 6
CASE "G", "g"
finishingColumn = 7
CASE "H", "h"
finishingColumn = 8
END SELECT

The above code breaks up the Move$ into the above-mentioned four numbers and you would have noticed that the break up has two steps which we didn’t quite mention before: First we break up the text and then we ‘translate’ the four text values into numbers. This is done with the SELECT CASE commands, which essentially select different numeric value for each possible value of the columns and ranks. And yes, the text “8” needs to be translated to the number 8. As far as the computer is concerned they are completely different monsters altogether.

So now we have what we need. The starting column and rank and the finishing ones. How do we check the legality and validity of the move? Well, there is no “magic” way. We just have to write code to do that.

For clarity purposes we will gather all the code performing the check of the legality in one function (= set of code) which we will call ElegxosNomimotitas (= Check of Legality, in Greek). We will define the call parameters of the function (i.e. what parameters we need to pass over the function for it to do its job) and then write the code inside it.

What would be the input parameters?

The starting and end column and ranks of course. And we will also send the Moving Piece in a separate variable because this is a crucial part of the function. Different pieces move in a different way, right?

The function declaration would be something like…

DECLARE SUB ElegxosNomimotitas(ENSkakiera() AS STRING, startColumn AS INTEGER, startRank AS INTEGER, finishColumn AS INTEGER, finishRank AS INTEGER, MovingPieceEN AS STRING)

The ENSkakiera (=Elegxos Nomimotitas Skakiera = Check Legality Chessboard in Greek) is the array of the chessboard (= Skakiera in Greek) we will need to pass. The function will check the legality of a move not in general, but in the context of a specific chessboard of course. Then beyond the chessboard we pass over the start and end columns and ranks and the Moving piece as mentioned above.

Now we are in the function which checks the legality of the move. We will show how to do this for one piece, the rook. Then the logic is similar (not exactly, but you will get the meaning) for the other pieces.

Without further delay, here is the code…

IF (MovingPieceEN$ = "wrook" OR MovingPieceEN$ = "brook") THEN

    IF debugMode = 1 THEN PRINT "Nomimotita = " + STR$(NomimotitaEN)

    'Check correctness of move (Rook only moves in lines)

    IF ((startColumn <> finishColumn) AND (startRank <> finishRank)) THEN NomimotitaEN = 0

    IF debugMode = 1 AND NomimotitaEN = 0 THEN PRINT "Checkpoint ROOK-0"

    'Check if the Rook moves beyond the limits of the chessboard

    IF ((finishColumn < 1) OR (finishRank < 1)) THEN NomimotitaEN = 0
    IF ((finishColumn > 8) OR (finishRank > 8)) THEN NomimotitaEN = 0


    'Check if another piece is between the current and the target square

    'Horizontal movement

    IF (startColumn > finishColumn) AND (startRank = finishRank) THEN
        FOR J = startColumn TO finishColumn STEP -1
            IF (J <> startColumn) AND (J <> finishColumn) AND ENSkakiera(J, startRank) <> "" THEN NomimotitaEN = 0
        NEXT J
    END IF

    IF (startColumn < finishColumn) AND (startRank = finishRank) THEN
        FOR J = startColumn TO finishColumn
            IF (J <> startColumn) AND (J <> finishColumn) AND ENSkakiera(J, startRank) <> "" THEN NomimotitaEN = 0
        NEXT J
    END IF

    'Vertical movement

    IF (startColumn = finishColumn) AND (startRank > finishRank) THEN
        FOR J = startRank TO finishRank STEP -1
            IF (J <> startRank) AND (J <> finishRank) AND ENSkakiera(startColumn, J) <> "" THEN NomimotitaEN = 0
        NEXT J
    END IF

    IF (startColumn = finishColumn) AND (startRank < finishRank) THEN
        FOR J = startRank TO finishRank
            IF (J <> startRank) AND (J <> finishRank) AND ENSkakiera(startColumn, J) <> "" THEN NomimotitaEN = 0
        NEXT J
    END IF

    'If the start square is the same as the destination...
    IF startColumn = finishColumn AND startRank = finishRank THEN NomimotitaEN = 0

    'Check if a piece of the same colour is at the destination square
    IF MID$(ENSkakiera$(finishColumn, finishRank), 1, 1) = MID$(ENSkakiera$(startColumn, startRank), 1, 1) THEN NomimotitaEN = 0

    IF debugMode = 1 AND NomimotitaEN = 0 THEN PRINT "Checkpoint ROOK-5": 'INPUT a$

END IF

This code checks for many things:

  • If the rook moves in rows or columns
  • If the rook moved beyond the limits of the chessboard
  • If the rook is blocked by another piece before he reaches the destination square
  • If there is a piece of the same colour at the destination square.

If any of the above validations fail, then the Nomimotita (legality in Greek) variable is set to false (0). If not, the Nomimotita is 1 (= true). Note that we use an integer variable to indicate the Nomimotita (which takes values 0 or 1) instead of a text variable (which would take the values “True” or “False”) to use less memory. But we could anyway use a text variable with the same result.

Note: The “IF debugMode = 1” lines of code are used to print to the screen messages for debugging.

It may look complicated, but at the end it is not. The code is simple and self explanatory, with comments. Take for example the first validation: A rook must move in columns or ranks. How is this translated in the code?

    IF ((startRank = finishRank) AND (startColumn <> finishColumn)) THEN NomimotitaEN = 0
IF ((startColumn = finishColumn) AND (startRank <> finishRank)) THEN NomimotitaEN = 0
IF ((startColumn <> finishColumn) AND (startRank <> finishRank)) THEN NomimotitaEN = 0

Read the code at your own pace.

At the end it is just… English. 🙂

After making sure that the move entered is valid, then all we have to do is… make it and present it to the screen.

'If move is legal, then do the move and present it in the chessbooard
IF Nomimotita = 1 THEN

    IF debugMode = 1 THEN
        PRINT "Now we will redraw the chessboard"
    END IF

    'Do the move
    chessboard$(finishingColumn, finishingRank) = chessboard$(startingColumn, startingRank)
    chessboard$(startingColumn, startingRank) = ""
    CLS
    CALL drawBoard

END IF

Go on and check the program source code (check at the end of the tutorial to find it), which contains all the other move validity checks for all the other pieces. You will find it pretty easy to read and understand. It contains comments within the code to support you in your lesson. Copy and paste the code in your QBasic interpreter/ compiler to see it and compile it.

III. Chess thinking algorithm

In the previous chapter we managed to create the function that checks the legality of a move. With that we managed to check the move entered by the user and present it to the screen.

What is next?

To make the computer think of an answer!

In essence this is easy! (the difficult part is to make the computer think of a really good move, that we will tackle later on)

What we will need besides the SUB which checks the legality of the move (ElegxosNomimotitas) is a SUB which counts the score of any given position in the chessboard. This will allow us to evaluate all the possible moves, so that the computer can select the best one.

This is done by the code below, which simply scans the chessboard for pieces and adds or subtracts the value of each piece it founds from the total score of the chessboard.

SUB countScore

positionScore = 0

FOR I = 1 TO 8
    FOR J = 1 TO 8

        IF chessboard$(I, J) = "wpawn" THEN positionScore = positionScore + 1
        IF chessboard$(I, J) = "wrook" THEN positionScore = positionScore + 5
        IF chessboard$(I, J) = "wknight" THEN positionScore = positionScore + 3
        IF chessboard$(I, J) = "wbishop" THEN positionScore = positionScore + 3
        IF chessboard$(I, J) = "wqueen" THEN positionScore = positionScore + 9
        IF chessboard$(I, J) = "wking" THEN positionScore = positionScore + 100

        IF chessboard$(I, J) = "bpawn" THEN positionScore = positionScore - 1
        IF chessboard$(I, J) = "brook" THEN positionScore = positionScore - 5
        IF chessboard$(I, J) = "bknight" THEN positionScore = positionScore - 3
        IF chessboard$(I, J) = "bbishop" THEN positionScore = positionScore - 3
        IF chessboard$(I, J) = "bqueen" THEN positionScore = positionScore - 9
        IF chessboard$(I, J) = "bking" THEN positionScore = positionScore - 100

    NEXT J
NEXT I

END SUB

Easy? Pretty much. All that is needed is a nested FOR loop (read in QB64 here how that works). Nothing more.

Now that we have that, let’s move on to the main course.

The ComputerMove SUB, which – you guessed right – makes the computer perform a move!

In essence, the steps needed are pretty simple:

Scan the chessboard.

If you find a piece of the computer, then…

Scan all possible moves of that piece to all squares of the chessboard.

For every possible move, check the legality of that move.

If the move is legal, then make it!

Check the score of the move.

If the score is best than the current best move (in the beginning there obviously no current best move), then this is the current best move!

After you have examined all the possible moves, do the current best move

Simple isn’t it?

How is the scanning of the chessboard and the checking of all possible moves performed? With four nested FOR loops.

Check the code below. It simple scans all the chessboard with the FOR loops of I and J and then, if it finds a piece which belongs to the computer, it scans all possible destination squares with the FOR loops of ii and jj.

How do we determine is the piece we found is one of the computer’s pieces? We compare the first letter of the piece (which would be ‘w’ or ‘b’ for white and black pieces) with the color of the player. If for example the color of the player is ‘w’ (for white) and we encounter a piece ‘brook’, then this is a piece of the computer since it is black – i.e. opposite than the color of the player.

'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

                    startingColumn = I
                    startingRank = J
                    finishingColumn = ii
                    finishingRank = jj

                    MovingPiece$ = chessboard$(I, J)
                    ProsorinoKommati$ = chessboard$(ii, jj)

                    'Check legality of the move entered
                    CALL ElegxosNomimotitas(chessboard$(), 0, startingColumn, startingRank, finishingColumn, finishingRank, MovingPiece$)

                    'If move is legal, then do the move and present it in the chessbooard
                    IF Nomimotita = 1 THEN

                        'Do the move
                        chessboard$(finishingColumn, finishingRank) = chessboard$(startingColumn, startingRank)
                        chessboard$(startingColumn, startingRank) = ""

                        'Count the score of the move
                        CALL countScore

                        'If the score is better than the existing best score, then this is the best move now (and the best score)
                        IF ((playerColor$ = "b" AND positionScore >= bestPositionScore) OR (playerColor$ = "w" AND positionScore <= bestPositionScore)) THEN
                            bestStartingRank = startingRank
                            bestStartingColumn = startingColumn
                            bestFinishingRank = finishingRank
                            bestFinishingColumn = finishingColumn
                            bestPositionScore = positionScore
                        END IF

                    END IF

                    'Undo the move
                    chessboard$(startingColumn, startingRank) = MovingPiece$
                    chessboard$(finishingColumn, finishingRank) = ProsorinoKommati$

                NEXT jj
            NEXT ii

        END IF

    NEXT J
NEXT I

If the move analyzed is legal (the ElegxosNomimotitas SUB is called to determine that) then the move is performed. The score of the position resulting after that is counted (the CountScore SUB is called for that). If the score is better than the current ‘best score’ (the initial best score is zero of course) then this move is registered as best move.

After the scanning is complete, we simply perform the best move!

'Do the best move found
chessboard$(bestFinishingColumn, bestFinishingRank) = chessboard$(bestStartingColumn, bestStartingRank)
chessboard$(bestStartingColumn, bestStartingRank) = ""
CLS
CALL drawBoard

Easy? Yes!

IV. Advanced concepts (Part 1)

The last chapters (Advanced concepts Part 1 and 2) will touch-base on some more advanced concepts in chess programming:

  • Thinking for more moves ahead in the game
  • Improving the position evaluation
  • Selecting the best move (miniMax concept introduction)

Up to now the program we have developed (see the previous lessons, where you can download the program) can think in one (1) move depth. This means that it simply (well, not ‘simply’ – we have gone a long way to make this happen) scans all the possible moves and then selects the one with the highest score.

This has just gave us an insight of the way a computer may think for chess, but a very limited one. The basic thing for thinking for chess is thinking in depth. Everybody would agree that thinking in more depth makes someone a better player.

How can we make that happen?

Simple!

We will copy-and-paste (sort of speak) the main computerMove SUB (Move depth 1 – Existing) two times more, so that the computer also thinks two moves more in depth. In essence, there will be two additional ‘thinking SUB-routines’: One which thinks of the potential human moves (Move depth 2) and another that thinks of the reactions of the computer to those moves (Move depth 3).

After that we will have the following structure:

DEPTH 1: computerMove: This routine thinks of the potential moves of the computer at the first level of thinking. If the thinkingDepth is not reached (i.e. if it is not set to 1, but e.g. 3) then the HumanMove1 SUB is called.

IF Move = thinkingDepth THEN
   'If the score is better than the existing best score, then this is the best move now (and the best score)
   IF ((playerColor$ = "b" AND positionScore >= bestPositionScore) OR (playerColor$ = "w" AND positionScore <= bestPositionScore)) THEN
           bestStartingRank = startingRank
           bestStartingColumn = startingColumn
           bestFinishingRank = finishingRank
           bestFinishingColumn = finishingColumn
           bestPositionScore = positionScore
   END IF
END IF

IF Move < thinkingDepth THEN CALL HumanMove1(chessboard$())

DEPTH 2: HumanMove1: This routine is scanning for all the possible answers of the human opponent. For each of those movements, the next thinking depth routine is called.

DEPTH 3: ComputerMove2: The last routine. Searches for possible moves at depth 3 (i.e. 3 half-moves). The move which ends up with the position with the best score at the end, is the one chosen.

IF ((playerColor$ = "b" AND positionScore >= bestPositionScore) OR (playerColor$ = "w" AND positionScore <= bestPositionScore)) THEN
          bestStartingRank = startingRank
          bestStartingColumn = startingColumn
          bestFinishingRank = finishingRank
          bestFinishingColumn = finishingColumn
          bestPositionScore = positionScore
END IF

With these you will have the program think in depth of 3 half-moves (i.e. a move of the computer, a move of the human opponent and a last move by the computer).

We have been slowly progressing.

Yet, there is a lot more way to go…

V. Advanced concepts (Part 2): Improving the computer thinking with MiniMax

The algorithm described above is simple and does make the computer think in depth. When using the code below, you will see an obvious latency in computer’s thinking vis-a-vis the time needed by the previous version which thinks in depth of only 1 move.

When using the code however one can see that it does not make good moves! Simply by checking the score of the positions at the end, does not lead to wise decisions. The computer thinks, but not very well.

Yet.

What is needed for that to happen?

First improvement: Improvement of the position evaluation.

Now we are just counting the material in the final position.

SUB countScore

positionScore = 0

FOR I = 1 TO 8
    FOR J = 1 TO 8

IF chessboard$(I, J) = "wpawn" THEN positionScore = positionScore + 1
IF chessboard$(I, J) = "wrook" THEN positionScore = positionScore + 5
IF chessboard$(I, J) = "wknight" THEN positionScore = positionScore + 3
IF chessboard$(I, J) = "wbishop" THEN positionScore = positionScore + 3
IF chessboard$(I, J) = "wqueen" THEN positionScore = positionScore + 9
IF chessboard$(I, J) = "wking" THEN positionScore = positionScore + 100

IF chessboard$(I, J) = "bpawn" THEN positionScore = positionScore - 1
IF chessboard$(I, J) = "brook" THEN positionScore = positionScore - 5
IF chessboard$(I, J) = "bknight" THEN positionScore = positionScore - 3
IF chessboard$(I, J) = "bbishop" THEN positionScore = positionScore - 3
IF chessboard$(I, J) = "bqueen" THEN positionScore = positionScore - 9
IF chessboard$(I, J) = "bking" THEN positionScore = positionScore - 100

    NEXT J
NEXT I

END SUB

But material is not everything.

For example in the initial position all moves seem to result in the same material score, however it is known that in the chess opening the good player always moves hies pieces near the center of the chess board, avoid unnecessary movements of the king and the queen and avoids to move the same piece twice.

EXERCISE: Try to improve the countScore SUB to cater for the above. You might need to also introduce a new variable which will count the number of moves we are in the game, so that the computer knows if we are at the opening, the middle of the final stage of the game.

Second improvement: Apply the MiniMax algorithm

Improving the CountScore SUB does not solve our problems.

The thinking mechanism of the program we have desribed is inefficient. One could say that it is inherently flawed.

The program searches for the best score at the end of 3 half-moves, but does not cater at all for the fact that the human opponent moves (at move depth 2) will not be the ones which maximize the score for the computer, but the ones maximizing the score for the human opponent.

In other words: The variants (set of moves) which include completely stupid human opponent moves end up in high scores in favor of the computer and that is why, those variants will at the end be chosen.

But in real life the human opponent will never play his worst moves, but quite the opposite: He will play his best moves so as to win the computer!

The following example will better illustrate the problem.

Imagine we are at the following position…

Important note: The Huo Chess program was developed with simple text-like ‘graphics’. There is also a graphics-version based on Deep Basic chess program (by Thomas McBurney), which you can also download.

An initial version of Huo Chess which simply thought in terms of the best score at the end of 3-half-moves, would play… Qf7+ in this position.

But this is a bad move! Why does it play that?

Simple.

The computer assumes that at the next move human will play something stupid and then it will be able to capture the king of the opponent. The set of moves “1. Qf7+ [something stupid] 2. Qxe8” results in the best (highest) score for the computer, so this move is selected.

The algorithm did not even think that human after Qf7+ will simply play KxQf7 and take the queen, simply because this move results in low score for the computer.

But how do you take into account the best moves for the human opponent (MAXimize value) and at the same time the worst possible variants for the computer (MINImize value)? In other words, at the end, how can the computer play its best move taking into account the worst scenario, which we will have only if the human opponent plays his best move?

EXERCISE: Try to think of the above on your own, WITHOUT reading online about the MiniMax algorithm. First of all – who knows? – you might think of something better! Secondly, one only masters knowledge when he has tried on his own and failed to acquire it. Having things ready for you simply does not lead to wisdom.

The solution to the above problem is the MinMax algorithm. The current version of Huo Chess utilizes it, so you can read there how it works. However note that you can never learn anything by simply copying the program of someone else. Unless you write the program on your own, make mistakes, spend countless nights and days pondering upon them, you will never truly develop anything.

In the MinMax algorithm, we start from the lower level nodes and go up to the beginning of the tree, like in the schema that follows:

MinMax algorithm [Source: Wikipedia]

Suppose the game being played only has a maximum of two possible moves per player each turn. The algorithm generates the tree shown in the figure above, where the circles represent the moves of the computer AI running the algorithm (maximizing player), and squares represent the moves of the human opponent (minimizing player). For the example’s needs, the tree is limited to a look-ahead of 4 half-moves.

The algorithm evaluates each leaf node using the CountScore evaluation functions, obtaining the values shown. The moves where the maximizing player wins are assigned with positive infinity, while the moves that lead to a win of the minimizing player are assigned with negative infinity (this is again for illustration purposes only – infinity will not happen in the game as it is currently developed). At level 3, the algorithm will choose, for each node, the smallest of the child node values, and assign it to that same node (e.g. the node on the left will choose the minimum between “10” and “+8”, therefore assigning the value “10” to itself). The next step, in level 2, consists of choosing for each node the largest of the child node values. Once again, the values are assigned to each parent node. The algorithm continues evaluating the maximum and minimum values of the child nodes alternately until it reaches the root node, where it chooses the move with the largest value (represented in the figure with a blue arrow). This is the move that the player should make in order to minimize the maximum possible loss. (source)

In simpler words: It is not enough to calculate the best end-score of a node! Because this might be the result of a combination of good computer moves and bad human moves. The human will not make stupid moves (or at least this will have to be our assumption). So in the level that the computer plays, we must maximize the score (the computer makes the best possible move), but in the levels the human opponent plays we must minimize the score of the computer (i.e. the human plays the best move for him, so the worst move for the computer).

In order for the program to calculate the best move, a number of “for loops” are applied so as to make the abovementioned backwards computation possible.

Make sure you check the relevant Huo Chess C# tutorials or the page in Codeproject which refer in more depth to the algorithm (which stays the same regardless of the programming language you use of course).

More updates coming soon!

Download Source Code

This section contains the source code of the Huo Chess QBasic application. Make sure to check here frequently for the latest updates.

Huo Chess source

The Huo Chess source code can be found below. Copy and paste the code in your QBasic interpreter/ compiler to see it and compile it.

One can also download a version with more elaborate graphics for the chessboard, where I have re-used the graphics from the Deep Chess program (by Thomas McBurney). Note that all the code is the same as the Huo Chess above, only the graphics are added – so if you need to study the engine the Huo Chess edition without these more elaborate graphics will perfectly fit your needs.

Important Note: For it to work, copy the PIECES.EGA file you will find in the Deep Chess site to the same folder as your program (this file contains the images of the pieces).

For historical purposes I have added previous versions of the code. You do not have to worry about those. Simply choose the latest one. Make sure you keep on coming to this page for updates of the code.

Important Notes

  • The “HUO Chess with graphics v0.6” needs a lot of memory for the logs so in some systems it may throw an Out of Memory exception. In those cases, please use the “Huo Chess v0.7” which has reduced memory needs instead.

Opening Book Editor

The latest versions (v0.6) of the code have an opening book functionality. In order to generate the files of the opening book you can use the Opening Book Editor found below.

Simply run the program, play the moves you want to store in the opening book and they will all be stored in separate txt files. These files must then be places in the same folder as the Huo Chess executable for the latter to utilize them.

As with Huo Chess, make sure you visit this page again to check for any updates or improvements in the code!

Other Huo Chess resources

Other Huo Chess related resources are listed in this section.

Feel free to write for any comments or suggestions for the program.

Until we meet again…

Happy coding!

Programming for kids: Developing a chess program in BASIC – Part 3

Interested in chess programming? You are interested in philosophy too! What is thinking? Can AI be conscious? What does it mean to do something? Can the AI understand that it does play chess? Explore the AI related articles in Harmonia Philosophica and understand why you are already a philosopher!

Programming for kids – How to program a chess program in BASIC

Other Related articles

In the previous lesson we managed to create the function which checks the legality of a move. With that we managed to check the move entered by the user and present it to the screen.

What is next?

To make the computer think of an answer!

In essence this is easy! (the difficult part is to make the computer think of a really good move, that we will tackle later on)

What we will need besides the SUB which checks the legality of the move (ElegxosNomimotitas) is a SUB which counts the score of any given position in the chessboard. This will allow us to evaluate all the possible moves, so that the computer can select the best one.

This is done by the code below, which simply scans the chessboard for pieces and adds or subtracts the value of each piece it founds from the total score of the chessboard.

SUB countScore

positionScore = 0

FOR I = 1 TO 8
    FOR J = 1 TO 8

        IF chessboard$(I, J) = "wpawn" THEN positionScore = positionScore + 1
        IF chessboard$(I, J) = "wrook" THEN positionScore = positionScore + 5
        IF chessboard$(I, J) = "wknight" THEN positionScore = positionScore + 3
        IF chessboard$(I, J) = "wbishop" THEN positionScore = positionScore + 3
        IF chessboard$(I, J) = "wqueen" THEN positionScore = positionScore + 9
        IF chessboard$(I, J) = "wking" THEN positionScore = positionScore + 100

        IF chessboard$(I, J) = "bpawn" THEN positionScore = positionScore - 1
        IF chessboard$(I, J) = "brook" THEN positionScore = positionScore - 5
        IF chessboard$(I, J) = "bknight" THEN positionScore = positionScore - 3
        IF chessboard$(I, J) = "bbishop" THEN positionScore = positionScore - 3
        IF chessboard$(I, J) = "bqueen" THEN positionScore = positionScore - 9
        IF chessboard$(I, J) = "bking" THEN positionScore = positionScore - 100

    NEXT J
NEXT I

END SUB

Easy? Pretty much. All that is needed is a nested FOR loop (read in QB64 here how that works). Nothing more.

Now that we have that, let’s move on to the main course.

The ComputerMove SUB, which – you guessed right – makes the computer perform a move!

In essence, the steps needed are pretty simple:

Scan the chessboard.

If you find a piece of the computer, then…

Scan all possible moves of that piece to all squares of the chessboard.

For every possible move, check the legality of that move.

If the move is legal, then make it!

Check the score of the move.

If the score is best than the current best move (in the beginning there obviously no current best move), then this is the current best move!

After you have examined all the possible moves, do the current best move

Simple isn’t it?

How is the scanning of the chessboard and the checking of all possible moves performed? With four nested FOR loops.

Check the code below. It simple scans all the chessboard with the FOR loops of I and J and then, if it finds a piece which belongs to the computer, it scans all possible destination squares with the FOR loops of ii and jj.

How do we determine is the piece we found is one of the computer’s pieces? We compare the first letter of the piece (which would be ‘w’ or ‘b’ for white and black pieces) with the color of the player. If for example the color of the player is ‘w’ (for white) and we encounter a piece ‘brook’, then this is a piece of the computer since it is black – i.e. opposite than the color of the player.

'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

                    startingColumn = I
                    startingRank = J
                    finishingColumn = ii
                    finishingRank = jj

                    MovingPiece$ = chessboard$(I, J)
                    ProsorinoKommati$ = chessboard$(ii, jj)

                    'Check legality of the move entered
                    CALL ElegxosNomimotitas(chessboard$(), 0, startingColumn, startingRank, finishingColumn, finishingRank, MovingPiece$)

                    'If move is legal, then do the move and present it in the chessbooard
                    IF Nomimotita = 1 THEN

                        'Do the move
                        chessboard$(finishingColumn, finishingRank) = chessboard$(startingColumn, startingRank)
                        chessboard$(startingColumn, startingRank) = ""

                        'Count the score of the move
                        CALL countScore

                        'If the score is better than the existing best score, then this is the best move now (and the best score)
                        IF ((playerColor$ = "b" AND positionScore >= bestPositionScore) OR (playerColor$ = "w" AND positionScore <= bestPositionScore)) THEN
                            bestStartingRank = startingRank
                            bestStartingColumn = startingColumn
                            bestFinishingRank = finishingRank
                            bestFinishingColumn = finishingColumn
                            bestPositionScore = positionScore
                        END IF

                    END IF

                    'Undo the move
                    chessboard$(startingColumn, startingRank) = MovingPiece$
                    chessboard$(finishingColumn, finishingRank) = ProsorinoKommati$

                NEXT jj
            NEXT ii

        END IF

    NEXT J
NEXT I

If the move analyzed is legal (the ElegxosNomimotitas SUB is called to determine that) then the move is performed. The score of the position resulting after that is counted (the CountScore SUB is called for that). If the score is better than the current ‘best score’ (the initial best score is zero of course) then this move is registered as best move.

After the scanning is complete, we simply perform the best move!

'Do the best move found
chessboard$(bestFinishingColumn, bestFinishingRank) = chessboard$(bestStartingColumn, bestStartingRank)
chessboard$(bestStartingColumn, bestStartingRank) = ""
CLS
CALL drawBoard

Easy? Yes!

Happy coding!

Read the full program here. Copy and paste the code in your QBasic interpreter/ compiler to see it and compile it.

IMPORTANT NOTES

  • The code is draft and errors might exist. Make sure to also check Huo Chess in C# (can be found in Harmonia Philosophica here).

Next lesson: How to improve the game of the computer.

Huo Chess (C# micro chess)

Huo Chess DV – GUI edition

Interested in chess programming? You are interested in philosophy too! What is thinking? Can AI be conscious? What does it mean to do something? Can the AI understand that it does play chess? Explore the AI related articles in Harmonia Philosophica and understand why you are already a philosopher!

Latest versions

  • In .NET Framework: Huo Chess 0.9922
  • In .NET: Huo Chess DV [2021-11-10]

Huo Chess News

  • 2021-11-10: Ported Huo Chess in Visual Studio 2022 (C# .NET 6.0) to create the latest Huo Chess DV version. The equivalent version in .NET Framework is the v0.9922 version.
  • 2021-04-07: Re-optimization of CountScore (evaluation of position) function for endgames regarding the pawns evaluation.
  • 2021-04-03: Optimized the CountScore (evaluation of position) function for endgames. Huo Chess v0.9921 beat bot at Chess.com with 1100 ELO rating.
  • 2021-03-20: Added the castling capability also for the computer (up to now, the program only recognize and allowed the castling move for the human opponent).
  • 2021-03-14: Thinking in level 4 and 5 is conducted only if the moves entail the capturing of a piece. Removed redundant code. Improved CountScore function with positional elements for the ending of the game. Introduced the elements of mate and stalemate in the thinking process.
  • 2021-01-06: Fixed initialization of nodes 3 and 4.
  • 2020-09-03: Minor updates.
  • 2020-08-10: Updated the countScore function that evaluates positions to include also qualitative criteria for the position.
  • 2020-08-03: Minor updates to the v0.992 Developers Edition. The trimming rules have been updated to enable deeper thinking.
  • 2019-02-21: The v0.992 has received initial operational capability. The algorithm now works for thinking depth of 5 half-moves, with thinking tree trimming applied.
  • 2019-02-12: Huo Chess version 0.991 published. Now the algorithm performs as planned. Thinking depth limited to 3 half-moves.

Huo Chess Overview

The Huo Chess is one of the smallest open source chess programs in C# (the latest .NET console version is only 159 KB is size, even though it utilizes the latest .NET Platform; while the latest version in .NET Framework is only 44 KB in size). It has heavily commented source code so that it can be used for teaching purposes on how to develop a chess program (or a program in general). It can be easily reused in other applications, e.g. to use it as a chess engine for a robot playing chess (see here).

Feel free to re-use it as you see fit (including changing it or selling it), as long as the source is cited properly. The goal is to spread the knowledge on the basics of chess programming, so sharing is important. Feel free also to contribute to the project, by contacting Harmonia Philosophica with ideas or code that can be used.

Huo Chess sites

You can download the latest files via the relative sites:

Alternatively you can download it below.

Important Notes: The latest version of Huo Chess that is still in development is available only in this site and in GitHub repository. The CodeProject and the MSDN sites still have the v0.992 version.

Huo Chess-based tutorials

Over the years I have written several tutorials on how to develop a chess program based on the Huo Chess.

Tutorials on how to develop a chess program include:

LATEST VERSIONS

DV Version highlights

The latest Huo Chess DV (Delta Version) editions are built in the latest Visual Studio 2022 and use the latest C# .NET 6.0 platform. Remember: along with having the goal of being the smallest chess program for educational purposes, the goal is also to constantly follow all developments in the programming landscape so as to stay relevant!

However being modern and flexible has a price. The new platform had a significant impact on the size of the Huo Chess application: Even after all optimizations, the console edition is now 159 KB (from 44 KB that it used to be) and the GUI edition is now 239 KB (from 96 KB that it used to be). Hopefully the application trimming in the new .NET platform will be improved in the future so these numbers can do down.

Read the Develop a (chess) program in Visual Studio 2022 (C# NET 6.0) article to see how the Huo Chess program was ported into Visual Studio 2022 and .NET 6.0, along with some details on the publishing and trimming settings of the application.

Version 0.9922 highlights

The version 0.9922 is the latest .NET Framework version, i.e. the equivalent to the latest DV Version in .NET. This version has only minor updates regarding logs when compared to v0.9921.

OLDER VERSIONS

Version 0.9921 highlights

The new version of Huo Chess (v0.9921) is even smaller in size than all the previous ones and yet much more capable. This was made possible by optimizing code and removing redundant code as well. The official edition with Windows Forms user interface is 77 KB in size (as opposed to 78 KB of the previous version), the Console application with a chessboard User Interface (UI) edition is 45 KB (as opposed to the 46 KB of version v0.992) and the Console application with text-based chessboard UI edition is 44 KB in size (whereas the previous version was 46 KB in size).

The new version has an updated evaluation function (CountScore) for the endgame, it has improved code for the castling move and also has an optimized deep thinking mechanism.

Huo Chess v0.9921 editions

  • Huo Chess 0.9921 with GUI: This version is the main version with a Windows Forms chessboard User Interface.
  • Huo Chess 0.9921 cs: Console application (text only).
  • Huo Chess 0.9921 cs with graphics: Console application, with minimum text-graphics to depict the chessboard.
  • Huo Chess 0.9921 Developers version: Full developers version with Windows Forms chessboard and logs to show the thinking mechanism. (Attention: Remember to delete the logs when needed, since their size can increase significantly)

Version 0.992 highlights

The v0.992 version of Huo Chess is small in size (as all the previous ones) and much more capable. The official edition with Windows Forms user interface is 78 KB in size, the Console application with a chessboard User Interface (UI) edition is 46 KB and the Console application with text-based chessboard UI edition is 46 KB in size.

Issues with the MiniMax thinking algorithm are fixed and now the computer makes logical moves in every circumstance (at least for the depth of 5 half-moves in which it thinks). Capability of thinking at depth of more half-moves will be added in the future. The program also features an Opening book capability (must have positions in the “Opening Book” folder to use it).

Additional to the above, a Developers Edition has been created, which includes analytic logs of the thinking mechanism for debugging (for teaching purposes). The logs can be easily activated or deactivated. This edition also takes a small step towards showing the variant which the computer thinks to the user interface.

The Opening Book editor is distributed separately. Along with the editor, a library of some sample opening book positions is also included in the distribution files.

Huo Chess editions

There are various Huo Chess editions, each one with slightly different User Interface, plus one for developing purposes.

For the latest Huo Chess DV (Delta Version) there are currently two editions:

  • Huo Chess DV console: The console edition supporting opening functionality and up to 5-ply thinking. Currently using C# .NET 6.0 and standing at 159 KB.
  • Huo Chess DV: The GUI edition supporting opening functionality and up to 5-ply thinking. It also contains logs that can be activated to analyze and debug the thinking algorithm. Currently using C# .NET 6.0 and standing at 239 KB.

Both editions have heavily commented code to allow for using the open source chess engine for educational purposes.

Future versions candidate improvements

There is already a list of potential improvements for the next version of Huo Chess, that can be found below:

  • Add castling capability for the computer to also be able to castle. Also castling should be embedded in the CountScore function.
  • Reduce size by improving ‘peripheral’ functions (like CheckForBlackMate, ElegxosNomimotitas et cetera).
  • Increase efficiency of MiniMax algorithm, by taking into account the average score of each branch. (code already in place, but commented out)
  • Add neural network capability: This will be achieved at a very primitive level by having key points of the MiniMax algorithm (the inequalities at each node level analysis in ComputerMove) being dependent of values stored in external configuration files and by updating those files every time a game is played (increase ‘score’ if the game is a win, decrease if it resulted in defeat). This is still in preliminary stage, but I will try to have a relative Developer edition ready in the next version (without compromising the size).
  • Improve CountScore function, to take into account the position of the chessboard, whether you move the same piece twice in the opening et cetera.

Huo Chess DV distribution files (latest .NET version)

The Huo Chess DV version is the version developed in Visual Studio 2022 and utilizing C# .NET 6.0.

These versions are expected to be updated frequently as the .NET Platform is also updated. Needless to say that these editions render the v0.9921 version the last version utilizing the .NET Framework.

Huo Chess v0.9922 distribution files (latest .NET Framework version)

The version 0.9922 of Huo Chess is the latest version available in .NET Framework. It is the equivalent of the DV version but in the .NET Framework.

Huo Chess v0.9921 distribution files

The version 0.9921 of Huo Chess is currently in development. Take a look at the progress of the project exclusively here at Harmonia Philosophica or directly in the GitHub repository. The code is updated frequently.

HUO CHESS 0.9921 with GUI – Developers edition 2021-04-03 (GitHub)

Note that this is a draft version which is still under development. Also please remember to delete the logs after some moves, or disable them completely if you want to play a full game. The size of the logs of the Developers edition can increase significantly after only some moves.

Di mi se mai fu fatta alcuna cosa
(Tell me if anything was ever done to completion)

~ Leonardo da Vinci

Huo Chess v0.992 distribution files

The version 0.992 of Huo Chess is in development. Take a look at the progress of the project exclusively here at Harmonia Philosophica! The code is updated frequently.

All the files of the v0.992 can be found below. Make sure you download the latest one. The previous versions are kept for historical reference purposes. Also at the end feel free to download the latest v0.9921 version that is still in development

This version is the officially stable version that can also be found in the GitHub repository and the official sites (like CodeProject) which host the Huo Chess code.

Huo Chess v0.991 distribution files

Distribution files for the Huo Chess v0.991 version include the following:

  • Huo Chess 0.992 with GUI
  • Huo Chess 0.992 cs
  • Huo Chess 0.992 cs with graphics
  • Huo Chess 0.992 Developers version
  • Opening Book editor
  • Opening Book

Feel free to contact me for anything regarding the code or the project in general. Remember that the goal is not only to create the smallest chess program but also to create a good basis for educational purposes.

Huo Chess Opening Editor

From the beginning of the Huo Chess project (well, almost from the beginning), an opening functionality was developed. The opening book of Huo Chess is edited with the help of a dedicated tool: the Huo Chess Opening Editor. Simply run the tool, play the moves by selecting “Opening mode” and all the moves will be stored as suggested moves for the computer in its opening book.

There is a C++ (cpp) and a C# (cs) version of the tool, which can be both downloaded below.

The tools generate txt files which hold the positions of the opening book, along with the suggested moves for each position. Note that there must exist a ‘Huo Chess Opening Book‘ folder in the same folder as the application for the latter to store the opening book files.

Make sure you keep checking back in this page for more updates.

Huo Chess Java edition

The Java edition of Huo Chess is also developed in parallel with the C# versions. Currently, only the core engine with text interface with the user is developed in Java. Anyone willing to provide a GUI is more than welcome to do so. (I will try to do that as soon as I have time)

This code can be the basis for an Android Huo Chess application. I am currently working with Visual Studio and Xamarin framework to build it.

Huo Chess QBasic edition

The Huo Chess has been written in QBasic as well. Yes, you read it right! The old friend from the past, BASIC, is still alive and kicking!

You can find the code below. Along with the games’ source code, an opening editor is also distributed. Both work in the same way the C# edition works.

Feel free to write to me for any comments or suggestions.

Instead of epilogue…

The ultimate goal is to go back to where I begun programming and fulfill my child dream: to create a chess program for Commodore 128. The porting of the current Huo Chess version to QBasic is currently in progress and then the road to porting to Commodore BASIC v7.0 is open…

And remember: Huo Chess was not made to be completed. But exactly the opposite: It is here to remind us all the constant struggle to perfection. A struggle so vain as any other human struggle and yet, a struggle so familiar and lovely.

Huo Chess will constantly be upgraded…

By me… By you… By everyone…

And year by year it will constantly be better and smaller…

Until there is nothing left…

Because at the end, the best chess game I will ever play will be that game I played as a child, with my father, trying to learn how to play…

APPENDIX – Huo Chess games

This appendix contains various games played by Huo Chess over the years.

Game 1: Huo Chess v0.9921 vs. Jimmy bot (600 ELO rated) at Chess.com

Huo Chess v0.992 vs. Jimmy Bot @ Chess.com [2021-03-21]

[Site “Chess.com”]
[Date “2021.03.21”]
[Round “?”]
[White “Huo_Chess”]
[Black “Jimmy”]
[Result “1-0”]
[TimeControl “-“]

1. g4 g5 2. Nc3 d5 3. Bh3 Nc6 4. Nf3 h6 5. d4 Qd6 6. Be3 b6 7. Bd2 Nb4 8. Nb5 Qd7 9. Nxa7 Rxa7 10. Bxb4 Nf6 11. Ba3 Ba6 12. c3 Bc4 13. Ne5 Qb5 14. Bg2 Ra4 15. e3 Qa5 16. b4 Ba6 17. bxa5 Rxa5 18. Bb2 Bg7 19. Qf3 Bb7 20. c4 h5 21. gxh5 Ra7 cxd5 Ra6 23. e4 Bh6 24. Bc1 Ra4 25. Be3 O-O 26. Kd1 Ba6 27. Nc6 Kh7 28. Nxe7 Ra5 29. Qxf6 Bd3 30. Nf5 Kg8 31. Nxh6+ Kh7 32. Bxg5 Raa8 33. Nxf7 Rxf7 34. Qxf7+ Kh8 35. Bf6# 1-0 

The game resulted in Huo Chess easily beating the bot within 35 moves.

Game 2: Huo Chess v0.9921 vs. Jimmy bot (600 ELO rated) at Chess.com

Huo Chess v0.992 vs. Jimmy Bot @ Chess.com [2021-03-22]

[Event “vs Computer”]
[Site “Chess.com”]
[Date “2021.03.22”]
[Round “?”]
[White “Huo_Chess”]
[Black “Jimmy”]
[Result “1-0”]
[TimeControl “-“]

1. g4 g5 2. Nc3 e5 3. e4 Ne7 4. Nf3 f6 5. Bb5 Ng8 6. Ba4 Nh6 7. d4 a6 8. dxe5 c6 9. exf6 Kf7 10. Nxg5+ Kg6 11. Ne6 Rg8 12. Nxd8 d6 13. Bxh6 Kxh6 14. Nf7+ Kg6 15. Nxd6 b5 16. Bb3 Bxd6 17. Bxg8 Bc5 18. Qf3 h6 19. Ne2 Bb6 20. Nc1 Bd8 21. c4 Bxf6 22. cxb5 cxb5 23. e5 Bxg4 24. Qxa8 Bxe5 25. Qe4+ Kf6 26. Qxg4 Ke7 27. Qe6+ Kd8 28. Qxe5 Nd7 29. Qd6 h5 30. Be6 Kc8 31. Qxd7+ Kb8 32. Qe8+ Kc7 33. Qxh5 Kb7 34. Bd5+ Ka7 35. Nb3 Kb8 36. Rd1 Kc7 37. Qg6 a5 38. Nxa5 b4 39. Qg4 Kb6 40. Qxb4+ Ka6 41. Nb3 Ka7 42. Qb7# 1-0

Game 3: Huo Chess v0.9921 vs Sven bot @ Chess.com (1100 ELO rated)

[Event “vs Computer”]
[Site “Chess.com”]
[Date “2021.03.26”]
[Round “?”]
[White “Huo_Chess”]
[Black “Sven”]
[Result “1/2-1/2”]
[TimeControl “-“]

Huo Chess v0.9921 vs Sven (1100) [2021-03-26]
1. g4 g6 2. Nc3 d5 3. Bh3 c6 4. d4 Nf6 5. Be3 h6 6. Bd2 Na6 7. Nf3 Nb8 8. Bf4 Nxg4 9. Rg1 h5 10. e4 Be6 11. exd5 cxd5 12. Ng5 Bh6 13. Nxe6 fxe6 14. Bxb8 Rxb8 15. Rh1 Bg7 16. Rb1 Qb6 17. Qd3 Rh6 18. Qd2 Ra8 19. Na4 Qd6 20. Nc5 b5 21. Nb7 Qa6 22. Nc5 Qd6 23. Nb7 Qa6 24. Nc5 Qxa2 25. Rd1 Qc4 26. b3 Qxd4 27. Qxd4 Bxd4 28. Rxd4 e5 29. Rxd5 b4 30. c4 Rh8 31. Ke2 Rh6 32. Kf1 Rh7 33. Ke1 Rf7 34. Nd3 Rg7 35. Nxb4 Kf7 36. Nc6 Kg8 37. Nxe5 Nh6 38. c5 g5 39. Nf3 Kh7 40. Nxg5+ Kg6 41. Ne6 Kf7 42. Nxg7 h4 43. Nh5 Ng8 44. Rd4 Rb8 45. b4 a5 46. bxa5 Rb1+ 47. Rd1 Rb7 48. c6 Rb8 49. Rd4 Rb2 50. Rxh4 e5 51. c7 Rc2 52. c8=Q Rxc8 53. Bxc8 Ke7 54. Ba6 Kd7 55. Re4 Ke6 56. f4 Kf5 57. Rxe5+ Kg6 58. Bd3+ Kf7 59. Bc4+ Kf8 60. Rf5+ Ke7 61. Bxg8 Kd7 62. Rd5+ Kc8 63. Rd1 Kb8 64. Ra1 Kc8 65. f5 Kc7 66. Rd1 Kc8 67. Rd2 Kb7 68. Rd8 Kc7 69. Rd1 Kc8 70. Ra1 Kc7 71. f6 Kd8 72. f7 Ke7 73. Rd1 Ke6 74. Rb1 Ke7 75. Ra1 Kf8 76. Nf4 Kg7 77. Nd3 Kf8 78. Nb2 Ke7 79. Rd1 Ke6 80. Na4 Ke7 81. Nb2 Ke6 82. Ra1 Ke7 83. Na4 Kf8 84. Nb6 Ke7 85. Rd1 Kf8 86. Na4 Ke7 87. Nb2 1/2-1/2

Game 4: Huo Chess v0.9921 vs Sven bot @ Chess.com (1100 ELO rated)

[Event “vs Computer”]
[Site “Chess.com”]
[Date “2021.04.02”]
[Round “?”]
[White “Huo_Chess”]
[Black “Sven”]
[Result “1-0”]
[TimeControl “-“]

Huo Chess v0.9921 vs Sven (1100) [2021-04-02]
1. g4 c6 2. Nc3 h6 3. d4 g6 4. Be3 Qc7 5. Qd2 Bg7 6. Bf4 Qd8 7. e4 Kf8 8. Bc4 Ke8 9. Nge2 Qb6 10. Na4 Qd8 11. Nc5 b6 12. Nb3 d6 13. Rg1 Kf8 14. h4 Qe8 15. Nbc1 Bd7 16. Nd3 a5 17. c3 h5 18. g5 a4 19. Qc1 b5 20. Bxb5 Ra5 21. Bc4 Bg4 22. b4 Ra8 23. Ng3 Qd8 24. Nf1 Bd7 25. Qa3 Bg4 26. Nb2 Rh7 27. Nxa4 Na6 28. Bxa6 Qc7 29. Nb2 Bh3 30. Nd2 Be6 31. Qa4 Ke8 32. Nd1 Qb6 33. b5 Bf8 34. Rh1 Bc8 35. Nc4 Qc7 36. b6 Rxa6 37. Nxd6+ exd6 38. Qxa6 Be7 39. Qa8 Qd7 40. Qb8 Kf8 41. c4 Qd8 42. b7 Bxb7 43. Qxb7 Ke8 44. Qxc6+ Kf8 45. Qa6 Qd7 46. Qa8+ Bd8 47. Qa3 Be7 48. Qa6 Qd8 49. Nb2 Qc7 50. Qa3 Qb6 51. Qa8+ Kg7 52. Rb1 Qxd4 53. Ke2 Qb6 54. Qd5 Rh8 55. Na4 Qc7 56. Ra1 Qc8 57. Qd4+ Kh7 58. Bxd6 Qe6 59. Bb8 Qc6 60. Be5 Ba3 61. Bxh8 Bf8 62. Nb2 Qc7 63. Nd1 Qe7 64. Nc3 Qc7 65. Nb5 Qb7 66. Na7 Qa8 67. Be5 Bb4 68. Rab1 Ba3 69. Rb8 Qxe4+ 70. Qxe4 Bc5 71. Nc6 Ba3 72. Rb7 Nh6 73. Qd3 Ng4 74. Qxa3 Nxf2 75. Rxf7+ Kg8 76. Qf8# 1-0 

Game 5: Huo Chess v0.9921 vs. Sven bot @ Chess.com (1100 ELO rating)

[Event “vs Computer”]
[Site “Chess.com”]
[Date “2021.04.07”]
[Round “?”]
[White “Huo_Chess”]
[Black “Sven”]
[Result “1-0”]
[TimeControl “-“]

1. g4 d5 2. Bg2 Be6 3. Nc3 c5 4. e3 Qd6 5. Qf3 Nf6 6. Bh3 b6 7. Nge2 a6 8. d3 Qe5 9. Nf4 g6 10. d4 cxd4 11. Na4 Nbd7 12. Rb1 Rg8 13. Bd2 b5 14. Nd3 Qe4 15. Qxe4 dxe4 16. Nac5 Nxc5 17. Nxc5 Bxa2 18. Ra1 dxe3 19. Bxe3 Nd7 20. Rxa2 Rd8 21. Rxa6 Nb8 22. Ra5 Nc6 23. Rxb5 Ne5 24. Nxe4 f6 25. Bb6 Ra8 26. Ra5 Rb8 27. Ra6 Bh6 28. Bc7 Rb7 29. Ra8+ Kf7 30. Rxg8 Rxc7 31. Rh8 Rxc2 32. Rxh7+ Bg7 33. Rf1 Rc6 34. Nc3 Rb6 35. Na4 Re6 36. g5 Rc6 37. Rg1 Nf3+ 38. Kf1 f5 39. Rg2 Kg8 40. Rg3 Nd4 41. Rh4 Rc2 42. b4 Be5 43. Re3 Rc1+ 44. Kg2 Nc6 45. Rh6 Bg7 46. Rxg6 Kh8 47. b5 f4 48. Re4 Nd4 49. b6 e5 50. Nb2 Kh7 51. Rd6 Nb3 52. Nc4 Ra1 53. Bf5+ Kg8 54. Nxe5 Nc5 55. Rd8+ Bf8 56. Rxf4 Kg7 57. Ng6 Ra4 58. Rf3 Be7 59. Nxe7 Rh4 60. Rd5 Ne4 61. Rd4 Nxg5 62. Rxh4 Kf7 63. Re3 Kf8 64. Re5 Kf7 65. b7 Nf3 66. Kxf3 Kf8 67. b8=Q+ Kg7 68. Qa8 Kf6 69. Qh8+ Kf7 70. Rh7# 1-0
Huo Chess v0.9921 vs Sven (1100) [2021-04-07]

More games to be uploaded soon with stronger opponents!

Exit mobile version
%%footer%%