Week 3: Too Much To Check
March 24, 2023
“Even the laziest King flees wildly in the face of a double check!” -Aron Nimzowitsch
Welcome back to my blog! As you might have started to notice, I like to begin each post with some words of wisdom. To be honest, I don’t even know how useful they are. But they sound cool. And the one today is (kinda) relevant to what I have been working on! Anyways, let’s get started with what I did this week.
- Setting Up A Working Chess Board
- Debugging The System
- Implementing The Legal Move Checker
- Plans For Next Week
Setting Up The Chess Board
The Basic Framework
Last week, I talked about all the challenges and subtle implementation details I will need to take care of. I did do a bit more searching on the internet for coded chess boards, but I couldn’t find any that had everything I wanted. So, that meant more coding for me, yay (no, I’m not actually elated)! Luckily though, I realized that Marcel Jurtz, the person who explained the code on the website I’m using, also has a Github repository for the implementation. That is actually pretty useful, because in case something goes wrong in my version as I follow along his explanations, I can always refer to the complete code.
Anyways, as I said last time, before I start working on the special moves, I need to make sure I have a working chess board. That way, I will be able to test everything as I go. I decided to scrap the code for setting up the board that came with the 3D chess board asset I am using and just use Jurtz’s implementation. I worked with his BoardManager script, which has all the basic functionality, such as setting up the board, selecting squares, and moving pieces. Although I had to make some *minor changes* to the code so that it’s more understandable and reflects my implementation preferences, I was able to keep most of the original code. Yay! Less work for me. However, let me briefly go over some of Jurtz’s key implementation points.
Creating The Board
Jurtz actually had a pretty smart idea of using a self-drawn grid. Basically, instead of fitting the code to a specific chess board asset, it would be better to draw an 8-by-8 grid through code and use that as the “board” instead. This would help with setting the positions of the chess pieces, and in case I ever want to use a different 3D chess board model, I can easily switch it out. Here’s a picture of what it looks like:
It’s just a simple 8-by-8 grid drawn using Unity’s Debug.DrawLine function. The cube at the bottom lefthand corner is for size reference. Right now, the grid is actually too big, but this is one of the advantages of using a self-drawn grid: I can adjust the size accurately through code while maintaining the relative positioning of the pieces. I will go more into this when I actually start working on it because a bit more change is necessary, but trust me, this makes my life easier in the long run.
Placing Pieces
Now, after the board is drawn, I can place the chess pieces in their respective positions. Jurtz created a very useful method for converting between grid coordinates and world coordinates, so instead of working with nasty floating point values, I can just treat the pieces as if they are in an 8-by-8 2D grid. Perfect! Now, after hardcoding each piece to their correct positions, the chess board is all set up!
The last basic feature is to include a way of indicating which square/piece the mouse is currently hovering over. Again, Jurtz already had code for doing that. He puts an ‘X’ on the targeted square. For this to work, however, I actually had to put a transparent cube under the grid because the self-drawn grid doesn’t register as a gameobject when using Raycast. After everything is done, I will be replacing the transparent layer with the actual chessboard, of course. Here’s what the final board setup looks like:
Moving Pieces
Jurtz broke down moving pieces into two steps: selecting the piece and then actually moving it. Internally, all pieces are indeed stored inside a 2D array, which helps simplify implementation. When the user clicks the mouse, the program will convert the screen position coordinates to grid coordinates. Then, if there is a piece at that location, it becomes “selected” and returns the 2D array of possible moves. This feature was implemented last week. After that, if the user selects an empty square that is reachable, the piece will move.
This system is just temporary. In the final project, the user won’t have a mouse, so I need to come up with another way for them to move pieces. I will ask my mentor for suggestions on how to do this after I finish creating the board. For now though, having a mouse-based movement system is very useful for testing.
Board Highlighting
The last bit of code I used from Jurtz is a board highlighter. This is a separate script from the BoardManager but is called inside it. Basically, what it does is that it highlights all the legal moves once the user selects a piece. I won’t be going into the implementation details for this one (I might also change it up from the original code), but it’s incredibly useful for making sure that all my pieces are moving properly. Here’s a screenshot of what it looks like:
You can see that all the possible moves for the Black Queen are highlighted! Now, I can finally go talk about how I resolved the special case scenarios, right? Sadly, no.
Debugging The System
Remember how I talked about the *minor changes* I made to Jurtz’s code? Well, that “minor” change turned out to be not so minor after all. Jurtz used X and Y for the 2D grid coordinates, but I prefer to use R and C. Because of that, I had to make literally dozens of adjustments throughout the code to convert between X/Y and R/C. Let me explain why.
In 2D arrays, the cell at the top lefthand corner has index [0, 0]. That’s why I prefer to use row/column, because it makes more sense for 2D grids. However, Unity uses the Cartesian coordinate system, where the cell at the bottom lefthand corner has index [0, 0]. That means not only do I have to convert Jurtz’s code from X/Y to R/C (which isn’t difficult, just annoying), I also need to convert everything back to X/Y when moving the 3D pieces in Unity. It took a while for me to debug everything, but I promise you, it’s all working (for now).
Implementing The Legal Move Checker
Surprisingly, I did actually have time to start implementing the special case scenarios. I chose to start with the checks, not because it’s the easiest, but because it’s quite necessary, as checks occur very frequently in chess. For those of you who don’t play chess, I’ll quickly summarize the rule:
If your king is in check, that means one of your opponent’s pieces is attacking your king (aka it has a legal move that reaches your king’s square). Thus you must play a move that will get your king out of check, either by moving the king, blocking, or capturing the attacking piece. In addition, even if your king is currently not in check, you can’t play a move that will cause your king to be in check.
Thus, for every “possible move” that a piece has, I would then need to double *check* it, making sure that it doesn’t leave the king in check. If it does, then that move is not legal. The idea is simple, but it was difficult coming up with a clean, efficient way of implementing it. Luckily, I did find a good way. Thus, I starting writing my own LegalMoveManager script.
The Algorithm
Here’s the idea: whenever the user selects a piece, the program returns a 2D array of possible moves (not accounting for checks). I will then loop through all these possible moves and “make the move.” The position will update internally, but I won’t be moving the actual 3D figures. Then, the new position (after the move is “played”) will be passed to the LegalMoveManager, which examines for checks. If a check exists, that means the move “played” is not valid, and I will unmark it as a legal move. After the LegalMoveManager is finished, the position will be reset back to the original, before the move was “played.” This is much more efficient than creating a copy of the position every time.
However, now the question is, how would the LegalMoveManager script check for checks? My initial thought was to go through all the opponent’s possible moves and see if they attack the king. However, this is really inefficient. Instead though, I decided to invert the approach. Rather than checking from all the opponent’s pieces, I find where the king is located and starting checking from there. If the king is located at coordinate [R, C], then from where can it be attacked?
I check the diagonals: if there is an enemy Queen or Bishop (the two pieces that can move long distances diagonally), then the king is in check. I check the rows and columns: if there is an enemy Queen or Rook (the two pieces that can move long distance horizontally or vertically), then the king is in check. The same thing goes for the L-movements (the Knight), the immediately adjacent diagonals (the Pawn and King), and the immediately adjacent squares in the horizontal and vertical directions (the King).
Demo
Sorry if that was very confusing, but I was able to implement all that, and luckily, it worked! Here’s an illustration of what it looks like:
In this position, it is White to move, and currently, the White King is in “check,” since it is being attacked by the Black Queen. I have selected the White Pawn on f2, and normally, the pawn should have 2 legal moves: one step forward or two steps forward. However, only the two-step-forward move is being highlighted, which indicates that the script is working. If the pawn only moves one step forward, then the Queen will still be attacking the King. However, if the pawn moves two steps forward, then it is in the way of the Queen attacking the King (aka “blocking”). Thus, only the two-steps-forward move is legal, which is what my code correctly indicates.
In the same position, the White King can be selected as well. Normally, it would have 5 legal moves, yet both the Black Queen and Black Bishop are covering some of those squares. My script correctly indicates that, and shows that after taking checks into account, the White King would only have 2 legal squares where it will be safe from checks.
Plans For Next Week
All right that was a lot of explaining on my part today. It’s okay if not everything I said made sense, but I hope the images can describe it all. Anyways, I checked the timeline I made for this project, and it seems like I’m ahead of schedule in terms of progress. Yay! Next week, I will start implementing the remaining special moves (castle, en passant, promotion), and after that’s all done, I will finally transfer over the code portion I wrote for my Capstone CS class.
Sorry, this post is a bit long, but I hope you enjoyed it!!! That’s all for today, and I’ll see you again next week for more updates on my project!
References
- Jurtz, Marcel. “Building A Chess Game In Unity.” Medium, Medium, 12 Sept. 2018, Https://Jurtzmarcel.Medium.Com/Building-A-Chess-Game-In-Unity-85408f86b749.
- Jurtz, Marcel. “Marceljurtz/Chess: Chessgame Made In Unity.” GitHub, Https://Github.Com/MarcelJurtz/Chess.