Spiral Game System Prototype



A prototype console app for designing games for the Spiral Game System.

Business Purpose

I’ve always used spreadsheets to design games. I often feel it necessary to be able to compare apples to apples on game components, especially when balance is important.

But sometimes, a spreadsheet is just not enough. On Oubliette, I pushed the limits of lookups and object-oriented data in google sheets. After that, I decided that my next data-driven game would need a more robust object system.

It took a few games and several years, but we landed on The Spiral Game System, which would be the basis for our next big phase of games.

And with SGS, I my plan for a robust data system began to see the light.

This command-line app was my first attempt to build a tool that could manipulate the kinds of data structures I had in my head for the project. It later morphed into the Spiral Game System Website, but at the time, this is what I had, and it influenced the design of SGS.

At its core, the SGS console app allows you to take a document of game elements, such as stats, items, and creatures, and perform operations on them that would change their XP values.


the SGS console app was originally envisaged as a multi-platform, single user system composed of a core SGS library, and a number of Xamarin-based frontends. The pilot frontend was a simple command-line interface for the library itself, and in the end that’s all I built before deciding to upgrade to a website.


The console app was designed to run in two modes: compile or interactive. In compile mode, all options were selected on the initial call, and the app would perform its actions and compile a document for you. In interactive mode, the console app stayed open on a while loop and allowed you to perform commands on an opened SGS document.

In either mode, the program would load a document of human-readable game rule content, perform some math for each element, and write that information back to the document. In interactive mode, you could select and manipulate individual game objects, and the app would automatically refresh the UI so that you could keep track of the XP values of things and use new stats as you created them.

This was implemented as a loop of commands. Each command was composed of:

Each command had its own custom handler, and depending on the subcommand and parameters given, it would perform actions on the SGS document held in memory.

The advantage here was that objects could be referenced in multiple other objects, without needing to update the same object in multiple places. Change the stats on the longsword and it would automatically populate out to knight, veteran, and fighter instantly.

As the stats and objects were changed, the XP values of each affected item would automatically update.

In interactive mode, the command loop continued indefinitely until the user entered a quit command.


Points of Interest

Set command

The set command allowed the user to change values on entities. Depending on the subcommand, it would set different kinds of values. Generally you would set skill, tactical stat, or primary stat.

An example of use would be

set agility d4

Which would set the active entity’s agility score to a d4.

List command

List all entities:
longsword                    14 xp
dagger                        7 xp easily hidden
flame wand                   21 xp conjure flames small and large
earth staff                  19 xp Manipulate dirt & earth
longbow                      11 xp
mace                         14 xp good against armor
fire bolt                    23 xp
Fireball                     28 xp
assassinate                  30 xp
buckler                       6 xp
kite shield                  21 xp
plate armor                  82 xp impressive to common folk
chainmail                    48 xp
leather armor                12 xp
mage robes                   30 xp impressive to the common folk
battle axe                   14 xp
medicine bag                 10 xp
holy symbol                   7 xp
thieves tools                14 xp disarm traps & unlock doors
crossbow                     23 xp
darts                         4 xp easily hidden
healing spell                14 xp instant healing
invisibility spell           56 xp
Rapier                       14 xp Agile & Precise
Weak Poison                   5 xp Increases Damage When Applied
dragon leather armor         33 xp
Posh clothes                 16 xp impressive to common folk
Meteor Swarm                 98 xp
compass spell                11 xp
disguise spell                4 xp
Lesser Nature Magic           7 xp alter or create small natural aspects
Burglar's Kit                13 xp rope and climbing equipment, disarming tools and gadgets
Alchemist's Kit              13 xp bottles and tools for potionmaking, chemical testing tools
Craftsman's Kit              14 xp metalworking tools, woodworking tools
Generic Rogue               289 xp cunning and quick-witted, friends in low places
Generic Mage                273 xp wise and kindly old father figure, well versed in the ancient lore
Generic Soldier             282 xp Brave and Strong Willed, Monster Slayer
Petty Criminal               55 xp
petty criminal hero          54 xp
Criminal Thug               104 xp
Swarm of Rabble             200 xp Whole Crowd of Angry People
Epic Character            2,592 xp
Epic2                     2,585 xp
Banesword                    63 xp
Advanced Assasinate         122 xp
skeleton                     70 xp
orc warrior                 189 xp
shambler                    402 xp plant camouflage
warlord                   1,372 xp wily and brave, high pain tolerance
Generic dragon            5,548 xp magic-resistant hide, can fly

The list command showed a table of all entities in the document, their XP value, and a summary of its aspects. This quickly allowed the user to get an overview.

Object Math

Object Math is a module in the SGS core library that allows the app to perform mathematical operations on dice pools. This was one of the most complex parts of the app, as it involved string parsing and some very elaborate domain-specific rules.

In roleplaying games, dice are rolled during gameplay to produce outcome numbers. On the character sheet, a string like 2d6 or 1d20+5 represents an operation, not a specific number. Therefore, adding the two together doesn’t come out to a single number, but another dice pool, 1d20+2d6+5. The object math module covered as many of these operations as I could forsee at the time, by breaking each string up into its component parts and applying well-defined operatons to those parts.

For each operand of an operation, the system created a dictionary of die sizes (d4, d6, d8, and so on), and placed the number of dice in the value for its respective key. Another key was used for flat numerical bonuses. Dictionaries of this type were used for each of the operations. If the pools were added together, for example, the values from one dictionary would be added to the other.

In the event that the app couldn’t find a simplification for an operation (1d6 / 4 for example) the app would simply return that value as the most simplified value for the operation. When possible, it would perform the actual math and return the result.

The app provided the following operations, organized by the number of operands:

With these operations and references, you could build complex formulae for generated statistics, such as adding up an entity’s toughness, size, and armor to get its overall health.



It’s a command line app. It’s not exactly user friendly. A lot of people wouldn’t even know how to open it. Not exactly a good situation for adoption of the system.


Most of the time, people work on games in a group, and this had no mechanism for that. In the process of trying to solve that problem (by integrating Dropbox or Onedrive) I ended up on a research rabbit hole to investigating real-time communication web technologies, and ended up deciding that a server running a socket system would be better in the long run than a console app.

What I learned

Console App Design

Before this, the only console apps I’d worked on were utilities that did exactly one thing. This was the first time I got to write an interactive console loop, and it was actually a lot of fun. A lot simpler to deal with than all the stuff between the user and the code in something like Unity. But ultimately, only useful for niche use cases.

Prototyping is valuable

Though this app is consigned to the depths of history and a blog post, it did really help me organize how I wanted SGS to work. Designing this app forced me to really consider the rules to the game in a way that I don’t usually get to do, and almost never see: at a level where a machine could understand the rules. That means being extremely literal and very careful. Additionally, while none of the code was transferred, almost all of the ideas translated directly over and I was able to make very fast progress on the initial versions of the SGS Website because of the prototype console app.


comments powered by Disqus