Monday, April 12, 2021

The difference a decade makes: Revisiting Morgan's Raid

In summer 2011, my team released Morgan's Raid, an educational game about Indiana's Civil War history. I wrote about it in the early days of this blog, and my post about our use of entity component system architecture remains one of the most visited pages here. The game won the Indiana Historical Society's Outstanding Project Award the year it released, and my collaborator Ronald Morris featured the game in teacher in-service trainings. We wrote papers and a book chapter about it, gave several internal and external presentations, and even adapted it to be playable in Indiana's juvenile detention facility. 

Unfortunately, it has been unplayable for several years. We built the game atop Java Web Start technology, which was deprecated with the release of Java 9 in 2017. Once it became clear that it was beyond the scope of teachers and IT staff to configure machines that would run the game, we took the Web site down, as we did not want to mislead teachers.

Recently, I have been investigating sources of funding to revitalize Morgan's Raid, and I have a few grant proposals currently under review. My evaluation is that the work is beyond the scope of what I can do in an existing course. In fact, I did once have a small section of CS315 many years ago in which the students tried to rewrite the project in Unity, but it was too great a task for them to learn a new engine and understand enough of the original implementation to do the port.

I have spent some time reviewing the original implementation and piecing together how it might be implemented in Godot Engine. I approached it as I did Canning Heroes: Special Edition, but Morgan's Raid is a much more complicated game than Canning Heroes. Also, it was from much longer ago, and I myself don't even have a version of it that I can run, which means I am working from a combination of screenshots, memory, and the original implementation. 

One of first things I noticed from the original implementation is the mess of manually-managed dependencies. The game was programmed using Slick, which was itself built on LWJGL. These required both portable and platform-dependent native dependencies. We also used numerous third-party libraries, particularly from the Apache Commons but also including Guava, EasyMock, and JodaTime. All of these were handled manually within a hand-rolled ant build script. While Maven existed at the time, none of us knew about it; I would not learn about Maven until later projects using PlayN, which required it. These days, my Java projects are all powered by Gradle. This means that if I want to add a dependency, it's a simple matter of tweaking a value in a build script. Looking back at Morgan's Raid reminded me of the reality of "dependency hell" and how good my students have it these days.

The map in Morgan's Raid was represented by 63 512x512 tiles arranged in a 9x7 rectangle. At the time, we had to write the logic to dynamically load only those tiles that were visible so that we would not blow out the client's memory. In my Godot experimentation, I took those original tiles and just loaded them all into the editor at once with no problems. It may also be worth noting that the original implementation was pretty naive. Someone made the whole map in Photoshop by using a paper texture background, and then chopping the large map into these 63 pieces. Much of the map is actually empty aside from this texture. Now, I know it would make a lot more sense to just do that background texturing in-engine with a repeating texture, but we didn't know that at the time. Put another way, it's not just the technology that changed, but my own knowledge and ability to mentor students.

The original implementation used configuration files to specify the locations of the various cities. They are not rendered into the map background but rather overlaid as sprites. All the paths were similarly specified through configuration files, whose data were manually entered based on historic maps and contemporary GPS coordinates. In my demo Godot build, I instead instanced a City scene for each city and just dropped it into the editor. This would have blown the minds of the original Morgan's Raid team, who spent an enormous amount of time transferring data between different representations: if they could just drop a city or draw a path in-editor, our turnaround time would have been much greater.

I remember being very proud of the version control and continuous integration system we set up for Morgan's Raid. The systems administrators got local servers running Mercurial and... something for CI that I cannot remember now. It was my first foray into this kind of devops, and I learned a lot from it. It took a lot of effort from the systems administrators and myself to get this up and running, but now, we can do all of this immediately and for free on GitHub. Like Maven, GitHub also predates our project, but none of us was using it at the time, and it certainly didn't have the de facto standard status that it does now. Indeed, this was back before git had improved its command-line, and I was deep into the Mercurial camp anyway. These days, I can get everyone in a junior-level CS course using continuous integration via GitHub Actions by the second or third week of the semester. 

One of the shortcomings that our research found in the original game is that too many of the mechanics are hidden from the player. There is little feedback to the player about how a choice they are making will impact the future, or how past choices impacted the present. These were intentional decisions made under the reasoning of "fog of war," but our analysis of the game (published in GLS in 2013) showed that this was probably a mistake. I hope that we get a chance not only to re-engineer this game for modern audiences, but also to revisit some of those design decisions. As I recall, we were on the verge of adding the Copperheads and other historically-inspired narrative elements to the game when we had to freeze our features. 

I may continue to tinker with my initial Godot implementation when I find some time during this semester, in hopes that I can then work with a larger team and with dedicated time to complete the effort. This code can be found on GitHub in case anyone wants to take a look, but keep in mind that it's not really set up as a community project, with Issues or any kind of reasonable documentation. 

No comments:

Post a Comment