I'm not entirely sure how expensive you could make it. After all, with venom or info shots, I can force you to give me energy. Then I can use energy shots to feed. Then I can use body shots to feed. That's feeding three times as fast. How much are you thinkin' in terms of costs for shooting? It'd have to be exponential, because otherwise tieing would be the only real way to eat (or just biting their head off, if you're large enough).
Costs aren't my favorite option. I'll be revisiting the combat system in the future as well, adding some new combat ideas people've discussed over time. This may end up a moot point. Venom and poison, for instance, could be used as a method involved with
Phagocytosis. Meaning they wouldn't use shots as they do now. In the end it might turn out that there's only one or two shot types. It's an area I need to explore some more, but it's a bit off topic here so I'll save it for another time.
I could see control being returned to the root after every codule is completed, so long as it returns to the position that codule is called. It wouldn't be very powerful, but I could deal with it. Mostly would just need a lot more conditions and gotos in the root gene and less in other places. Not my particular style, but it would work either way.
I'm thinking a call stack. Codule A calls Codule B, which calls Codule C. When C is finished, it returns control to Codule B where it was called. And likewise with B to A. So a top level root codule could do some very gross conditions (do I see anything?), and then pass what to do in these cases on to codules.
I'm also imagining another system that works above this, the connects codules together in a large web structure. But I'm still on the fence about if it's a good idea and how it would work.
This is what you are thinking of, correct? If so, then I'd say we are now in agreement as to how codule calling should work.
I think so, if I understand you right.
With multi-threading, I still see little use to it, and if it were me, wouldn't bother programming it. Still, at least I can not use it should I want to. I am curious as what applications for multi-threading you were thinking of people using.
It's not so much for people. It's primarily for two areas: viruses and diploidness (IMO important for setting up sex that mirrors biology (which is a weak point IMO in other alife sims)). A virus would get injected as another thread. Runaway virus propogation would also be pretty easy to simulate, since you'd just have to count the number of identical viruses, run the virus once, and weight the results. This would be more complicated in the current system. There also wouldn't be the ordering issue of where in the genome a virus gets inserted like there is now. And for diploidness, you'd just end up running two versions of the same codule at first. Over time, though, the two identical threads would diverge, and you could implement some crossing-over to mix them. Haploid bots that "fuse" (this is basically how sex works for fungi and primitive plants) are basically agreeing to share control over a single body. Threads allow a reasonable and fair way to share control.
For bot authors, I can't imagine it making much of a difference one way or another.
Oh, and a bit earlier, I believe you mentioned something like "code defenses shouldn't be as useful, and should be replaced with better physical defenses". I don't remember the exact words, and I'm too lazy to look it up. I strongly disagree here. I should be able to place a superiorly coded bot into a sim and watch it win, even if the other, worse bots have built up significant amounts of slime, shell, etc. Essentially, code defenses don't cost much (only a store), but they only protect against 1 or 2 very specific things. However, if you just wanted a more generic defense, say, against all info shots, you could add in some shell or poison or whatever it is. If you wanted a specific defense against, say, Icarus' turning shot, then you could implement some code to protect against that.
The issue here is that the genome then becomes part of the phenotype. It's like using the blueprints for wallpaper in a building. I think it's good to create a degree of seperation between the body and the brain of a creature. The problem is that allowing a bot to, say, delete genes, or preempt a virus from working by being a single gene bot, is that it encourages the genomes to become rather monolithic. A single, huge, self policing, black box finite state machine. Nothing wrong with that per se, but it's just too dense for most people to decode and understand. I think we'd see better results if the genomes were more modular. If it wasn't a huge disadvantage to split computations into different discrete groups, it would allow less coupling between behaviors, and hopefully provide some extra wiggle room for evolution or authors.
When your DNA becomes part of the structure of a bot, I think it decreases readability. Though there's certainly an amount of fun writing code that makes others weep
In terms of preventing ridiculous numbers of loops, you could set it so that if a bot executes a single codule a certain large number of times in one cycle (1000? Larger?) then either that specific codule could be deleted, the codules that called it could be deleted, or the bot could be killed. I don't know which.
I've played around with these ideas, but none really satisfied me. I think the idea of "fizzling" a call to a codule if it's already in the call stack is the best. There are some really convoluted examples I can cook up that are truly terrifying if recursion (direct and indirect) was allowed with codules, even if its depth was restricted.
Related to looping, at the moment I'm playing with the idea of having a sort of event driven architecture for some DNA functions. Something like calling a codule with different arguments for everything in a bot's vision radius. Like the foreach loop in C#. I'm still working through how a bot would determine which cases to throw out and which to keep, but I think the idea of having some limited, hardwired looping is okay. It's just when the language allows bots to form loops in its DNA that things fall apart.
Your example of in-gene conditions (*.eye5 0 > *.refeye *.myeye = and 314 .aimdx store else *.revelup .up store) has some pluses and minuses. First of all, I like the ands and elses (and presumably elseifs, xors, ors, etc.) However, this assumes that after the last else you always want to stop at a store (or maybe it's the end of a line, but then you are making different forms of whitespace different, which is a big no-no. Like MUMPS. Bad, making whitespace different than whitespace). What if I just want to perform stack manipulations? Or if I want to perform multiple stores? We really need some sort of an operator that says "Stop checkin' this condition/this else." Else would also act as a condstop. Or are you assuming that it should follow the above condition until a new one is instated? That makes nesting impossible, however.
I was thinking something like a popbool command. Pops the top boolean off the stack. Have the bool stack default to true if there's nothing underneath. The only downside compared with how things are now is that you couldn't just issue a string of conditions and have them automatically be anded. The way something like this works, else and not are basically the same command.
And, compared with other methods, you couldn't use conditions to push specific values onto the regular stack. Something like *.nrg 5000 > 50 else 10 doesn't work (at least not as I'm imagining it at the moment). After all, you need that integer stack to stay active even when a condition evalutes to false so that you can set up for the next condition. Conditions don't so much cause the DNA parser to jump over parts of code (like it works now), but to cause certain key commands to "fizzle".
Of course, if we set up codule calls to work with conditions too, you could do something like this:
*.nrg 5000 > .Fifty call else .ten call
end
Fifty:
50
end
Ten:
10 end
The code structure is similar to the way that genes work right now, but explicitly stated.
Essentially, I'd like it something like the following:
*.eye5 0 > *.refeye *.myeye != and 50 -1 shoot else *.eye5 0 > *.refeye *.myeye = 20 .aimdx store *.eye5 30 > 30 .dn store condstop condstop
And here's the same thing commented:
*.eye5 0 > *.refeye *.myeye != and 'Checks that both eye5 is greater than 0 and that you aren't one of me.
50 -1 shoot 'Shoots an energy shot with a shootval of 50.
else 'Ends the previous condition, checks a new one that is equal to NOT the previous condition.
*.eye5 0 > *.refeye *.myeye = and 'If eye5 is greater than zero and you are one of me.
20 .aimdx store 'Turn.
*.eye5 30 > 'A nested condition. Activates if the else is true and eye5 is greater than 30.
30 .dn store 'Goes in reverse.
condstop 'Tells the nested condition that it's over.
condstop 'Tells the else condition that it's over.
[quote]
I'd like to move away from requiring a "closing brace" or something similar. They work fine when a human is writing, but when you get a random string of evolved DNA, a small change upstream can change the way an entire length of DNA is executed. Meaning it's very brittle.
Take, for instance:
[code]
A {
do things
}
B {
do things2
C {
do things 3
}
}
Now, remove A's closing brace. Suddenly B and C become nested entirely in A. B and C are totally at the mercy of A. Now, imagine that A, B and C are pushing and popping values from a stack, or something similar. Now B and C can remain in charge of themselves by not digging too far down the stack. If they want to AND with A's condition, they can. If not, it's as if B and C have formed their own cohesive gene that happens to be inside of A, but isn't influenced by it. There are still some issues with B and C interfering with A (by not cleaning up after themselves), so I think this still needs to be refined. But now nesting is at the control of the nester instead of the nestee (if you see what I mean). It gives strips of DNA stronger control over when and how they get expressed. Self determination from the tyranny of upstream DNA
Probably a dup command for the bool stack would be imperitive here, along with a pop command, to allow nested DNA to return the stack to the way it found it. Or maybe I can come up with something similar to the OpenGL Matrix stack operations, where you can push and pop matricies. (Push the bool stack, and you get a new empty stack that defaults to the top value of the old stack. Pop the stack, and you get back your old stack. Like a stack of stacks.)