Code center > Darwinbots3

Bot DNA

<< < (4/13) > >>

Numsgil:

--- Quote from: googlyeyesultra ---I humbly ask that you read this ridiculously long post.
--- End quote ---
Heh, you're in good company around here.


--- Quote ---Ultimately, for conditions, I'd like a multi-tiered system. At the top, we'd have root codules that would be executed every cycle. In those would be simple genes that called other codules. Thus, root codules to standard codules. Standard codules could and should link to a multitude of other standard codules.
--- End quote ---

That's what I'm thinking too.  I'd probably use something like a call stack to prevent infinite looping from indirect recursion.


--- Quote ---Then, in codules, genes should still have the "cond" statement to allow conditions to apply to all operations in that gene. Then, you could have conditions attached to each statement, like "*.nrg 1500 > 50 .repro store". One tricky bit would be deciding when the condition section ended, since we can't assume it ends at a store (some genes merely add values to the stack to be processed later). Perhaps a "condstop" operator could be used, of some sort, inside of the start/stop section of a gene. Essentially, it would look like "*.nrg 1500 > 50 .repro store condstop".

That would also mean that you could attach non-stores to conditions without creating lots of genes, like "*.eye5 0 > 50 mult condstop", which would multiply the top stack value by 50 and place that on the stack, if eye5 say something. It would also allow for easy nested conditionals, as the condstop could encompass multiple lines, if needed.
--- End quote ---

I was thinking something like a stack for booleans.  Which would allow some easy nesting of conditions.  Values could be combined using logical operators (and, or, etc.)

Something like:

--- Code: ---*.eye5 0 > *.refeye *.myeye = and 314 .aimdx store else *.revelup .up store
--- End code ---

Probably would need some stack manipulation commands for the boolean stack (duplication, popping, swapping maybe).


--- Quote ---To deal with shots, change .shoot to a universal shoot command. It would take the first to values on the stack to determine what kind of shot it was, and the second value to determine it's shootval. Essentially, shoot wouldn't need a store anymore. So a energy feeding shot with a shootval of 50 would be "50 -1 shoot". We'd probably have to do the same thing with quite a few other variables, and turn things into commands. Store, obviously, would still remain, for usage in any variables that don't support the command-ized form, or for free variables to store information. For multi-threading, perhaps we could do some sort of randomization for ones that don't mix well (so if codule1 tried to use an energy shot and codule2 tried to use a body shot, it would randomly choose one. Variables/commands that are more easily averaged (like up) could simply be averaged.
--- End quote ---

I've thought about making all the sysvars commands in the past.  It's an interesting idea, I might pursue it.  We could have some sysvars output into the boolean stack I was talking about above.

For shots, I'm thinking of splittling up the shoot command into several commands for different types of shots.  One sysvar for body shots, another for venom, etc.  For sysvars that don't average well, we could probably set up a voting system.


--- Quote ---I still think that raw gotos and gotosubs are essential. Say, if I've got a function that determines how much I should power up a shot. Perhaps a multi-gene one. I can't exactly wait until the end of the shooting gene/codule is over before I call that function. We could always disable these in mutations, and have a third command that would goto as soon as the gene/codule finished. Maybe gotoafter?

How will a bot react when it finishes a codule that has no goto commands? Will it automatically continue on to the next codule, or will it just end the program then? In theory, if the former is true, then could you end DNA execution early by creating a blank codule at the end of the DNA and call that?
--- End quote ---

I'm not sure what the name is of what I'm thinking (functional programming?), but basically you create a call graph from codule to codule.  At the end of a codule, control is returned to the calling codule.

Alternatively, I'm thinking of a top level graph, where maybe root codules execute and return control to one another.  But I dunno if it'll work right or not.


--- Quote ---If you split the .shoot into a plethora of things like .vshoot .wasteshoot .nrgshoot, .medicshoot, .infoshoot, .venomsoot, and .bodyshoot, what mechanism would be implemented to prevent me from firing every single one of them in one cycle? Essentially, bots could start throwing everything but the kitchen sink at their target and would no longer have to strategically decide which is better at a certain time.
--- End quote ---

I'm not sure yet.  We could make it prohibitively expensive, or maybe make a priority list.  I'm still working through how it would work.

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

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.

One way, of course, would be to combine the two options. Allow gotos, and after the codule called was completed, it would return to the codule that called it the line after the goto. Then, after that codule had completed, if it was called by the root, then the root would call it back.

So it would work like:
Root -> Codule1 -> Codule2 -> Codule3
Then, after codule three had completed:
Codule3 -> Codule2 -> Codule1 -> Root
(each codule being given a chance to finish before returning to the one that called it). Anyways, just my opinion.

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.

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.

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.

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.

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.

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.

Anyone reading this, please contribute to the discussion. Please. I think we probably need more than two or three people's inputs on such a radical and important change.

Jez:
I am following this Googlyeye, as best I can, codules and multi threading are a bit beyond my ken though!

I worry that the new code will be difficult for your average Joe to follow. Then again it was difficult reading the current code when I first started so that's probably not much of a problem.

Other than that the ability of bots to use tan or sin to accurately calculate trajectory and shot angle seems a bit more than the bots should have.

But I have trust in Nums ability to choose wisely, he has put a lot of work in to researching the ins and outs of different possibilities (as he is now). He's taken my opinion and ideas onboard in the past as he has with many other people. This is a thread about bots coding though and it's best left to people who have a good understanding of such things IMO.

Numsgil:

--- Quote from: googlyeyesultra ---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).
--- End quote ---

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.


--- Quote ---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.
--- End quote ---

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.


--- Quote ---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.
--- End quote ---

I think so, if I understand you right.


--- Quote ---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.
--- End quote ---

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.


--- Quote ---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.
--- End quote ---

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


--- Quote ---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.
--- End quote ---

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.


--- Quote ---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.
--- End quote ---

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:

--- Code: ---*.nrg 5000 > .Fifty call else .ten call
end

Fifty:
50
end

Ten:
10 end
--- End code ---

The code structure is similar to the way that genes work right now, but explicitly stated.


--- Code: ---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
  }
}
--- End code ---

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

googlyeyesultra:
Insta-fizzing anything that is already in the call stack isn't that useful. What if I need to run a formula at multiple points of a bot's code? If I only needed it once, then I could just copy and paste it in.

Alright, then, for multi-threading. Just for viruses and modeling, then.

I see what you mean by closing braces screwing up in mutations, but there isn't much of a choice if you want nested conditions. Besides, if messin' with the closing bracket is a deleterious mutation, the bot will likely die soon, and it wouldn't really matter.

As a side note, does the fact that you wrote the codule names in your example as text instead of numbers mean we will likely get to name our codules? Pretty pweases?

Navigation

[0] Message Index

[#] Next page

[*] Previous page

Go to full version