With us both being avid chess fans, we wanted to integrate the game into our project in some way. Before we came up with this idea, we considered several plans involving online chess APIs, and a variety of hardware we brought. When we were given our Rubik's cubes from the Jane Street stall, however, we had this idea to implement a game of chess, but where the board wraps around a working Rubik's cube! This idea seemed to have promising gameplay mechanics: bishops travelling over corners of the cube can effectively fork into one of two paths; threatened kings can rotate the ground that their enemies stand on to divert them away; and pawns could promote by travelling over an edge, to name a few possibilities.
What it does
It's "simply" a game of chess, but if your pieces moved over the exterior of a Rubik's cube. The size of the Rubik's cube is arbitrary: we're playtesting mainly with a size of 7x7x7 tiles, but this can be easily changed to try out different ways of playing the game. Allowing the players to, as a move, rotate slices of the Rubik's cube introduces a really interesting gameplay mechanic. It also makes certain types of move very complex to see without a decent amount of experience playing the game. This way, it doesn't get boring very easily. To win the game, take the opponents king! There is no check/checkmate, as in a good few types of chess variant. It's quite hectic, bishops can take kings from the other side of the board, in some cases.
How we built it
For the 3D rendering, we used Python bindings of a library called Raylib. This library is originally for C, but has a lot of bindings available. We chose Python for speed of writing code, however in hindsight C++ may have been a better choice in some aspects. Python did work well, but the lack of a solid type system made bugs a lot more common. The Rubik's cube itself is represented as an object of our very own data structure. This data structure allows us to access negative indices and indices greater than the size of one face of the cube, and internally translates the access to the correct face. This made the actual implementation of the logic easier than it could've been, but the data structure itself took a lot of effort to design. We split up the work into various parts between us. While one of us worked on the aforementioned data structure, the other used this data structure to implement the rotating of the cube. We were able to do these simultaneously because we defined an API that the data structure would use beforehand. The collaboration was all done using Git. This allowed us to efficiently work on the same codebase at the same time. Despite writing the game in Python, we didn't shy away from lower level graphics programming at the same time. We make use of a lot of shaders that we wrote in GLSL, for example, and make use of Raylib's direct C api.
Challenges we ran into
This project ended up being significantly more complicated than it seemed at face value. Choosing a representation for the Rubik's cube was difficult, and implementing it was even harder. After some later research, it turned out this is a commonly encountered difficult problem. Having physical Rubik's cubes certainly helped in the visualisation of the algorithms, but it was still tricky to understand exactly what should be happening. In addition to this, several unexpected problems arose. Firstly, unlike a normal computer Rubik's cube simulation, we needed a way to, given a point on the cube and a direction, continue in this direction wrapping around the edges of the cube for as long as needed. This involved a huge amount of edge cases that had to be accounted for, since the 2D array representation of each face cannot be aligned with every other face, by the very nature of a cube. In fact, a very common theme during our development was edge cases and lookup tables to account for these. This also came about in our algorithm for rotating a Rubik's cube along a specific slice. And remember, all of these algorithms had to work for any arbitrarily sized cube. There was no possibility for hardcoding rotations, etc. The hard work paid off, though. Once we'd finished developing the basic framework for our Rubik's cube, we could start programming the chess logic a lot easier than it would have been otherwise. This wasn't without problems though. It's unsurprisingly not trivial to calculate the path of various chess pieces around a complex shape such as this Rubik's cube. It's hard to stress how much more complex this turned out to be than initially expected.
Accomplishments that we're proud of
We're very proud of how polished this game looks. We think it looks like a game that you could feasibly find for sale to play online. The animations in the game (for example when the game begins and the cube drifts into view, followed by the pieces shooting towards it) looks very professional. We're also really glad that, despite the fact that the game involved a lot more complexity than we imagined, we managed to make a not only working, but enjoyable game to play.
What we learned
Rubik's cubes are hard to represent in a programming language :) Also for both of us, this was our first project in raylib save for basic drawing squares and text and such. It's a really enjoyable library to use. Learning to use an entire graphics library in 24 hours, in addition to making this game, seemed to be quite a good way of doing it.
What's next for Rotochess
We have a lot planned. We want to experiment with some non-traditional chess pieces, like perhaps a "Mole" that can tunnel through the center of the cube, or more classic non-traditional pieces looked the elephant or the knook! We also want to implement a networked multiplayer version of this game. We don't live near each other, so this would be the only way to play it together. We do think that this game has the potential to be popular online. If we built it for use on a website, it could have an inbuilt matchmaking system, for example.
Log in or sign up for Devpost to join the conversation.