Fire Walk with Me: Summer Progress on Arcana
Over the summer, I have been working with fiery passion on my game project, Arcana and its associated editor, the Arcana Ritual Toolset. Arcana is a twofold project: a) a game meant to simulate a rich experience of magic by allowing players to perform rituals and b) an editor that allows developers to build their own rituals for players to perform. Arcana has been in development in various iterations for the last seven years, including two years in which I worked with students. The game is the practical fulfillment of the theoretical principles about how to make better videogame magic systems described in my book, Game Magic: A Designer’s Guide to Magic Systems in Theory and Practice. This summer, I’ve been carrying forward the work, with the help of three collaborators: Steve Graham, Scott Graham, and Damian Fox. What follows is a summary of the project’s evolution over the summer. The Youtube links lead to game footage at the various stages of the project’s development described in the blog.
I began work on Arcana this summer with a simple task: to cause a card, representing a ritual object, to fade in and out through moving a slider. (The card was Anubis, the Egyptian god of Death). The fading of the card was meant to simulate the movement through a multi-dimensional space, i.e. astral projection, as well as summoning extra-planar beings to this world, i.e. invocation/evocation. I made the card into a GUI image, then accessed the alpha channel of its canvas renderer and tied this variable to a slider. I then constructed six sliders to represent six major dimensions that could be traveled, increased, or decreased through rituals: life/death, good/evil, order/chaos, pleasure/pain, knowledge/ignorance, and reality/illusion. By moving each of these sliders, a particular tarot card (drawn by Damian Fox) could fade in and out (e.g. the Anubis card would become clearer and more solid as death increased).
At this stage, I also experimented with creating some simple ritual actions, such as chanting and lighting candles, though they did not initially relate to any underlying model of ritual logic.
Once I had these six sliders, Scott Graham (whose background is in physics and computer science) provided me with a mathematical function to calculate “taxi distance” in six-dimensional space, which involved taking the sum of the absolute value of each difference along a given dimension. I faded the alpha channel of the canvas renderer of each card based on the multi-dimensional distance equation after I had translated it into Unity’s mathematical functions via C#.
Based on an inspiration in a half-waking state one night, I eventually arranged the six sliders, and two more form Time and Space, along the spokes of the eight-pointed star of chaos, in reference both to the arms of the sorcerer-king Elric’s patron chaos deity, as well as to the paradigms or perspectives of sorcery used in chaos magic. The sliders then ceased to function as sliders per se, but as gauges (analogous to health bars) of the various planar vector variables. The chaos star is an interdimensional compass rose visually representing the player’s position in multidimensional space. Because the sliders were now dimensional gauges, buttons on the right-hand side of the screen caused movement along a given vector. In keeping with chaos magic tradition, I gave each vector on the star a symbolic set of colors.
This scene and its associated functions represented the Editor Mode of Arcana, to be used by developers, as implied by the name “Arcana Ritual Toolset.” I then set to work on a game mode to be experienced by players. I initially began with six planar background screens that would be loaded if the player pressed a particular button. https://www.youtube.com/watch?v=PqLjTqq0kwo
I then began to work on basic ritual actions. At Steve Graham’s suggestion, I wrote up several example rituals of the sort that I would want players to experience. I noticed that a recurrent pattern in these rituals was placing a ritual object onto a consecrated space (called a ritual location): candles onto a pentagram, skulls onto an altar, coins onto a tombstone. Accordingly, I worked on basic drag-and-drop functionality using an official Unity example. Dropping a coin onto a tombstone would then cause a ghost sprite to appear. (The fictional premise is summoning a ghost by offering a coin called an Obolus to Charon the Boatman. Influence of both Huck Finn and Wraith: The Oblivion are at work here). At first, the ghost’s appearance was binary (either completely invisible or completely visible). Using the multi-dimensional distance function, I then tied the ghost’s alpha channel to the underlying death variable, which could be incremented by placing the coin on the tombstone. To simulate this ritual logic, I wrote a function called DeathShift() that would increment the death variable whenever the player put a coin onto a tombstone.
I then wrote code to retrieve the name of both the dropped item, called the ritual object in the language of our development team, and the consecrated space, called a ritual location. I slowly elaborated and built upon the tombstone ritual by creating a second ritual location (a tombstone) and a second ritual object (the flower). By retrieving the names of ritual objects and ritual locations, I could increment different variables.
I then elaborated and generalized this ritual logic by writing functions to increment all of the variables, initially incrementing a given vector variable by 1 at a time. (Later, I also wrote functions to increment the vector variables by 0.1, since float values map more easily onto an alpha channel that runs from 0 to 1). I also wrote a more generalized and sophisticated planar distance function that measures the multidimensional distance between the player and ritual cards. In order to make this function work, I attached a planarlocus script to each card to define its location in metaphysical space (referred to by my team as the metaspace). I also wrote distance functions manually to calculate the distance between player and every single ritual card individually. (It was only later that I learned the concept of functional abstraction, allowing me to parameterize the functions DeathShift(), which shifts the player 1 unit on the death vector, and MinorDeathShift(), which shifts the player 0.1 units, into a single function: DeathShift(n). A further layer of abstraction is planned, in which a PlanarShift(v) function is passed an entire six-dimensional vector. The advantage of this type of functional abstraction is concision: accomplishing the work of 200 lines of code in 1 line. At the time I was writing the distance functions, however, I was typing each individual line, which required great care, time, and double-checking when code didn’t compile or do what I expected.
Eventually, I imported all the card art produced by Damian Fox (as well as students Greg Roling and Matt Nelles), allowing me to build several rituals, including a ritual to travel to Carcosa by placing the King in Yellow’s mask, robe, and book onto a black star and an altar. These details allude to the King in Yellow mythos of Robert W. Chambers, recently popularized by the TV show True Detective.
While expanding the rituals, I also collected six planar backgrounds to represent particular planes, such as a giant chaos star for the Chaos plane and a macabre art nouveau piece called Demiurge by Anastasia Inspiderwiht to represent the plane of Ignorance. I adapted the multi-dimensional distance function to switch backgrounds using Sorting Order, so that planes become discrete boundaries between dimensions that change abruptly at a given threshold and stay fully opaque while the objects associated with that plane shift in and out.
I also separated all the images from their associated cards in order to be able to use the card images as sprites for ritual objects.
Once mathematical functions were in place to increment and decrement variables, I added greater variety to rituals by developing ritual actions beyond simply placing ritual objects. Each new ritual action mathematically affects the underlying vector mathematics. Ringing a bell calls a Purify() function that sets all dimensional vectors to 0 (useful if one has made a mistake in a ritual, or if one changes one’s mind). Lighting a candle adds 1 to all dimensional variables. Chanting squares all variables. Each ritual action also has associated multimodal feedback, including a temple bell sound from Kyoto, Tibetan throat singing, and the sound of a candle being lit and snuffed. I’m especially proud of the hourglass action. Pressing the hourglass button temporarily boosts all vectors, fires an animation of the hourglass turning over, starts a sand sound, and then re-sets all vectors when the sand runs out.
I then began work on creating an inventory system in order for the player to be able to carry ritual objects. I used the Inventory Master asset from the Unity store, and I spent several days re-building my Arcana ritual engine in order to work in conjunction with the new asset.
I also spent several days experimenting with object instantiation in order to be able to drop a 2d object into the scene (something not anticipated by the Inventory Master). Using several AddComponent() functions to add colliders, pickup scripts, and other needed parts to dropped objects, I can now pick up dropped objects and put them in an inventory.
These features pave the way for a planar scavenger hunt: an astral projection adventure in metaspace searching for ritual objects. With luck, the planar scavenger hunt will be a small playable demo: a few minutes of rough gameplay designed to convey the overall idea of Arcana in game mode.