Tonight I get to do something I’ve wanted to do for a really long time: I’m open-sourcing the roguelike I’ve been working on for several years. Amaranth is an old-school terminal-based roguelike written in C#. It looks like this:
Because I’m crazy about decoupling, it’s actually split into three separate projects:
Bramble is a very small low-level library containing utility classes. It doesn’t rely on anything beyond core .NET collections and provides more useful 2D vector and rectangle classes, along with some other handy stuff. Even if you aren’t working on a game, there may be something in here you can use, which is why it’s its own project.
Malison is the terminal library Amaranth uses for its user interface. Like many roguelikes, Amaranth doesn’t have graphics. Instead, it draws the game world in ASCII like an old computer terminal. Malison is a generic library for drawing to a virtual terminal. Even if you don’t care about Amaranth, Malison should be exactly what you need if you’re going to write your own roguelike or other terminal-style app in C#.
One nice feature it has is that it decouples a logical terminal from a specific renderer. It provides a renderer using WinForms, but it should be simple to implement other renderers on top of XNA, WPF, or Silverlight. Code that writes to a terminal only knows about the abstract terminal API, which means you could have a single game engine that supports rendering to a bunch of different terminal implementations.
Amaranth is the actual game, or the beginnings of one. I have lots of work left to do here, but a lot is also done. I’ll be writing more about interesting bits of the engine I hope. In the meantime you’ll just have to dig around in the code if you’re curious. Some fun stuff it supports:
- Game engine is completely decoupled from UI. It was designed so that if I later write a graphical front-end for it, zero engine code would need to change.
- Game loop handles different entity speeds, decoupling from UI, makes no distinction between player-controlled and AI entities, and makes clever use of coroutines.
- Game content is data-driven and loaded from friendly human-readable text files.
- Expected roguelike features are in there: random dungeons, line-of-sight, field-of-view, inventory, stores, spells, etc.
- The game loop was designed to support emergent behavior and interactions between entities. For example, hitting a monster could cause it to explode in a fireball which will in turn light a nearby torch, blinding an adjacent zombie. (There isn’t content for this stuff yet, though, just engine support.)
- No global state. Singletons are for amateurs.
It’s all up on bitbucket: bramble, malison, amaranth. Feel free to try it out, branch it, or whatever. In the meantime, I’ll try to find time to start writing some documentation on more interesting parts of what’s in there.