3 ms·
My pet project is attempting to reimplement an old roguelike to have modding support. So far I've managed to spend about 4 years on and off hitting roadblocks a
by nonbirithm 5y ago
My pet project is attempting to reimplement an old roguelike to have modding support. So far I've managed to spend about 4 years on and off hitting roadblocks and prototyping things related to it, purely for the sake of iterating on the idea a bit more each time.
With this project, I am faced with the problem of how to redesign an existing game to have a modern modding interface. Unlike the problems faced by developing a game from scratch, most of the work goes into engineering, since the game's design has already been proven to work, and I'm approaching everything with a mindset of backwards compatibility. There are dozens of forks of the original game that add their own features or make specific changes to things like the experience formulas, but all of them are fragmented and incompatible with each other. Figuring out how to integrate these changes in a way that can be toggled on and off at runtime means delving into topics like aspect-oriented programming, and designing the game object model to allow adding and removing extra per-mod state and behavior dynamically.
Originally, I came up with an interesting idea: what if you could dynamically program a roguelike in the same way you can program Emacs? And not just a bespoke roguelike with an original game design that might or might not work, but a fifteen-year-old game with some amount of cult recognition and a lot of development history behind it? To that end, I wrote an Emacs layer for the engine and integrated it to the point where I could hot-reload maybe 80% of the game's code without needing a program restart. I also added an in-game REPL that could call pretty much any API available to the engine and mods, and used it in significant capacity to prototype and debug things on-the-fly.
The interesting thing is how little gamedev-related information there is online about things I would consider to be essential to solving the problems I encounter. I think this is because most people are interested in just shipping games instead of bikeshedding over how to create a well-designed modding interface for all eternity because it's too much fun. One example of a difficult problem is how to program nested containers of items, as well as allowing mods to create their own containers with special filtering logic or similar. Another is adding extra state and logic for eating/using items while also having the new state compatible with item stacking/separation, deep-copying and serialization. These are the sorts of problems that you take for granted when writing mods for Minecraft or any other game with a robust modding interface. Previously I implemented the game in Lua to allow for maximum flexibility, but I started to run into problems that the choice of language ended up sweeping under the rug. One example is having no explicit interface for deep copying/serialization of game objects, and hoping that a naive key-value visitor would suffice (which it did not).
The interesting thing about this game in particular is that, fifteen years after its initial release, there exists a small but active community centered around a few forks of the game with significant differences in features/balance between them. (I also happen to maintain one of them.) My hope is that these forks can be unified under the system I'm envisioning, while also providing simple ways to add new content and allowing for new features that would have been impossible to implement in the past (the original game was written in an obscure offshoot of BASIC with no English documentation).
But honestly, it's mostly just fun to tinker around with the engine whenever I get some free time. I'm currently figuring things out at my own pace, to the point where having the finished product becomes nothing more than a nice bonus at the end.
The source code of the first prototype is here[1], although right now I'm trying to see if using a language like C# instead of Lua would solve some of the stability issues I'm encountering.
[1] https://github.com/Ruin0x11/OpenNefia https://github.com/Ruin0x11/OpenNefia