Inspiration
We both like chess, regardless of how terrible we may be, but it doesn't stop us from playing. Making a bot that plays better than the both of us wouldn't be hard to do. Starting off, most beginner chess bots are pretty simplistic because they only count raw points of the pieces on the board at a given time. A queen is always worth nine and a pawn is always one, but in real chess, where your pieces actually stand matters much more than just the material count. Leaving your king out in the open during the opening gets you crushed, but marching your king to the center in the endgame can win you the game. We wanted to build an engine that actually understands that difference and adapts its strategy as pieces disappear from the board, then see how long it could survive against Stockfish.
What it does
Vacuous is a terminal chess engine that lets you play locally against a friend, challenge our custom bot, play against Stockfish, or sit back and watch our bot fight Stockfish in real time. Instead of using a fixed evaluation, it calculates how far along the game is and smoothly blends between opening and endgame piece values (+/- grids for each type of piece). It also handles move inputs cleanly whether you type algebraic notation like e4 or raw coordinates like e2e4, and flips the board orientation automatically so both players can see what they are doing.
How we built it
We wrote everything in Python and used the python-chess library to handle basic board state and legal moves. The decision-making is powered by a minimax algorithm with alpha-beta pruning so it skips bad move branches and runs fast at a depth of 2. We utilized 64-square tables (courtesy of Gemini for the general strategy and explanations) for every piece type across two phases: early game and endgame. As the board clears, a lerp function alternates between the two tables so the bot naturally stops hiding its king and starts aggressively pushing pawns to promote toward the end. We also hooked into the official Stockfish executable using the UCI protocol so we could benchmark our bot against a grandmaster engine.
Challenges we ran into
We ran into a few roadblocks, especially with coordinate math. Because White and Black have separate point values (+ on one side / - on the other), we ended up with a couple logic errors like a negative value being miscounted as a good thing when playing as white, and vice versa, but it was quickly patched over with just a single negative sign being removed from our checkmate points function (99999).
Accomplishments that we're proud of
Getting the beginning stages working was the biggest hurdle, but watching the bot seamlessly switch from defensive castling to holding its own against the best chess engine in the world with only a depth of 2.
What we learned
We gained a much deeper appreciation for game tree search through minimax and just how useful it can be for game theory. We also learned more about abstract chess strategy like king activity and pawn structure into raw numerical values, and how it connects back to the overarching theme of planning ahead. Our bot in the video attached managed to last around 5 minutes trading blows with Stockfish, so it already plays better than the both of us combined.
What's next for Vacuous: Minimax Chess Bot
We want to implement more edge cases and smaller tactical nuance situational awareness, so it can play even fluidly, and eventually putting together a simple visual board interface instead of living in the terminal with Unicode symbols.
Log in or sign up for Devpost to join the conversation.