Game of the Amazons
Fire burn!
Jun 15, 2019
Game of the Amazons is a lot like chess except all pieces cannot be killed, move like queens, and shoot fire arrows that also move like queens.
Ok, maybe it’s not like chess at all.
In short, Game of the Amazons pits two players on a grid with an equal number of pieces or “Amazons.” Each player takes turns moving their Amazon and firing an arrow from it, both actions functioning like the queen’s movement in vanilla chess. When an arrow is fired onto a square, the square “catches fire” and becomes a barrier, blocking future movement and arrow firings. The game goes until one of the players cannot move anymore of their Amazons.
I started getting interested in the game after watching a Numberphile video on it a while back. Mathematically, it seems to be a very interesting and difficult game to solve. I wanted to experiment around with something more than the toy example given in the video and started scouring the internet for a playable version. I must’ve been really shot in the head that day because I could not find anything other than Michael Keller’s version of the game for Windows 3. Getting that to run was an adventure all on its own (see Appendix A).
Disappointed at the relative lack of Amazons online, I did the only reasonble thing a bored college student would do: Write my own!
Design
My goal was to build something similar to Keller’s implementation. I wanted to make it easily accessible and experiment with learning React as well so making it in the browser was the natural choice.
I also knew I wanted to separate out my UI code and my game logic from the start. The Amazons game was going to be abstracted out into a set of possible actions that the UI code would interface the game with.
Starting React
Before this, my experience with React was next to none, so most of this was an uphill fight. I also wanted to make this solely a browser project which meant avoiding Node as much as possible. I ended up getting React as a CDN and started testing out some sample JSX… But hold up! The browser doesn’t understand JSX! A quick search taught me about the Babel compiler which among many things can apparently transform JSX into browser-compatible Javascript.
I did the Babel transformation in the browser which popped up a warning telling me to transform before serving in production. I ignored it at first but later in the project, I did some digging and found out I could compile and bundle JS using Webpack first and simply include a single, bundled script file. Of course this meant going back near Node since I was using npm again. However, it seemed that Webpack just transformed and bundled the scripts without involving anything server-side. I think my fears were mostly in wrongly associating Node with being exclusively linked to doing server work.
Anyways, with JSX working, I could finally go my merry way and get started.
Amazons Game Logic
Game logic was contained within a single class that would keep track of the state of the game and provide a set of interfacable actions for the game.
I split the functionality of the game into 3 different actions: choosing a piece, moving a piece, and firing an arrow. Each action would accomodate for the state of the game and alter the board accordingly, usually setting for the next action to take place. This scheme worked very well for player vs player games as it made every action easy to link to some event that happened on the UI side. However, as I started adding rudimentary AI later, I found it to be quite troublesome, needing to save the state of the Amazons instance as actions would directly alter the board.
I also needed a way of highlighting where the pieces could move and fire. Since they follow the movement rules of queens, I had thought to originally just highlight the 4 lines going through the piece. However, this presented a problem: I was unable to detect when a barrier was blocking movement. In the end, I switched over to doing a very watered-down raycast. Normally, raycast is something seen in graphics where, a vector is incrementally traveled along until it ends up within or on some mesh. Here, however, I simply needed to travel along the eight directions on the grid, stopping when I hit a barrier or the edge of the grid.
Wrapping Up
The rest of the project was mainly linking up the UI with the game logic, making sure users couldn’t pull off illegal moves and break the game. I also added some extra features like a board reset, a dialog that displayed the state of the game, and a log of player moves.
I also wanted to try adding AI but realized that it was its own can of worms. Moreover, the possible moves in Amazons is very large in the opening making the AI very slow as I tried to add in a heuristic. Perhaps with the advent of web assembly and more time, I could properly sit down and try to write something that would work and run reasonably fast but that’s for another time. For now, the AI option simply has the agent move randomly until the number of possible moves it can make thins down. At that point it switches over to greedily using the relative territory heuristic that tries to maximize square ownership.
Conclusion
In retrospect, doing this write-up and retracing my steps and thoughts, I feel like this was a project where a few things were done right but many could have been done better. For one, I severely underestimated the number of implementations of Amazons floating out there. I think a decent number of people got the same idea as me after watching the Numberphile video and set out to make their own versions. Additionally, instead of taking the path of least resistance, I ended up installing Windows 3 to play Amazons to begin with and then re-invented the wheel to make my own JS version. The journey itself was fun and I frankly learned a lot from simply finishing this project, but it’s also something that shows I should be more aware of my own naivities and perhaps do better reconnaissance before starting things.
On the other hand, this project was my gateway into a larger browser JS project along with learning more of the language and its accompanying resources. Amazons itself often served as a small reprieve from school. I would often boot-up my VM and play Keller’s implementation with the AI or friends.
Currently, the project is live here to play around with.
Appendix A: Fun with Windows
For some reason I was really intent on getting Michael Keller’s Game of the Amazons implementation up and running. The oldest Windows system I had ever used was XP so anything older was truly a mystery. Internet searches convinced me Keller’s game was supposed to run on Windows 3 (although it may have been fine on Windows 95).
Windows 3 runs on top of MS-DOS. At first, I got DOSBox but couldn’t figure how to install anything on top of it. The only other way I could think of to get Windows 3 was through a virtual machine. I created a new MS-DOS VM in VMware, but when I went to find images of MS-DOS and Windows 3, I found myself greeted with about 3 to 7 floppy disk images. Vintage. Turns out I can choose to add a floppy drive to my VM as well, so pretending to be from a bygone era, I loaded the images into my virtual floppy drive, switching them out when prompted to to obtain my version of MS-DOS. Then doing the same procedure, I installed Windows 3 on top of it.
How was I going to transfer my copy of Amazons to my VM though? I figured well since the floppy drive worked so well, why not just burn it on an floppy disk image like everything else and load it in? Sure enough it worked. Missing a DLL? Do the same thing and copy it to where it needed to go.
As someone who thought VHS tapes were ancient when I was young, seeing this kind of old tech was a little exciting. Floppy disks are only around half a century old at the time of this writing, so it really makes you think about how fast technology advances. We take a lot for granted these days too. First booting up Windows 3 after installation, I was asked if I wanted to know how a mouse worked. A mouse. Of course everyone knows how a mouse works! But not those who grew up on a terminal right? Windows 3 also had some different widgets on their windows. We’re mostly used to the standard minimize, expand, and exit widgets today but on Windows 3, I was trying to make heads and tails of these minus signs and up and down arrows!
I’m sure older developers are rolling their eyes as they read this, but that’s how I really felt. We treat a lot of technology as “duh” and “it’s always been this way” but the truth is that there were many prototypes and versions that came before our obvious standards today. It’s quite fascinating and also makes me slightly afraid that in the future, I will be one those people complaining how, “Yer new-fangled 3D desktop don’t make no sense! In my day, we had 2D windows” or something like that.
UPDATE 11/15/20: Update with new link to demo