Back to projects
Apr 17, 2020
5 min read

Chess

First attempts at a chess engine.

Goal - to build a rudimentary chess engine that can take any board position, examine all legal moves and rank them to find the best single move.

Chess

Status

Current status : game engine built, most moves implemented, still need to implement castling and en passant. I added both text output and also a simple GUI to watch the game and spot strange moves while debugging.

From there I plan to extend it to multiple levels - but I’m already wondering about how that works. If I have move A and then move B is brilliant … I still have to account for my opponents move, and if they don’t do what I want, does that mean move B is no longer possible ? At which point I should have tried a second move, move C ?

Ranking moves

Initially, I was calculating all possible moves for each piece on a side, with values based on if they were (a) taking another piece, and then (b) threatening another piece. But that doesn’t pick up checks, or the fact that by moving the piece, I’ve exposed them to be taken by another piece.

Instead, I need to be able to calculate a value for the board. I need to calculate some sort of value for a given board, that will include :

  • what pieces I still have - these must be valuable
  • what pieces I am threatening - less valuable.

That’s for my side; and then I do the same for the other side, only this will be a negative. I then make the move and repeat the process.

So if I have my first value X, and make the move which takes a pawn from the other side, Y should be more - I will subtract less. If my move threatens a piece, that should increase it’s value; but if it exposes itself or another piece, that will reduce.

Obviously being in check is a special case as I MUST resolve that : if I was in check before, I should only count the boards where I am no longer in check.

What I don’t know yet it is how to value the threats. If I take a pawn (1 point), should that be more, less, or the same than exposing my knight (3) ? Probably less : the value of a threat is the same as the potential loss.

Rewrite to simple string based approach

I have written it in a very object-orientated and powerful way, where a game has a board, a board has two sides, each side has pieces and each piece has potential moves. I’ve now got stuck when planning for future moves, and needing to move a piece and recalculate it’s moves; and have to undo the move and recalculate again.

Picking up from the previous exploration, I’ve rewritten it with a much more static/string based approach - instead of a complex (but powerful) set of objects, I have a single Board object which includes a 64 char string (8 ranks x 8 files) that holds the board state; this makes it much easier to clone and update a single move to evaluate it’s options.

I’ve added in Promotion of pawns to Queens if they reach the far side; and I make sure that the king will move out of check if possible (or a piece can jump in to block it.) I’ve also tested that a piece will block a check if needed.

I’m only evaluating moves on the number and value of pieces made after the move; I’m not yet evaluating them based on attacking moves (e.g. a move that puts a pawn in a position to attack another piece should be worth more than just moving into space.) (Unless it’s strategically valuable space, like the middle of the board, or stopping the opponent moving to an advantageous position for them) and that’s going to be hard to calculate.) I’m also not evaluating protecting other pieces.

Results

Stalemate too many moves : 145
Stalemate repeat moves : 15
Stalemate only Kings : 691
Black wins : 84
White wins : 65

Average (completed) game length = 70753/855 = 83

Only 149 wins in 1000 games : 145 times I hit 1000 moves and gave up as uncompleted; the majority of games end up with each side only having a King. That’s not expected.

At this point, the bar closed.