Armory of Babel

Armory of Babel is my personal experiment of creating procedurally generated weapon mechanics. I think there’s a certain charm in exploring the combat mechanics of a new game. Figuring out how everything fits together, exploring and optimizing the best ways to use the tools the game has given me. With this experiment I ask the question, “What if we give that experience to the player each time they start up the game?”.

I decided to do this experiment in Unity as that’s what I’m most comfortable with at the time of writing, additionally, Unity Editor Scripts provide a fairly straightforward way to create the tooling I need for this project.

the mechanics

Before I could start generating mechanics, I had to decide what “weapon mechanics” meant in the context of this experiment. I wasn’t going to be generating animation hitboxes or moves, these were to be predefined. Instead I define how these interact with each other, the player, and the enemies. This involves elements such as stamina bars, mp pool, movement speed, attack strengths and the synergy between attacks. As a result my system can be agnostic to the actual game it is being used for, the same weapon mechanics could be generated for a FPS as they could be for a sidescroller.

Having decided what the system can and can’t do, I went on to make a system to create these mechanics by hand before I started generating them. I chose to make this into a node graph like system as shown below. Each node has a label, a value, and a set of connections. The labels indicate certain functions that can be controlled by other systems. A node labeled ‘A’ will be activated when the player presses the A button / Key. Next, the connected node labeled OUT will be called, this will try to play an animation and or spawn a particle (however the game implements this action). This activates the connected node if the action was possible. The nature of this outgoing attack is defined by any attached modifier nodes (damage in this case) whose value (2) is read to modify the attack’s properties.

I researched several games with intricate combat mechanics and tried to replicate them within this system, extending the system each time a feature was missing. One of the more intricate mechanics is shown below. This graph is a representation of the way Dual Blades function in the game Monster Hunter: World

Generation

Having the ability to create sufficiently complex mechanics for this experiment, the next step was to create a system to generate these procedurally. I chose a two step approach for this using formal grammar and node grammars. These steps will be explained in more detail however the concept behind this is to create a rough outline of how the mechanic will function (example: one resource , something to generate the resource, and a damage buff) and then to have a separate system interpret these instructions and create a node graph.

string grammars

For those unfamiliar, formal grammars can (for the context of this experiment) be described as a set of rules that create a sequence of characters from a starting point. These rules are written out like this:
S → aBSc
This means any occurrence of S will be turned into aBSc, all subsequent rules will be applied to this transformed string. We can add a second rule:
S → abc
Now the system will randomly pick between these two rules, it will keep doing this until no more rules can be applied to the string. Let’s say we add a few more rules like:
Ba → aB
Bb → bb
Each time we run this set of rules on the starting character “S” we’ll get a random output that looks like <abc,aabbcc,aaabbbccc,aaaaabbbbbccccc…>

These strings of characters can be interpreted as the building instructions for the mechanic; grammars allow for a way to control the randomness of these instructions. For example grammars will let me ensure that a resource always has at least one producer and one consumer. I made an editor to create and test formal grammars for this project, shown below.

Node grammars

The next step involved creating a system that can interpret these instructions and create a node graph for a playable mechanic. This involves the output generated by the formal grammars being split up character by character, these individual characters will correspond to a node-grammar. For example, if we get the output “aabc” from the formal grammars the system is going to apply the node-grammar labeled “a” twice before executing “b” then “c”.
These node-grammars function much in the same was as formal grammars, instead of replacing characters in strings however they replace matching sub-graphs (part of a graph which is in itself a graph) with other sub-graphs. These node-grammars can grow the node graph, replace nodes, connect, disconnect or remove nodes. Below you can see the editor I made to create these node-grammars.

In addition, the editor I made allows for the creation of grammar-sets this is for the convenience of importing and exporting but also allows me to have multiple node-grammars under the same label. These grammars will be treated as fall-trough, if the system calls for the grammar ‘b’ and the first rule labeled ‘b’ can’t be applied (the left hand sub-graph isn’t found in the graph) the system will attempt to execute the second rule and so forth.

combining

Having finished these two systems the next step was to combine them so I could start creating the grammars that would end up generating weapon mechanics. To do this I created another editor window where I could test and combine these parts together and analyze the generated mechanic.

From this point I created several dozens of grammars to generate somewhat diverse and interesting weapon mechanics.

testing environment

What’s left is to set up a game to test how well these generated mechanics work and balance them. I had set up a simple top-down dungeon crawler with a variety of enemies to test out my mechanics however it became immediately clear that without the help of some signifies the player would quickly get lost as to the function of the UI elements and how they relate to the weapon mechanics.

results

The results of this project can be found on my Github. This includes a build you can play around with as well as all the source code for the project. Below you can see some of the mechanics this system will generate as well as a short description of how they work.

This mechanic gives the player a resource controlled by two attacks. When the resource is high the punch attack will gain an ice effect, freezing and slowing enemies. When the resource is low the sweep attack seems to gain an extra projectile.
Here is a showcase of a more complex mechanic the system can generate. The primary attack turns into a (weaker) projectile if not used regularly indicated by the green progress bar. The secondary attack gains an ice effect and extra power by using the magenta resource. This resource is generated slowly by moving. The player also has a “stance” they can switch on (indicated by the blue bar), this turns their primary attack into a fire punch but makes their secondary attack weaker, additionally it regenerates the magenta resource over time.
The system is not yet perfect, sometimes it generates mechanics that are hard to understand at first. Sometimes it generates mechanics with a broken premise as shown above, the player fires continuous projectiles but is so slow they can only move by punching. I’ll keep working on making sure mechanics like this can exist in a more controlled manner.