25
$\begingroup$

Inspired by Cort Ammon wonderfully detailed answer here: How to prevent tiny mistake in 'programmable language' magic spell causing horrible disasters, and my desire to go out of my way to invalidate large portions of his wonderful answer (sorry Cort!).

The premise of the world is that magic is something that can be programmed. Put together words or symbols with predefined meaning into spells, provide power to the spells, and the result is whatever the spell is programmed to do, exactly as written. Magic is not (entirely) about raw power, but instead ability to program intelligently to write more complex programs.

Cort took this to the logical conclusion in his answer, treating magic entirely like a program and speaking in terms identical to Software Engineering, with the obvious parallels of writing a spell checker (I'm punny!) and even magical VMs for testing, amongst other examples. This is the logical output of a world where anything can be programmed. However, the world that would result from this approach is a far cry from the traditional 'feel' of most fantasy worlds, once you have the power of computer-level programming and a proper software engineering techniques you have exponential growth to a world as advanced or more so then our own.

I want a world that is somewhat closer to 'traditional' fantasy, with technology no greater then Renaissance era and, while magic can obviously automate some aspects of the world, I don't want magical replacements for every technology we have. Most importantly I don't want magic computers or the exponential increase in magic that would come from spells reaching the level of discipline, and more importantly programmatic support, of magical computers.

Modern Software engineering use what I'll call meta-programming, for lack of a better term, to create software who's sole purpose is to enable the production of better software. This includes things like building reusable modules and larger software frameworks (or even entirely new languages); but also includes indirect software support like use of IDEs to support software development, static analysis and unit testing tools for validating software, code repositories, or even internet and sites like stack overflow. I want to mostly forbid, or greatly limit, the ability to do this sort of 'meta-programming' due to it's allowing exponential growth as every program builds on the power of the last.

Thus I'm looking for a way to keep the core concept, that magic can be programmed and good magicians are good programers, but without exponential magical growth or 'meta-programming' taking to it's logical extreme.

I'm assuming a world where magic is not a brand new idea that has yet to be fully realized; it has been around for at least a century and has been taught and learned without 'meta-programming' proving a logical next step. Answers along the lines of "people just haven't thought to try meta-programming" are allowed, only if you can justify why a field with smart people striving to increase it's potential wouldn't realize the implication of what they can do; not just presume their too ignorant.

I could think of two potential avenues for approaching limiting of meta-programming, but can't quite figure out a proper implementation of the ideas.

  1. Prevent the magic from being Turing complete by removing some feature necessary for proper meta programing. Here the problem is making the programing magic 'full featured' enough to allow interesting spells, and sufficient complexity for skilled mages to clearly surpass lesser ones, while still making meta-programming impossible.

  2. Placing a limit on the power level of the mage, limiting their ability to cast more complex spells and thus causing meta-programming to quickly grow too magically taxing on the caster to be viable; much as how we have limits on CPU and memory usage with modern computers. The difficulty here being how to define the magical 'expense' of more complex spells that have little direct impact on the world (and thus impart little energy into the world) in a way that makes sense (ideally even to non-programmers who wouldn't fully grasp concepts big-O or the expense of abstraction) and is sufficiently limiting while still allowing skilled mages to make complex and interesting programs.

I'm open to any novel ideas for proper limiting of meta-programming beyond the above as well. If the ideas also encourage a system where skill of individual writing a program allows more powerful programs to be developed that is an added bonus.

$\endgroup$
7
  • $\begingroup$ How easy is it to make a magical effect permanent (that wouldn't be equivalently permanent if done in a mundane way)? What I mean is: something charred by a fire spell is likely to remain charred. However, if you want something to be permanently under a globe of darkness, how much energy does it take to sustain that spell indefinitely? $\endgroup$ Commented Dec 23, 2015 at 16:57
  • $\begingroup$ This sounds a bit like the"Halting problem" in Turing computers. I'm not entirely clear how this will work in the situation you've set up, though. cs.odu.edu/~toida/nerzic/390teched/computability/unsolv-1.html $\endgroup$
    – Thucydides
    Commented Dec 23, 2015 at 17:04
  • 2
    $\begingroup$ Challenge accepted =) $\endgroup$
    – Cort Ammon
    Commented Dec 23, 2015 at 17:40
  • 1
    $\begingroup$ I think the answer you link to is the wrong one $\endgroup$ Commented Dec 23, 2015 at 19:10
  • 1
    $\begingroup$ Have you considered a version where the magic itself is a force in motion until someone taps into it, rendering it inert but malleable? Then, when ripped from it's larger mass, it is like play dough for the skilled magician, but only "active" and "in motion" while the programming words are spoken. This would probably limit the effects to static ones, like a magical sword, improved armor or a perhaps magical reprogramming of someone's mind. But it would not be like a meta-enabled machine to keep working on something after the mage is done. $\endgroup$
    – Dale Gusta
    Commented Apr 10, 2020 at 7:51

9 Answers 9

18
$\begingroup$

One way is to make it so that you can't create frameworks.
Corts answer was a great example of software engineering, but how would you create a framework that can be used and reused and build upon by anyone?
You can't just write your code on the fabric of the universe.

For instance, say I create a spell to warm my tea. I cast it and my tea is warm.
In software you'd then create a function to warm any object to any temperature inside a class with other functions and it becomes a framework.
But a magic spell isn't software. The closest you could get would be to have a big spell book with all the spells, and invoke each one in turn, one at a time, which is classic fantasy.
One spell wouldn't invoke another spell.

The closest you could come to having stuff passed around would be if you bound magic to an object, like a magic ring for instance. The object would be usable by anyone wearing it, but once bound unchangeable, and unable to trigger or affect any other spell.

Lastly, the language could be a very low level language. Running on the bare metal as it where. And without the ability to make spells that call other spells you couldn't really make a high level language very easily.

$\endgroup$
2
  • 6
    $\begingroup$ TL;DR - "One spell wouldn't invoke another spell" $\endgroup$ Commented Nov 18, 2017 at 17:20
  • $\begingroup$ Something else that might have been interesting would be to also dramatically increase the magic cost the more a spell does. In a recent episode I watched the characters are trying to make complicated magic circles, but the different circles interfere with each other and burn out. So then they figure out they can make one circle per sheet of paper, and then layer them like a multilayer circuit board, but the magic cost is huge so only the MC with the most mana is able to power the thing. $\endgroup$
    – AndyD273
    Commented Apr 24 at 15:19
13
$\begingroup$

So as you can tell, I've played with these concepts just a little bit =) I find them great fun because its so easy to create scenarios where you don't know what's going to happen, but that brings a sense of wonder rather than fear.

I'm actually playing with this system right now, and I think it has a reasonable chance of meeting your needs. I'd love to have more people playing with it, beating on it, leveraging it, seeing what it can do.

Fundamental to the way Turing machines reach their ultimate capability with Turing Completeness is the idea that the bits stored last forever. If you write a 1 to a memory address, and come back any time later, it will still read a 1, as long as you or nobody else who has access to that memory space writes a different value.

What if we took that away? What if bits did not always behave like perfect little angels, holding onto our data for an eternity? What if surprises could happen? Surprises are great for a mage, but very very undesirable in the programming business, so this seems like a rather promising way to go!

If you take a hard look at our computers, you will find that they are not actually Turing machines. We program them according to a model which is Turing complete, but the real machines are layered on top of physical hardware. Fuses blow, cosmic rays dash bits of data into oblivion, even the dopants which turn silicon into one of the most valuable substances on earth eventually diffuse enough to end the life of a chip (especially if you run it too hot). Turing machines are an approximate model of the real thing, and quite an optimistic model at that. We get away with treating them as Turing machines because the mean time between failures for our modern processes is quite high. 99.999% of the time, your computer acts indistinguishable from a perfect Turing machine. That last 0.001% of the time? Well, that's when you angrily hit the reset button and think about just how much work you lost!

But what if the components were even more unreliable. Too low of reliability, and the only Turing style programming you are going to do is simple stuff, or small stuff. Of course, having your components always turning into useless smoke on a regular basis isn't going to the basis of much magic, so we're going to have to be more creative in what it means to be unreliable.

What if every "component" of a spell had its own "personality." It generally does whatever it feels like. If you can get a good bead on what it feels like doing, you can integrate it into a spell such that it generally does what you want it to do! This is a rather foreign concept to traditional engineering, but we see it in art all the time. When it comes to musical instruments, there's "good instruments" there's "bad instruments," and then there's those beautiful artists who can make music with whatever instrument you give them, catering to the instrument's strengths.

Mages making spells would have to have some ability to create components, just like imbuing a spell with magic in the first place. Clearly they would want some level of control over the personality of each component they create, but each component would certainly have its own individual spark. A novice may cram a bunch of components which they believe will work together, but an expert will listen to each component softly, listening to its whispers and adapting the spell to suit.

Now any engineer will look at this, and see the opportunity to abuse the Central Limit Theorem to minimize the effects of personality on their final product. As long as the effects of all of the personalities work out to about average, the spell will work. To tear this away from the engineering and programming minds once again, we're going to give these components two abilities.

  • Components can "talk" to each other, in any way they see fit. You can make it harder for them to communicate by putting stuff in the way, but you can never prevent it. If you give one component of a spell a pretty posh deal, and shaft another, you might regret your decision when they start comparing notes.
  • Components can cast magic of their own, creating new components. Obviously they're limited by the energy available to them, but the personality of the new component is all up to them!

The former rule makes it clear that you're never going to "control" the spell statistically. You're going to have to work with the spell, negotiating with it, bartering with it, until it agrees to do your bidding. The latter makes that even more extreme, because the spell can actually change meanings completely while you're not looking at it! (This is also really close to the "grey goo" concept of runaway AIs that can replicate)

Now how do we make sense of all of these components? There's actually several approaches, which may form several different fields of magic. One is testing. You stamp out a billion small components, and then test each to determine if they are a match for the personality you need. This gives you great precision in your spell, but is extremely wasteful (more on waste later). Another approach is to carefully listen to each component, and find it the best place possible. This creates spells of extraordinary power, but they are very tedious to construct. A third approach, we borrow from Mickey:

Mickey!

You mentioned wanting to limit meta-programming; this system embraces it.

What if each component acted like a spell, itself. It was simply casting whatever effects its personality wanted to do. This means that components are not lying in wait, ready for you to pull the trigger. They're doing their own thing. And that means, we can put them to use!

If we can encourage a few well-minded components to be sheep dogs of sorts, they can keep the rest of the components in mind as they jabber amongst each other and spawn new progeny. These components may be trained (by the mage) to encourage the others to want to do productive things, working with their personality like we do when teaching or tutoring. This is the dreaded meta-programming you mentioned, but its wings have been clipped. Instead of getting to rely on perfect provable automata, the wizard has to depend on a bunch of spells with personality to help him or her out. Needless to say, the art of stacking this meta-programming chain arbitrarily deep would be true art indeed, rather than a simple provable eventuality.

Fundamental to all of this is the idea that the components have some value. If I'm programming, and I determine I no longer need an integer, it is summarily sacked. In fact, I care so little for it that I let my compiler decide when and where to reuse its memory for another purpose... I don't even think about it. However, if these components have some intrinsic value, it makes sense to protect them, and reuse them after the spell is over. However, this leads to the question of where does the initial components come from, since something of value had to go into them. I suggest a system of offering. You offer something of value to {whatever}, and you are given an initial component in return. You can then teach this component to help you create new components, or offer something more to {whatever}. You never know what you get, but the general trend is "the more you sacrifice, the more you are given." This gives each component value.

You can also have an alternate construction, where you offer nothing, and accept whatever component you are given. Schools could grow up around how to care for these components that come from nothing, to give them value that nobody else could see.

All of these rules lead to two neat patterns that I find fascinating for World Building purposes. First is a set of archetypes for working with components:

  • The technology route - use lots of small cheap components, test them out, determine which ones meet your needs. Gets you good results quickly, but is wasteful of material.
  • The noble route - use very expensive components to accomplish everything. Gets you good results quickly, but you may have to sacrifice a great deal of wealth for them.
  • The artist route - use few components, each carefully listened to and whispered to. Gets you good results with very little waste, but its terribly slow.
  • The delegation route (Mickey!) - use components to work with other components for you. This permits massively parallel training of components that permits good results with little waste very quickly. It, itself, has two extremes, from which you can mix and mingle to your leisure:
    • The light side - encouraging components to work with you, listening to them, and adapting based on their wants and needs. This allows for theoretically unlimited capabilities, but you don't have full control over the situation. Done wrong, your components may break away from you and grow on their own, or you yourself may become a slave to them.
    • The dark side - ensuring components work for you by fear. As long as every component is afraid of you exerting enough spell casting power to wipe that component out, they are kept in line. This also has theoretically unlimited capabilities, but you must always fear a rebellion yourself. Your construct may turn on you with its full force, and you may not have enough power to wipe it all out at once.

The second neat thing is a new reading on the concept of a spell scroll. A spell scroll could be, as always, a bunch of magical components imbued onto a sheet of paper with a trigger to set them off. However, it could also be a non-magical sheet of paper with directions that permit a "delegation route" mage to let a component cast the spell for him/her. In this case, the scroll is not magical, but its more like a set of guidelines to help the caster make their own magic. In fact, one of these scrolls might even be the basis for the generation of a component without a sacrifice, bringing a new way of magic to a old world stuck in its ways.

In my playing with this system, I have found it allows intelligent individuals to construct rather marvelous things. However, I have found that, even more, it allows wise individuals to construct things nobody ever thought could be constructed. Wisdom reigns supreme in this system, not intellect.

$\endgroup$
7
  • $\begingroup$ very interesting idea. I'm going to come back to this when I have more time to process it and address it. Though I will nitpick by pointing out at this point it really isn't a programming language, even if you go with the 'technical approach' since there is no guarantee of results; though that could be tweaked. It does offer some advantages over the pure-programing concept, but is likely a bit too far off from the original results as I had imagined for programming magic...Still I'll come back to this some other time, I feel like there are some cool things to explore when I have the time :) $\endgroup$
    – dsollen
    Commented Dec 23, 2015 at 20:06
  • $\begingroup$ imcomplete thought, but I'm thinking for programming magic to exist raw code must run deterministically, so what if it's possible to do deterministic code, but much easier and/or cheaper to create code that has a sentience (or whatever you call having a predefined goal) , or perhaps code eventually gains a sentience once it reaches a certain threshold. Maybe sentience is a side effect of meta programing for instance. The coding bug issue from last question could be addressed if a meta-programing 'sentience' is usually used to run deterministic code to test and works to stop 'bad' code. $\endgroup$
    – dsollen
    Commented Dec 23, 2015 at 20:17
  • $\begingroup$ ...this also addresses the idea of mages 'casting' on the fly in such a world. They can cast on the fly using 'sentience' spells either directly, or deterministic code run through their personal sentient code-compiler which will work to stop 'bad' deterministic code and/or help rapidly modify the code. The trade off being confidence in results. The personal compiler is more deterministic because usually it's in consensus with you, but still may disagree or may not catch less horrible compile errors, the other option means far less control of what happens and possible worse effects $\endgroup$
    – dsollen
    Commented Dec 23, 2015 at 20:21
  • $\begingroup$ There's two answers you your notes. One is that, if you're willing to be wasteful, you can simply acquire components who are willing to be 'deterministic,' at least as deterministic as our current computers. Then you could "program" magic, with all the power therin, except that you have to pay to buy a monster meta-spell to do it with. The latter is that it is possible that such behavior could arise out of probabilistic behavior (deterministic is too limiting), such as arises in parallel Turing machines (which have a level of indeterminism in them). $\endgroup$
    – Cort Ammon
    Commented Dec 23, 2015 at 20:29
  • $\begingroup$ Whether that possibility will probably arise, or whether it is an infinitesimal chance of occurrence is left as an exercise for the reader. $\endgroup$
    – Cort Ammon
    Commented Dec 23, 2015 at 20:30
7
$\begingroup$

How about limiting the "memory" of the magic users? A better magic user can memorise bigger programs, so is capable of more complex magic.

Or you could have a "clock speed", whereby a more capable magic user can run through steps more quickly, increasing the speed in which they can cast, and thereby allowing them to do more in a given time?


Going back to the idea of Turing completeness, though, I'm borrowing heavily from an answer on Programming Stack Exchange:

In general, for an imperative language to be Turing-complete, it needs:

  • A form of conditional repetition or conditional jump
  • A way to read and write some form of storage

A jump could include something like a function definition, or a "subspell", which can be referred to multiple times - if I want to turn a bag of leaves into gold coins, I effectively run the "leaf to gold" subspell in a loop, with the end condition of "bag contains no leaves". There is no particular difference between changing one leaf to gold and changing 1 million leaves to gold in this case - there might be a time implication (which the clock speed suggestion addresses), but it's not memory bound really - there is no need to remember how many times the loop has run, just that you keep running it whilst there are still leaves in the bag.

The storage requirement allows for a more abstract end condition, so is easier to get rid of. For the bag of leaves to gold, the end condition is fixed, and easy to check (well, unless you get too much gold). For something like "give every person in the kingdom one gold coin, when they visit the fountain in the square", you need a kind of memory. Has this person previously had a gold coin? You can't easily check this condition based on any other source, so you need the memory to be implemented in some way to fully automate this spell.

Luckily, removing the possibility of memory limits the kind of spell you can do in almost exactly the way you want. If there is no way to store the current state of the spell, you are limited in the possibilities of meta programming, since you can't stop and debug code. You are limited effectively to input testing: I provide a bag with 1 leaf, and see what happens. What if I provide 1 stone instead? What about 10 leaves? What about 1 gold coin? There isn't the concept of a program state - either it has been run, or it has not been run, or it is in progress, and you can limit that by affecting the input (reaching into the bag and pulling out leaves).

$\endgroup$
2
  • 2
    $\begingroup$ +1 for your 'hardware' limitation idea; I think this approach will be a lot simpler and be more reasonably limiting without removing some of the fun stuff that Turing-completeness adds to the concept. Also gives some interesting opportunities for centuries-old megaspells TRYING to achieve some of the crazy meta stuff the OP doesn't want in immediate-mode long after their casters have died. $\endgroup$
    – Finch
    Commented Dec 23, 2015 at 17:06
  • 2
    $\begingroup$ Back in the real world, note that the quantum srate of a system can not be fully recorded (copied). This arises from the uncertainty principle. So if there's a magical uncertainty principle, then the way your magic behaves might be interestingly analogous to quantum reality. $\endgroup$
    – nigel222
    Commented Dec 24, 2015 at 11:31
3
$\begingroup$

Original Answer

I'm looking for a way to keep the core concept, that magic can be programmed and good magicians are good programers, but without exponential magical growth or 'meta-programming' taking to it's logical extreme.

The reason why there wouldn't be exponential growth is because high level magic has a cost. Consider the case software, the only reason why we can run complex high level software is because hardware improved... picture running Windows 7 on a 80's machine. You get the idea.

In the case of magic... sure you can create complex abstractions, but unlike computers the CPU models are not increasingly faster. Magic runs at the universe at the speed of magic (whatever that is), and it doesn't double each 18 months... so each abstraction brings an additional cost in time (and any other cost magic has).


Prevent the magic from being Turing complete by removing some feature necessary for proper meta programing. Here the problem is making the programing magic 'full featured' enough to allow interesting spells, and sufficient complexity for skilled mages to clearly surpass lesser ones, while still making meta-programming impossible.

It is understood that the better the understanding of the nature of the universe is, the better the mage. Because (as is the case with software) an user that understands what is happening at a lower level will be able to better take advantage of the tool.

As per making it not turin complete... what I would do is force the magic to be cosntant. Sure you say it is created like a spell that is wrote is some langague. It makes sense to me that the spell doesn't take parameters, and doesn't have an internal memory.

Instead magic use the universe for storage. So it has to move stuff in the world to store information, and retrieve information from it. This mean that the use of "memory" requires energy, and by whatever means this is done, other magic active at the same time could mess with it... meaning that memory is not a sacred place and information can be lost or corrupted. Using magic to protect the storage location for the spell will have an additional cost too - and it is probably something unskilled users don't do.

[Please see extended answer below, for another idea]


Placing a limit on the power level of the mage, limiting their ability to cast more complex spells and thus causing meta-programming to quickly grow too magically taxing on the caster to be viable; much as how we have limits on CPU and memory usage with modern computers. The difficulty here being how to define the magical 'expense' of more complex spells that have little direct impact on the world (and thus impart little energy into the world) in a way that makes sense (ideally even to non-programmers who wouldn't fully grasp concepts big-O or the expense of abstraction) and is sufficiently limiting while still allowing skilled mages to make complex and interesting programs.

The prefered storage location for magic variables could be the memory - as in the brain - of the caster. This means that accesing the memory of a person via magic is doable, protecting own memory from intruders is a must for mages, and using an spell that spawns a large data structure - in addition of the energy cost for the extra neuron synapses - will have an impact of the mage concentration [and perhaps sanity].


Extender answer

How to prevent tiny mistake in 'programmable language' magic spell causing horrible disasters

Since we are considering a world with a magic that uses memory that could be corrupted... the concern of the old question is relevant.

A solution is to have students create their magic using a higher level language, that has already incorporated limitations and controls, that makes it both predictible (to a degree) and easy to use.

So, elements used in this language are not the most basic ones. Instead they are made by expert users and invoked by the lesser ones. Even tho, it has been mentioned that there is (as currently stated) no sandbox or virtual machine for magic, some preventions could be taken for safe experimentation. Also, the ones that are allowed to know the low level language should be selected and trained to be responsible, careful and skilled enough. Sure, there is no perfect security... and some tragedies may lie in the past, but nothing from which they can't learn and improve upon.


Also, if we go for the idea of a high level language it could have limitations built in. It could be not turing complete intentionally, as a way to prevent new users from doing dangerous things.

For instance, the high level langauge could include a fail safe that will shorthand any long running loop, that means that no magic that uses the high level language will run for an undefined period of time.


Addendum: Extending on the idea of having no internal memory. This will make it harder for magic to write magic, as it will need the meidum to do it (be it a person, or some writing material).

As per, materializing where to write the spell, you should consider what goes into materialization. Are you taking protons from some atoms in the air and moving them to others to create heavier materials? Sounds expensive. How about teleportation? Even if magic allows it, didn't it cause a sudden pressure difference? And besides, it moved some mass across a certain distance in no time, that's infinite energy.

$\endgroup$
3
$\begingroup$

So far, all of these answers have been about limiting computability and meta-programming as a solution to your problem.

Your main issue with software engineering seems to be that magic will become too "overpowered".

However, the world that would result from this approach is a far cry from the traditional 'feel' of most fantasy worlds, once you have the power of computer-level programming and a proper software engineering techniques you have exponential growth to a world as advanced or more so then our own.

However, removing turing completeness from your 'magic language' is perhaps not the only way and certainly not the easiest way to achieve this effect. For a real world computer, there is another thing besides raw computing power that determine what it can and cannot do: I/O.

from this answer about turing completeness:

Strictly speaking, I/O is not required for Turing-completeness; TC only asserts that a language can compute the function you want, not that it can show you the result. In practice, every useful language has a way of interacting with the world somehow.

So my solution would be:

Make your "magic computer system" have a limited set of I/O operations.

this makes it really difficult to achieve something great. Clearly define the interface your language has to the outside world.

Perhaps I/O operations would only be possible that make some change to a single particle, such as moving or transforming a molecule or a grain of sand, and doing lots of these operations would be expensive. It could cost a lot of time, materials, energy, some kind of 'mana points' or other resource which is costly.

In short, you could consider not limiting the possibilities of your magic system in software land, but instead limit the possibilities of your 'hardware'. Since the 'hardware' is the the way your programs affect the real world, and how it works is completely determined by you, you don't need to have some kind of stagnation in the technological advancement in the "software industry". This way you dont have to impose a limit on the ingenuity of the mages in your world, but can still conveniently limit their capability in such a way to fit into your story.

$\endgroup$
2
$\begingroup$

There are already two inherent limits to "meta-magic" in the sense you use it, which you've also already touched on

  1. Magic messes with reality. It can't be sandboxed.
  2. "meta-programming" generally comes with a performance cost

And then you also need to nail down what exactly the result of a "syntax error" would be

Sandboxing

Most of the "meta-programming" in actual software engineering relies on some assumptions

  • "meta" products (frameworks, libraries, virtual machines, etc) are reliable
  • they can be developed and tested independently of anything they might be used with (e.g. you can write a library that is linked to other code, and operates using callback functions, without knowing about or actually having those callback functions present, although you would need a stub function for testing)
  • testing during production of "meta" products is safe, and relatively inexpensive (because it can be sandboxed), and the test stubs might be harmless (but that assumes the stubs have been tested as safe too ;) )

The reason we have stable, usable virtual machines is that we started with a level physical isolation from the beginning. Mucking around trying to develop the virtualizable chips and the virtualization software would break a single physical machine at a time, with no risk to the "caster's" life. You can't create a virtual machine with magic, because you're already living inside the host machine, a.k.a. reality. As far as reusable code components go, you already have that sort of stuff in more traditional magic systems, in the form of spell scrolls or otherwise repeatable and shareable magical effects.

You could possibly build a spell engineering room, with walls, ceiling and floor imbued with magic dampening barriers. Inside this room you could test your magic frame work, but you'd still be inside the room with your magic, and it could kill you, making development extremely risky. And development of meta-magic *extremely** dangerous. Testing a change to a magic framework for spatial manipulation/placement/targeting of your spell, and accidentally have an infinite loop with your testing spell to move a pebble. You know your move pebble spell is safe, but the infinite loop in the framework makes the pebble zip back and forth at increasingly faster speeds. Now it's a speeding bullet in a ricochet chamber.

You could try to develop a library of spells (functions) that get combined (linked) with other magic, but this assumes magic is allowed to exist in partial form, so it can later be combined. Of this would always be possible if there is a theoretical representation of magic available, i.e. the equivalent of source code, where the actual magic is machine code, and the compiler/linker is the caster. But, even with a theoretical representation, the framework/library would still need testing, which requires execution. How would you know your framework for parallelizing a spell works, if the spell being parallelized is a do-nothing stub. Even if all the spell does is create some sparkles, that would require energy, and what if there's a bug in your framework that allows runaway threads... methinks, dead mage, or burnt out mage, or similar.

As far as static analysis tools are concerned, most of those rely reproducing functioning parts of the compiler (lexer, parser, etc). In code, this is a "simple" case of reading and processing text strings. But if the compiler is human (or some other living being) that means reproducing a substantial part of the consciousness of said living being. The main distinction here is that in real life software development, the physical machines executing your code are inherently symbolic in nature. You're not messing around with electrical currents and different voltages, you're dealing with bits in memory. The hardware does a significant amount of abstraction for you. With magic, the same isn't true. The magic to read symbols for a written page would have to at some point distinguish the ink from the paper (either via visual recognition, or atomic analysis), translate that into text, etc before any static analysis could be performed. It all depends on the primitives of the "magic language".

Performance costs of frameworks/libraries

Using frameworks, libraries, virtual machines, containers, etc all carry a performance cost in software development. Sure, sometimes the cost is negligible, truly. But most of the time, we consider the cost negligible because the underlying hardware has become fast enough that those costs are imperceptible (or acceptable compared to the gains in actual development time). Reality, the physical hardware of the magic language, doesn't get faster and doesn't obey Moore's law. Also, if casters are expected to provide the energy (either from themselves or a secondary source) then frameworks becomes doubly expensive, both it terms of spell execution time and energy costs.

Syntax Errors are a special class of bug

So, in general, the closer to the bare metal you are, the less syntax there is. Technically, you can't make a syntax error in machine code. You upload a bunch of binary into memory, execute it. There can be plenty of other errors when you do that, but not really syntax errors. And magic is pretty much as bare metal as you can get. There are two possibilities here

  1. Syntax errors are a result of casters acting as compilers, translating between a higher level expression of a spell. A syntax error in the higher level expression could still then be handled (because the caster-compiler is intelligent) but it makes the spell more difficult to cast. It might be so bad that the spell 'crashes', being only half complete. Did you leave out a semi colon somewhere ... "ignite flame in palm; grow flame into fireball move fireball where I point"? Now your hand is engulfed in a fireball, whoops! Doing it this way would imply that magic is an interpreted language and executed on the fly, further limiting magic-assisted static analysis

  2. Syntax errors actually exist, because reality has a syntax, e.g. a caster tries a spell that violates some technical law of magic, e.g. a targeting verb must have at least one operator of a particular type (point in space, area, or volume). Now if there's a spell that doesn't specify a target, reality crashes (or at least a localized portion of it crashes). I would think that if your messing with spatial targeting and relationships, and you break the syntax then physical spatial relationships start breaking down, and stuff disintegrates. The extent and vigour of such "crashes" might be related to the amount of power put into the spell initially. Another magical syntax rule might be that "life force" must be conserved, i.e. you can't just set the number, you can only add or subtract from another life force pool, i.e. transfer. To heal one person, another must sacrifice their life force (voluntarily or otherwise). If you don't specify a source of life force, then all life force in a localized area is suddenly averaged out, injuries heal by taking equal portions of life force from everyone within the radius of the crash zone.

Summary

To answer your question directly, I don't think meta-magic programming should be impossible. Assuming you disallow high level primitives and symbolic introspection of magic, it will be hard enough, dangerous enough and expensive enough as it is to not develop rapidly. I would strongly suggest that you tie execution of a spell to some cost or resource, payable by the caster, e.g. You can sit down and design/write your spell source code as long as you want, but when you cast, your life force pays per clock cycle/instruction. This means that what makes a mage truly powerful is

  1. the ability to not make (or catch and correct before casting) mistakes in their source code
  2. the ability to write efficient source code (they can fling more fireballs per reality clock cycle)

Tying casting cost to spell efficiency is the key to keeping frameworks out of the picture, but you get to keep Turing completeness, reusable 'code' components, etc...

$\endgroup$
1
$\begingroup$

Software and even areas of study like symbolic logic, rely upon created "languages". The reason is that natural languages are too imprecise and inefficient for writing expressions in.

Following in that vein, you could force:

spell magic to rely upon natural languages only

This would make the development of magical expressions very much more difficult than getting to use a more precise invented language. How you would explain this limitation in a believable way is up to you :)

It's imprecision and "clunkiness" would limit what could be done with it pretty effectively. It also might mean that every person had the ability to "cast" a certain amount of magic. But only those that have studied for a long time would be capable of mastering the art.

IMO, this would make magical spells come to resemble legal documents (and wizards the equivalent of lawyers, lol!). Pages and pages of statements which few realize all the ramifications of.

$\endgroup$
1
$\begingroup$

Spells are limited to a specific rune count.

If spells had to fit in a tweet, there would be a limited set of operations you could do with them and you'd basically be forced to golf every spell. Granted, there might be hundreds or thousands of different runes at your disposal, but you won't be able to do anything beyond a certain complexity simply because of length limitations.

The end result would be a lot of specialized-purpose spells that make a lot of assumptions and not a lot of frameworks/libraries or customizable spells. You might be able to employ clever tricks to make every last rune count, but the most complex spell you could make would be something on the order of the original Pitfall. (Note that Pitfall wouldn't actually fit in a tweet, though it was crammed into 4KB, which is still very impressive)

$\endgroup$
1
$\begingroup$

If your goal is to ensure the magic isn't Turing Complete, there's two things you could omit:

  1. Conditional branching. Omitting this makes anything requiring a decision impossible. An infinite loop is still a possible construct, by using unconditional jumps, but one with an abort condition is not. This would essentially limit all decision-making to being done by the caster before casting. A magical security system which lets authorised people in would not be possible with this model. You could make a spell which generates a bubble of heat around whatever it's cast on, though.

  2. Storage. Omitting this results in a Finite State Machine. This pretty-much limits you to programming with regular expressions or state-machine diagrams. More useful than the former approach would be, but still limited in power.

For a gaming example of a non-turing-complete programming scenario, though sci-fi themed, rather than magic, take a look at SpaceChem. The reactors you design in the game are FSMs. They have a decision-making capability in the form of a sensor object which can report the type of atom over it, but they don't have any storage.

$\endgroup$

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .