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:
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.