How I made (and got beaten by) a Chess playing bot.
Chess is one of the most insane games on the planet.
Really — we’ve become so used to it that we sometimes forget just how absurd it is.
A horse jumping over soldiers? A psychotic, all-killing queen? And a rook that somehow can’t kill anything that’s literally one 1 square diagonally from it? (whoever made that last one — do you like causing misery 😢)
However, despite its objective insanity, it’s still fun as hell to play. Except of course, when you play a 2-hour game and end up losing…to your 10 year old sister. Better luck next time!
On a quest to get better at the game (and not get utterly destroyed), I had an epiphany. I might not be able to play chess if my life depended on it. But, I could build something that can.
So, in the spirit of a true developer, I slammed together code and AI to make a chess-playing AI — which, mind you, is still better at playing chess than I am. 😁
And, here’s how I did it.
How to make a Chess-destroying AI overlord
Okay, maybe that title was a little exaggerated.
But, the point remains the same. In total, there are 4 steps that we need to take to get this AI from the “I’m a figment of your imagination” stage, to the “My AI is genuinely a force of nature” stage.
So, let’s get to it!
Step 1 - Scoring the Chess Board
As any great philosopher (or anyone with common sense) would say:
“To play chess, you must first have a board to play chess on…and hopefully some pieces.”
Abiding by this axiom, we first need some way to make + analyze moves on a chess board…virtually.
It would take WAY too long to build something like that from scratch. Think about it — we’d need to program checkmates, track different moves, handle obscure castling and edge cases, and who knows what else. So, we’ll be using python’s open-source chess engine to give us a head start.
Ultimately, this lets us focus on the AI part of our chess AI!
But, there’s a problem. Even if we can play chess virtually, how would the AI actually make a move? And, an even more important question — how would it make a good move?
Let’s take a step back. What even is a “good” move? Does it mean taking a piece? Moving the most spaces? We can’t get an AI to make good moves, if we can’t define what makes a move good.
Luckily for us, chess is a closed game — criteria we make for one game would likely apply to all games. Let’s list some:
- Protecting valuable pieces from future harm (throwback to me sacrificing a queen for a pawn)
- Advancing your pieces closer to the opposing side (while maintaining the safety of your own pieces)
- Threatening the other side’s pieces as much as possible (even if they take one of your pieces, you should be able to take theirs in return)
Luckily, we don’t need to worry about all these different points. We can combine all these different metrics into one, quantifiable score using the stockfish grader — an engine that analyzes each move on the board and returns a score.
If the move has a positive score, that means that it was better for white. And, a negative score means that the move benefited black. The further the scores are from 0, the greater the advantage for the respective side.
Here’s an example:
As you can see, this….is kind of a bad move (black really needs to step up their game 😅).
Really, moving the king isn’t useful or productive. It doesn’t really add pressure on any piece, and kind of just moves for the sake of moving. Outraged by the sheer uselessness of this move, the grader gives white a whopping 1909!
Now, here’s an example of black making a not-outright-stupid move:
In this case, black moves the rook back to a8 — moving it out of danger and receiving a score of -597.
(Though it could probably have been in a more tactical position by taking the pawn at a2, or taking white’s rook at b5, or the knight at h3…I’ll stop ranting about chess now lol).
Now that we’ve found a good way to quantify our moves (because machines like numbers), we now need an algorithm that can look at our board and actually evaluate our moves!
If only there was an algorithm that could “see” things like a human, pick up visual trends, scan images like you’re scanning these words, and turn them into predictions…oh wait.
Step 2 - Making the CNN (not the reporting station)
CNNs (convolutional neural networks) are perfect for this problem — they can process visual data, and extract valuable insights that we can use for our chess bot.
Note — for the sake of length, I won’t be going too in depth on how CNN’s work. If you want to learn more, check out this article.
In a nutshell, here’s what a CNN does:
- Takes in image/spatial data (any data that’s related by space — for example, pixels need to be in a certain space relative to each other for the image to make sense!)
- Converts the input to a matrix
- Applies “filters” to detect patterns
- Processes those patterns numerically (this is where the patterns turn into our output!)
- Gives us our output! (in this case, we want a score evaluating any given move)
But…what do we input?
Well, here comes a slightly complicated part. Instead of just taking screenshots of the computer (which can go wrong for a dozen different reasons), we’ll instead convert the board to a series of arrays.
(This might be a little confusing at first, but stick with me.)
A single board will be split into a series of 14 arrays — each with an 8 x 8 array inside of it (array inception? 😮)
Basically, the first 6 arrays each represent the locations of different pieces on the board. If the piece in question is on the board, that position is marked by 1. And if it isn’t, it’s left as a 0. Let’s consider the following board:
As we can see, we have 6 pawns (both white and black). Now, here’s one of the 14 arrays that corresponds to all the pawns on the board:
As you can see, it’s basically just translating pieces from the board into an array!
We repeat this for all different pieces on the board (for both the black and white sides). Then, we add 2 more arrays — one for all of the black pieces, and another for all the white ones.
The result? A damn good map of where all the pieces are! Now, the model can train in piece (see what I did there? 😁).
Jokes aside, see why this is better than screenshots? The model has a detailed map of where every piece is at any given time, and can now use this additional information to make better predictions.
And that’s pretty much it! Now, all we need is to train our model, and we’ll be all set!
Well…no. See, our model doesn’t actually make moves. It evaluates them. Basically, it checks whether a move is actually worth taking. But, for it to evaluate different moves, we need something that will give us all possible moves.
Confused? Think about it this way.
Pretend you’re a train inspector. Your job? To look at each nut and bolt on the train, to make sure that they…you know, actually stay intact.
And after you’re done, you move on to the next train. You don’t actually sit down to drive each one of the trains in the station! (Unless of course, you have 200 hours in a day, and more energy than the universe combined.)
The point is — our model is the inspector, not the conductor. We need something that can give us the trains, and then get our inspector to evaluate the best one.
And that, dear reader, is where the minimax algorithm comes in.
Step 3 - Miniature Maximization of Minuscule Maximum Minimum Functions
(say that 3 times fast)
Minimax! Every game-AI programmer’s best friend. If our CNN is like a specialist, minimax is like a jack of all trades — capable of giving us a lot of results quickly, drawing on multiple specialists to give us valuable insights.
Let’s look at how a game works. If in a two-player scenario, chances are you’re trying to maximize your own chances of winning on your turn.
On the other hand, the other player is trying to minimize your chances of winning on their turn.
So, the (conveniently named) minimax algorithm is basically just a huge binary tree — each branch splits into two other branches.
These branches each have a score — and it’s minimax’s job to find the maximum and minimum score for each branch, alternating for each level.
Let’s say you have this minimax tree:
First, minimax is going to start from the bottom (I think it likes Drake). For every two “leaves” (the circle things at the bottom), minimax is going to choose the minimum (smallest) number per leaf, and move it up to level 3.
(Don’t get confused by the max and min labelling — it’s just trying to explain how we got the numbers of that particular layer.)
So in this case, we got layer three by taking the min of layer 4!
We then take the maximum of layer 3 to get layer 2, the minimum of layer 2 to get layer 1, and keep going until we finally have one number standing. (this is literally battle royale with numbers)
And that, is what minimax does! For our chess AI, we’re going to use it to pick the best move out of a sea of different possibilities. But, minimax can’t rank moves if they don’t have a score — which is exactly where our CNN comes in.
Now that we have all the pieces of the puzzle, here’s what our final algorithm looks like:
BOOM! We’re done most of the work. Now, we need to train our model so that it…you know, actually works.
And, after a couple of hours, we’ve gotten the loss down to ~0.0003 — not bad! We could probably get it lower, but after a certain point the network stops learning anything useful.
Instead, let’s get to the fun stuff — playing against our AI!!!
Step 4 - Getting beaten by my own creation
Luckily for us, this is pretty easy. All we need to do is take a board, send it to our CNN and minimax, extract the move, and execute it!
Unfortunately, python’s chess engine gives us the chess board in random letters, instead of…actual pieces:
I don’t know about you, but I actually want to see the move I’m making. So, we’re going to make our own board using python display-chess instead! Cool, right?
And…we’re done! After coding a small set of prompts (the AI will taunt you if you lose), here’s what the final project looks like:
Needless to say, my AI probably isn’t going to lose anytime soon (though, it does still make some rather interesting moves 😁)
Now- it’s time to practice! (and stop getting humiliated in chess)
I hope you guys enjoyed this breakdown! I’m Aditya Dewan, and I’m a 15-year-old AI enthusiast looking to solve the world’s biggest problems. If you want more breakdowns, like and follow for more! 😉
Code for this article: https://github.com/thetechdude124/ChessAI — thanks so much to DigitalSecrets for providing the tutorial for this concept!
More about me: www.adityadewan.com
Thanks for sticking around, and stay tuned for more articles!