Please sign in to access this page

Gideon's Chess Engine

Gideon's Chess Engine

9 devlogs
74h 8m
•  Ship certified
Created by Gideon

A bot capable of playing chess against humans

Timeline

Ship 1

0 payouts of shell 0 shells

Gideon

7 days ago

Gideon Covers 9 devlogs and 74h 8m

I spent some more time tweaking the search function in an effort to get it to compete with other engines and measure ELO. I also added a README.

Update attachment
Gideon
Gideon
18h 29m 19 days ago

Since the last devlog, I have implemented search in the engine. This means it is now capable of playing chess by making moves. Doing so required developing an evaluation function and search algorithim, making major modifications to the GUI and UCI interfaces, and doing extensive validation and benchmarking. I also extended the GUI to support using an opening book, which prevents the engine from playing the same opening every time, and implemented a number of new features in the UCI interface.

Subsequently, I created a web build of the UI and implemented a CI pipeline to build my UCI and GUI executables for all major platforms. I then extended my search functionality to use a transposition table, which caches results of previous searches, as well as iterative deepening, where it starts with a low depth search and grows from there. This allowed me to add time management, so the engine determines how deep to search depending on the amount of time on the clock.

As you may remember from my last attempt at building an engine, perft testing is a technique used to debug chess engines by counting the number of legal positions reachable from a given position up to a specified depth. Each position is called a node. My original engine could process around 900,000 nodes per seconds. I've now finished perft testing my new engine and–after a ton of debugging around weird edge cases–it processes an average of 92,128,420 nodes per second. That’s a 102x improvement.

I'm not sure exactly how long I spent on move generation during this vs. the previous attempt, but this version's move generation uses bitboards–64 bit integers where each bit represents a square–to store information about the chess board. This technique is much less intuitive than my old 64-length array approach, and requires a lot more specific knowledge of bitwise arithmetic and chess programming-specific algorithms, but results is much, much better performance.

Gideon
Gideon
12h 31m 28 days ago

Since my last devlog, I've realized that my engine's core had some problems, so I decided to embark on a full rewrite. Unfortunately, the old project was tightly coupled to the engine core's design, so I will need to rewrite a lot of the auxiliary software like perft testing and the GUI. However, I will try to reuse as much code as I can. I am keeping the core of the engine in C, but I am using C++ for the GUI so I can use imgui instead of nuklear. I've attached a screenshot of my new GUI. I'm working on move generation, and have already finished pawns, knights and the king. Next are sliding pieces.

Update attachment

Although I like the UCI interface, I realized it won't be very helpful when I share my project for Summer of Making, so I decided to put some time into improving my UI and making a web build. This took much longer than expected, but I now have a working web build of my new GUI.

I have now implemented a small program to connect my engine to UCI, which is a protocol for chess engines. This will allow me to use chess GUIs and make my engine into a Lichess bot.

I'm happy to report that my chess engine now fully understands the rules of chess. I implemented a program to run something call perft testing, which essentially has my engine generate the number of possible moves from a given position and compares the results with Stockfish. After a lot of tedious debugging, my engine's results match Stockfish's perfectly. The engine passes the perft test up to depth 5 from the starting position, and also from a position known as Kiwipete. While perft testing, I discovered and patched a number of bugs in the engine. Most of the bugs were related to special rules like castling and en passant.

Since my last devlog, I have update the engine to support move generation for all of the pieces, and I have added castling. I also made a few tweaks to the UI.

I started my project by researching and experimenting with numerous chess programming methods for representing boards, generating moves, etc. I also tested out a few different UI frameworks. I originally started the project in Go with Ebiten, but have pivoted to C99 with Raylib. So far, I've built a UI capable of displaying the chess pieces on the board and executing moves. My engine is rudimentary, but the internals are solid. It is capable of representing all valid positions and moves, and can currently generate moves for pawns. I have yet to implement en passant. This is an exciting project, although I had a slow start. I look forward to working on it.