Hello everyone

As mentioned in the previous post, I have started in a new direction for our chess engine. If the program is to think like a human then we must first look at how a human plays the game. Now I am not the best chess player in the world, in fact I consider myself to be slightly less than an average club player, but as part of the research of this program I have played and reviewed hundreds of chess games from both masters and amateurs alike. What I have been able to determine is the best players all seem to work three strategies at the same time.

Control

Offense

Defense

Control

A player exerts control on the game by protecting key squares on the board, threatening the opponents piece, sacrifice’s, forcing the opponent to move pieces where you want them and by winning exchanges.

Offense

Attacking is more than just exchanging pieces, the player must have an idea of if the attack gives them the advantage. For example if the players Queen attacks an opponents pawn then the opponent attacks the queen, that is not a good move on the part of the player because the Queen has a greater value than the pawn. If the reverse is true where the pawn attacks the opponents Queen, it a great move even if the pawn is captured. Typically attacks are done in chains forcing the opponent to exchange pieces or to retreat. Both scenario’s give the advantage to the player.

Defense

As with offense, good defense is more than just protecting a piece on the board. The good player decides if a threatened piece is worth saving or should it be sacrificed? For example, you have a piece on the board which is threatened and in a chain exchange you know your opponent will come out on top. The good player looks at the vacated square of the threatening piece to see if it opens a vulnerability in the opponents defense. If it does, moving a piece to attack that vulnerability may force the opponent to rethink the attack. There is a lot to think of for each move in a chess game. The good players do this well and balance all strategies of their game, others find their rating based on where they put the most emphasis in their game play.

Now when it comes to planning moves ahead, in chess many moves are straight forward and do not require much future thought. Typically this comes into play when chaining attacks, forcing the opponent to move where you want and at the end of the game.

So now we know what we wish to program to do, so lets look at how I intend to accomplish it.

Analyze Move table.

Move analysis table                                                               (click image for larger view!)

In the image above the table represents all current values at the start of a new game. Initially black will use the open book to determine the best moves then it will switch to thinking and making the best move on it’s logic. That logic will come from this table. To make a decision, black will need to parse through the table and analyze each of program factors;

  • All Available Moves.
  • What moves will result in Black’s capture.
  • Where can Black Attack?
  • Where must Black Defend ?
  • Who wins in an exchange?
  • Is Blacks King in Check?
  • The Value of the Move.
  • The Mobility of all player pieces on the  board.
  • Whites current score.
  • Blacks current score.

To parse through the table we will use the table open method and assign all tracking values to local variables which then can be analyzed using string comparisons. If we were to do a table open for each value needed, the game would bog down. By making one pass through the table the process is fast and the variable analysis takes place in upper memory which is very fast. Our code will look something like this.

dim rcnt as N
dim WHSquares as C
dim WAttackSqs as C
dim BHSquares as C
dim BAttackSqs as C
WHSquares = ""
WAttackSqs = ""
BHSquares = ""
BAttackSqs = ""
t = table.open("an_move")
t.fetch_first()
while .not. t.fetch_eof()
    if Alltrim(t.WAttack) = ""
    
    else
    WAttackSqs = comma_to_crlf(t.wattack)
    for each xap in WattackSqs
        WHSquares = WHSquares + alltrim(t.sq)+":"+ xap+":"+if(Word(xap,1,":",1)="W Pawn",1,if(Word(xap,1,":",1) = "W Rook",3.75,if(Word(xap,1,":",1) = "W Knight",3.25,if(Word(xap,1,":",1) = "W Bishop",3.5,if(Word(xap,1,":",1) = "White Queen",7.25,0)))))+crlf()
    Next    
    end if    
    if Alltrim(t.BAttack) = ""
    
    else
    BAttackSqs = comma_to_crlf(t.battack)
    for each yap in BattackSqs
        BHSquares = BHSquares + alltrim(t.sq)+":"+ yap+":"+if(Word(yap,1,":",1)="B Pawn",-1,if(Word(yap,1,":",1) = "B Rook",-3.75,if(Word(yap,1,":",1) = "B Knight",-3.25,if(Word(yap,1,":",1) = "B Bishop",-3.5,if(Word(yap,1,":",1) = "Black Queen",-7.25,0)))))+crlf()
    Next    
    end if    
t.fetch_next()
end while
t.close()

This code snippet only builds a list of white and blacks attack squares which looks like this

Attack Squares

Even though it is Blacks move, we look at white’s squares as well so we can compare the result of each possible move. This example looks at the fields WAttack and BAttack and converts the values to a list sorted by square. The list also shows the value of each piece to be moved to the right of the piece. These two list tell us a lot. We know if white and black can both move to the same square and if so who will win the exchange. We know which of blacks moves will be protected which will be put in danger. Now the system can decide which move makes the most sense just like a human. To determine if any of blacks current pieces are under threat of attack we would add the following code to our table open method

t = table.open("an_move")
t.fetch_first()
while .not. t.fetch_eof()
if *any(t.WMoves, t.BFrom) = .t. then
     dangerlist = dangerlist + t.BFrom +crlf()
end if
t.fetch_next()
end while
t.close()

Note: The purple code would be added to the table open method above so that the table is only opened once.

Once we have built all necessary list we then only need an if statement to determine the value of each move. Those values would then be written back to our table. The final step is to make the actual move which is done once we know the best move.

tablemin("an_move",".t.","BVal")

gives us our best move value. We then fetch that record and assign the piece to move and where to move it to using our table fields

BFrom

BTo

I am using tablemin because blacks value is represented in the negative and we want the largest negative number for our move.

Well that’s it for today’s session. The next session will look at the final code needed which is the actual algorithm that makes the computer think. Stay tuned.

Thanks again for stopping by and Remember, if you need help with an Alpha Software application or wish to inquire about a custom application for your business go to our website

www.cdc-takecharge.com

and inquire or contact

NLawson@cdc-TakeCharge.com

Have a great day.