I like to use compiler spells a lot, so I try to make these spells as versatile as I can with as few patterns and meta-eval as possible to maximize utility and portability. You won't see any use of external memory in these spells; no overwriting the ravenmind, no overwriting spell books or foci. This is to keep the spell compilation process versatile.
Most of these spells I was able to reduce the pattern count using 1.19+ patterns and smarter compilation methods. I've been trying to shrink these spells for a few hours. If there is a way to compact any of the compiler spells further, let me know what I missed.
I'm also going to use my iota notation to explain some things. Here's what you need to know
Iotas can be patterns, lists, numbers, or names:
[ 6 <some iota> ]
A name inside of <angle brackets> signifies exactly one iota. A name inside of (round brackets) signifies zero or more iotas, for example,
[ (Create Particle Star Spell) [(Vector List)] ]
I use a similar input/output notation as the hex book:
<second top iota on the stack>, <top iota on the stack> -> <output to the second top of the stack>, <output to the top of the stack>
I made my compiler spells expect the stack to be in an intuitive order. If a spell is taken as input, the stack should generally be arranged in a way where just drawing Hermes Gambit would cause the spell to evaluate normally, and not throw any errors.
________________________________________________________________________________________________________________________________________________________________________________
So we want to make a self modifying spell, lets tackle the modifying part first without worrying about replication for now. An easy place to start is with Stygian Weave spells (Stygian spells). These are spells that are meant to be duplicated before they are cast. There are a couple reasons a spell may want to be cast like this, but the main one is for storing data. The copy of the spell dissects the original to obtain raw data that has been embedded.
An easy way to create Stygian spells is with Charon's Gambit. The Charon pattern halts spell execution. That means that you can end a spell pattern list with a Charon, then append raw data directly afterwards without causing the spell to throw errors when cast.
I discovered a nice design pattern for these spells. A post-Charon list is extracted, then that list is unpacked and the first iota is executed with Hermes Gambit. The idea here is that when the list is unpacked, it will leave the stack with the spell you want to cast (called the function spell) at the top, and the other elements (the arguments) will make up the rest of the stack. When the function spell is executed, it can access all of the argument iotas.
[ [(arguments), [(function spell)]]]
I streamlined the creation of this spell design with Stygian Loom. It takes a spell with any number of raw arguments and turns them into a Stygian spell.
Stygian Loom (13 patterns)
(arguments), [(function spell)] -> [(spell)]
Code: Select all
{
Flock's Reflection
Flock's Gambit
{
Numerical Reflection: 5
Selection Distillation
Flock's Disintegration
Hermes' Gambit
Charon's Gambit
}
Jester's Gambit
Combination Distillation
}
For our purposes, instead of extracting data from the spell copy, we want a spell that can modify the copy to achieve different behaviors between castings. I call this type of spell a Royal Stygian Weave, or just a Royal Spell. It's defining feature is that it leaves behind a modified version of itself (a new Royal spell) on the stack when cast as a Stygian.
Royal spells are tricky to construct though, we can't just make a spell that changes large parts of itself at random because at the end it needs to compile into another Royal Stygian for the next cast. We need to be careful about what parts of the spell we modify.
Lets construct such a spell using the same approach that we used for Stygian Weaves. The overall layout is a base spell followed by a Charon. After the Charon, we place all the variable argument iotas. The base spell will unpack the arguments, cast the function spell, then recompile the new arguments into a new Royal spell.
[ (function spell) (arguments)]
I made a compiler to streamline the process. This takes a function spell and variable arguments and turns them into a Royal Spell.
Royal Loom (20 patterns)
(arguments), [(function spell)] -> [(spell)]
Code: Select all
{
Flock's Reflection
Flock's Gambit
Retrograde Purification
Speaker's Decomposition
{
Flock's Disintegration
}
Jester's Gambit
{
Flock's Reflection
Flock's Gambit
Charon's Gambit
}
Combination Distillation
Combination Distillation
Jester's Gambit
Retrograde Purification
Combination Distillation
}
I made another compiler spell called Royal Loom + that fixes these issues by only using one iota for the argument. If a spell requires multiple arguments, the iota can be a list of arguments. (This will be helpful later)
Royal Loom + (28 patterns)
<argument>, [(function spell)] -> [spell]
Code: Select all
{
// append consideration to the end of the function spell
Consideration
Consideration
Consideration
Consideration
Integration Distillation
{
// reverse the spell list, pop the arg
Retrograde Purification
Speaker's Decomposition
// get the function spell
Prospector's Gambit
Numerical Reflection: 0
Selection Distillation
// add the base spell list (escaped) to the end
Rotation Gambit
Retrograde Purification
Integration Distillation
// patterns to add the arg back onto the base spell
{
Jester's Gambit
Integration Distillation
}
Combination Distillation
// cast the compiled spell
Hermes' Gambit
// halt casting before args
Charon's Gambit
}
// append the function spell and arg after the charon
Jester's Gambit
Integration Distillation
Jester's Gambit
Integration Distillation
}
Now that we have solved the issue of modification, lets figure out self replication. For this, we need to turn to Quines. In computer science, a Quine is a program that outputs itself. For hexcasting, a Quine is a spell that leaves itself on the stack when executed with Hermes' Gambit.
Here is a simple Quine, It works by nesting itself every time it's cast.
[ [ <placeholder> ] ]
You can think of this spell as having two states, there is the base state that holds the placeholder (which can be any iota) after the consideration, and there is the single nested state, which holds the base state spell instead of the placeholder.
When cast, the single nested state spell puts the base state spell onto the stack, then copies it and inserts it into the other base state spell at the position of the placeholder, thus turning it into the single nested state.
Basic Quine Compiler (11 patterns)
-> [(spell)]
Code: Select all
{
Consideration
Consideration
Bookkeeper's Gambit: - //placeholder iota
Numerical Reflection: 1
Prospector's Gambit
Surgeon's Exaltation
}
Numerical Reflection: 1
Prospector's Gambit
Surgeon's Exaltation
It's trivial to add extra patterns by appending them to the end of the base spell, these will be executed after the spell has copied itself so we can do some pretty interesting things here.
The first that comes to mind is making what I like to call a Hydra Quine. A spell that, when executed, returns two copies of itself to the stack.
[ [(base spell)] ]
This is accomplished simply by appending a Gemini Decomposition to the end of the base spell when we are constructing it.
Hydra Quine Compiler (12 patterns)
-> [(spell)]
Code: Select all
{
Consideration
Consideration
Bookkeeper's Gambit: -
Numerical Reflection: 1
Prospector's Gambit
Surgeon's Exaltation
Gemini Decomposition
}
Numerical Reflection: 1
Prospector's Gambit
Surgeon's Exaltation
we can attach basically anything we want at the end of the quine, but it's a bit annoying that we have to deal with having a dirty stack when whatever spell is at the end gets cast. If we want a spell to execute before the quine copies itself, we need to move this function spell to the beginning of the quine. This proves tricky as the variable length of a function spell at the beginning throws off the insertion index.
There are three main methods we can use to avoid this:
1. reverse the quine so the distance to the insertion index is from the back of the spell list rather than the front, then insert, and reverse again
2. use an escaped pattern list for the function spell and execute it with Hermes to achieve a constant length spell
3. find the length of the function spell and add it as an offset for the insertion index
Using the first method, we get something like this:
[(function spell) [(base spell)] ]
The Queen Quine compiler takes any spell, and inserts it into a quine of this format.
Queen Quine (18 patterns)
[(function spell)] -> [(spell)]
Code: Select all
{
// append a consideration to the end of the funciton spell
Consideration
Consideration
Consideration
Consideration
Integration Distillation
// create the insertion pattern list
{
Combination Distillation // placeholder
Retrograde Purification
Numerical Reflection: 6
Prospector's Gambit
Retrograde Purification
Surgeon's Exaltation
Retrograde Purification
}
// use the insertion pattern list to append itself, then nest the quine
Gemini Decomposition
Hermes' Gambit
}
If we look at the second method though, it's clear that this will work very easily with Stygian spells. We're already using a pattern list and Hermes, so all we need to do is to duplicate the spell pattern list before we execute it. We could even use a Royal spell for the function spell and insert its output into the base spell when nesting the Quine to get a self modifying spell!
[ [(royal spell)] [(base spell)] ]
The King Quine compiler uses this method to incorporate a Royal spell into a Quine. After the Royal has been executed, the output is used to overwrite the function spell placeholder in the base spell. So the next time the quine is cast, it executes the new Royal.
King Quine (27 patterns)
[(royal spell)] -> [(spell)]
Code: Select all
{
{
// put the Royal spell on the stack
Consideration
Consideration
Consideration
Consideration
Bookkeeper's Gambit: - // function spell placeholder
// cast as Stygian
Gemini Decomposition
Hermes' Gambit
// put the Base spell on the stack
Consideration
Consideration
Consideration
Consideration
Bookkeeper's Gambit: - // base spell placeholder
// duplicate base, and insert into copy
Numerical Reflection: 5
Prospector's Gambit
Surgeon's Exaltation
// insert result of Royal Stygian
Numerical Reflection: 1
Rotation Gambit
Surgeon's Exaltation
}
// copy the injection patterns, and execute them
Gemini Gambit
Numerical Reflection: 6
Numerical Reflection: 12
Selection Exaltation
Hermes' Gambit
}
Finally we have it, a spell that modifies itself when it is cast and can change it's own functionality. But we can make it much better with a small modification. Remember the Hydra Quine? It's not possible to produce such a spell with the current King Quine compiler. The Royal Spell is executed before the replication process. However, we can add a section after the replication patterns in the base spell called the Meta spell, which is used to manipulate the produced Quine.
[ [(royal spell)] [(base spell)] (meta spell)]
We can implement this into the compiler trivially by adding two patterns
King Quine + (29 patterns)
[(royal spell)], [(meta spell)] -> [(spell)]
Code: Select all
{
{
// put the Royal spell on the stack
Consideration
Consideration
Consideration
Consideration
Bookkeeper's Gambit: - // function spell placeholder
// cast as Stygian
Gemini Decomposition
Hermes' Gambit
// put the Base spell on the stack
Consideration
Consideration
Consideration
Consideration
Bookkeeper's Gambit: - // base spell placeholder
// duplicate base, and insert into copy
Numerical Reflection: 5
Prospector's Gambit
Surgeon's Exaltation
// insert result of Royal Stygian
Numerical Reflection: 1
Rotation Gambit
Surgeon's Exaltation
}
// add meta spell onto the end of the base spell
Jester's Gambit
Combination Distillation
// copy the injection patterns, and execute them
Gemini Gambit
Numerical Reflection: 6
Numerical Reflection: 12
Selection Exaltation
Hermes' Gambit
}
To show off what we can do with these new compilers, lets make a spell that counts how many times it has been cast, then deletes itself when it has been cast for the 5th time.
First we need to create the variable argument. Lets start with 0. Next, we need to create a spell that increments the number on the stack, reveals it, and leaves 'true' on the stack if the number reaches 5. At the end of this spell, the the number should be left above the boolean on the stack, the number will get sucked up as the arg for the next casting of the royal spell, and the bool will stay on the stack until the meta spell is evaluated.
[]
0
After this, use scribe's reflection to put Royal Loom + on the stack, then execute it with Hermes. We are now left with the Royal Spell. Now we want to add the meta spell. It will take the boolean on the stack, and drop the current spell list if the boolean is true:
[]
[(royal spell)]
Next, use scribe's reflection to put King Quine + on the stack, and execute with Hermes. The resulting quine counts how many times it has been cast, and deletes itself when it has been cast for the 5th time.
You can use the meta spell to do all sorts of interesting things, such as recasting the quine until some condition is met, switching out the function spell, filling every page in your spell book with a copy of itself (okay, maybe don't do that one)
This does feel a bit clunky though, We have to use two compiler spells to produce just one Quine. Its 28+29=57 patterns worth of compiler spells and the compiled spell uses up a meta-evaluation unnecessarily. The process can be streamlined by merging Royal Loom + and King Quine +.
Because we don't want to use any meta-evaluations, there can be variable length patterns before (the function spell) and after (the meta spell) the escaped base spell list. So we need to use the 3rd nesting method: find the length of the function spell and add it as an offset for the insertion index.
[ <arg> (func spell) [(base spell)] <base index> (meta spell)]
King's Loom (33 patterns)
<argument>, [(function spell)], [(meta spell)] -> [(spell)]
Code: Select all
{
Jester's Gambit
Consideration
Consideration
Consideration
Consideration
Single's Purification
Undertaker's Gambit
Nullary Reflection
Integration Distillation
Undertaker's Gambit
Combination Distillation
Combination Distillation
Undertaker's Gambit
Abacus Purification
Numerical Reflection: 1
Subtractive Distillation
Integration Distillation
{
Prospector's Gambit
Surgeon's Exaltation
Numerical Reflection: 1
Rotation Gambit
Surgeon's Exaltation
}
Combination Distillation
Undertaker's Gambit
Combination Distillation
Rotation Gambit
Combination Distillation
Jester's Gambit
Hermes' Gambit
}
And there we have it, A single spell that can compile any type of self modifying spell.
________________________________________________________________________________________________________________________________________________________________________________
Alright, now I've talked all about Stygian Weave, Royals, and Quines, but what we have right now isn't actually very practical. The main issue is the lifecycle of a Quine. The Quine lives on the stack, and as soon as we clear the pattern grid, it'll disappear.
The solution to this is to save the quine to an external storage with the meta spell. If you choose to use a focus or spellbook, then the meta spell should check if it can write to the item in the offhand, and save itself if it can.
[(King's Loom)]
[]
[(func spell)]
<arg>
(then use hermes' gambit to compile the spell, and save it to a focus or spellbook)
Using this even allows you to cast the spell with a standard CAD!
A dynamic quine that can live on the stack or in an item is rather powerful. But what if we don't care about it living on the stack, what if we are only going to use our spell in conjunction with a save item?
It turns out that we can cut a lot of corners. The spell doesn't even need to be a quine. We can use scribe's reflection to obtain a copy of the spell rather than having to nest it.
[ <arg> (func spell) ]
This is what the Enlace compiler creates. It's short, simple, and produces high utility spells. Definitely one of my favorite compiler spells.
Enlace (17 patterns)
<argument>, [(function spell)] -> [(spell)]
Code: Select all
{
Jester's Gambit
Speaker's Distillation
Consideration
Consideration
Consideration
Consideration
Speaker's Distillation
{
Scribe's Reflection
Numerical Reflection: 1
Rotation Gambit
Surgeon's Exaltation
Scribe's Gambit
}
Combination Distillation
}
Switchback
A spell for teleporting between 2 locations.
Cast while standing to teleport to the last place you cast this spell
Cast while sneaking to set your current location as the teleportation destination (without teleporting to the previous location)
Switchback (20 patterns)
Code: Select all
// arg
Mind's Reflection
Compass' Purification
// standing spell
{
Mind's Reflection
Compass' Purification
Undertaker's Gambit
Subtractive Distillation
Mind's Reflection
Jester's Gambit
Greater Teleport
}
// sneaking spell
{
Bookkeeper's Gambit: v
Mind's Reflection
Compass' Purification
}
// compile everything together
Scribe's Reflection // Knitting Needle
Hermes' Gambit
Scribe's Reflection // Enlace
Hermes' Gambit
So what's the next step? How do we take this further?
The answer is Advanced Multitool Spells. A multitool spell is a type of spell that has two or more different tools/spell functions, and a way to choose which one to use. Switchback was a simple multitool with only two possible functions (set location, and tp). An advanced multitool allows you to select a tool, and it will keep track of the selected tool until you select a different one. This type of spell is handy if you don't yet have access to spellbooks but want to keep multiple spells handy for CAD casting.
The construction I'm going with for this multitool is to have the arg be a list containing the currently selected tool index, followed by a bunch of tool spells.
[<tool index> (tool spells)]
If the spell is cast by a sneaking player, it will cycle the index. If the player isn't sneaking, it will grab the spell at the current index and execute it.
Basic Multitool Compiler (24 patterns)
[(list of tool spells)] -> [(spell)]
Code: Select all
// construct the arg, with the initial index of 0
Numerical Reflection: 0
Speaker's Distillation
// selection spell
{
// add 1 to the index
Speaker's Decomposition
Numerical Reflection: 1
Additive Distillation
// loop the limit
Prospector's Gambit
Abacus Purification
Modulus Distillation
// print new index
Reveal
// replace the arg
Speaker's Distillation
}
// casting spell
{
// cast the selected spell
Speaker's Decomposition
Selection Distillation
Hermes' Gambit
// restore the arg
Scribe's Reflection
Numerical Reflection: 1
Selection Distillation
}
// compile everything
Scribe's Reflection (Knitting Needle)
Hermes' Gambit
Scribe's Reflection (Enlace)
Hermes' Gambit
As an example, A simple meta tool may execute a levitation spell, then set the multitool index to the index of an impulse spell.
A very handy meta tool I like to use is New Page. It takes a spell on the stack, and adds it to the multitool.
New Page (11 patterns)
[(tool spell)] ->
Code: Select all
{
// get the metatool spell list
Scribe's Reflection
Undertaker's Gambit
// get the argument
Numerical Reflection: 1
Undertaker's Gambit
Selection Distillation
// add the new spell to the argument
Rotation Gambit
Integration Distillation
// save the new argument to the spell and save the new spell to the item in the offhand
Surgeon's Exaltation
Scribe's Gambit
}
Thanks for reading! I've been working on this for several days. If you have any questions or want to show off your own self-modifying spells, leave a reply!
Also, I didn't explicitly state this above, but the compilers you should be focusing on for making self-modifying spells are King's Loom for quines and Enlace for focus/spellbook spells.