Author Topic: Bot DNA  (Read 19584 times)

Offline Numsgil

  • Administrator
  • Bot God
  • *****
  • Posts: 7742
    • View Profile
Bot DNA
« Reply #15 on: July 18, 2007, 12:15:52 AM »
Quote from: googlyeyesultra
I humbly ask that you read this ridiculously long post.
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.

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.

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: [Select]
*.eye5 0 > *.refeye *.myeye = and 314 .aimdx store else *.revelup .up store
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.

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?

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.

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.

Offline googlyeyesultra

  • Bot Destroyer
  • ***
  • Posts: 109
    • View Profile
Bot DNA
« Reply #16 on: July 18, 2007, 01:54:43 AM »
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.
« Last Edit: July 18, 2007, 04:52:33 AM by googlyeyesultra »

Offline Jez

  • Bot Overlord
  • ****
  • Posts: 788
    • View Profile
Bot DNA
« Reply #17 on: July 18, 2007, 06:02:30 AM »
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.
If you try and take a cat apart to see how it works, the first thing you have in your hands is a non-working cat.
Douglas Adams

Offline Numsgil

  • Administrator
  • Bot God
  • *****
  • Posts: 7742
    • View Profile
Bot DNA
« Reply #18 on: July 18, 2007, 07:54:51 AM »
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).

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.

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.

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.

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.

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.

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.

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: [Select]
*.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.

Code: [Select]
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.)

Offline googlyeyesultra

  • Bot Destroyer
  • ***
  • Posts: 109
    • View Profile
Bot DNA
« Reply #19 on: July 18, 2007, 08:43:32 AM »
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?
« Last Edit: July 18, 2007, 08:45:43 AM by googlyeyesultra »

Offline Numsgil

  • Administrator
  • Bot God
  • *****
  • Posts: 7742
    • View Profile
Bot DNA
« Reply #20 on: July 18, 2007, 10:51:07 PM »
Quote from: 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.

Remember that it's a call stack.  Meaning that once a codule returns control to the calling codule, it's popped from the stack.  Something like this would work just fine:
Code: [Select]
10 DoStuff 20 DoStuff 30 DoStuff
You just want to prevent something like this:
Code: [Select]
DoStuff:
5 sub DoStuff

Recursion = very, very bad.  It shouldn't limit the DNA that much.  Recursive functions can be rewritten using iterative versions without too much effort usually.

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

Depends on how you define nested.  If you see it as one condition checking previous conditions, I think it's possible.

Quote
Besides, if messin' with the closing bracket is a deleterious mutation, the bot will likely die soon, and it wouldn't really matter.

Most mutations are bad, but if we can reduce the number of bad mutations without limiting the expressiveness of the language, I think we'll see some better evo sims.

Quote
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?

Part of me really wants this.  You could basically write some custom codules that act like any missing math functions, and there wouldn't be any difference between them and the default ones.  You could write a custom distance function, for instance.  You could just call it with something like 0 30 10 20 dist and it would find the distance between <0,30> and <10,20>.

On the other hand, evo bots aren't going to be inventing reasonable names anytime soon.  It'll probably work like sysvars.  Custom labels that are called, but that evaluate to numbers.  I still have to work out the best way to do it I think.

Offline googlyeyesultra

  • Bot Destroyer
  • ***
  • Posts: 109
    • View Profile
Bot DNA
« Reply #21 on: July 19, 2007, 12:00:26 AM »
We could totally program in evobots a series of possible codule names. Would be hilarious.

Like:
cond
start
call Darwinbots_Awesome_>
stop

It would crack me up if I saw evobots naming codules like that.

Offline Numsgil

  • Administrator
  • Bot God
  • *****
  • Posts: 7742
    • View Profile
Bot DNA
« Reply #22 on: July 19, 2007, 05:53:25 AM »
Heh, I can just imagine

Offline googlyeyesultra

  • Bot Destroyer
  • ***
  • Posts: 109
    • View Profile
Bot DNA
« Reply #23 on: July 19, 2007, 06:22:40 AM »
Furthering the discussion on physical defenses or code defenses, code defenses does NOT necessarily mean illegibility. They can be as simple as zeroing things that you aren't using if your gene count goes up. Honestly, I agree. Stab the SG bots. However, code defenses really ought to stay. It would take a lot of ingenuity, for instance, to make a bot that could recognize when it had been turned by an info shot (maybe by storing how much it turned last turn into a free var and the same with last turn's orientation, and if it didn't fit right, turn back). Seriously, we should be promoting ingenuity, not demoting it. It's a lot more fun to see bots using complex behaviors to protect against things like this (especially since a lot of attacks specifically attack behaviors, ala info shots and viruses), then it is to just write 100 .mkslime store. Still, those are just my own (rather strong) viewpoints.

Custom labels would work, probably. You could also just make evobots name the codules from a list, which, could either as an easter egg be populated with joke names, or they could just be things like a, b, aa, etc. Either would honestly work, but defining codule names wouldn't allow any funny easter eggs in the game, would it?

Understanding your idea on the call stack makes a lot of sense, now. I agree with that approach (Why do I feel like I'm being converted, somehow?).

You also mentioned that nested conditions could be done without ending braces. The only way I can think of this would be having ridiculous numbers of codules pointing at each other, each representing one condition. Kinda like programming nested if-then-elses on my TI-83: you can do it, but only if you jury-rig it with a boatload of goto commands.

In terms of pop and push commands for recalling old stacks... It'd have to entirely repopulate the stack multiple times in one cycle for each and every bot if someone wrote something that called the pop command multiple times. I don't know if this would be a major performance hit, but even a small one, with enough bots doing it, would be kinda awful.

Offline Numsgil

  • Administrator
  • Bot God
  • *****
  • Posts: 7742
    • View Profile
Bot DNA
« Reply #24 on: July 19, 2007, 08:49:12 AM »
Quote from: googlyeyesultra
Furthering the discussion on physical defenses or code defenses, code defenses does NOT necessarily mean illegibility. They can be as simple as zeroing things that you aren't using if your gene count goes up. Honestly, I agree. Stab the SG bots. However, code defenses really ought to stay. It would take a lot of ingenuity, for instance, to make a bot that could recognize when it had been turned by an info shot (maybe by storing how much it turned last turn into a free var and the same with last turn's orientation, and if it didn't fit right, turn back). Seriously, we should be promoting ingenuity, not demoting it. It's a lot more fun to see bots using complex behaviors to protect against things like this (especially since a lot of attacks specifically attack behaviors, ala info shots and viruses), then it is to just write 100 .mkslime store. Still, those are just my own (rather strong) viewpoints.

Those aren't so much the defenses I'm concerned about.  That tends to be more cleaning up after the damage has been done.  It's things where there's two equally valid ways to write a feature for your bot, and you choose to write it in a more obscure way because it gives you an advantage against viruses or something else similar.  Don't use any eyes (but still read from the eye locations) so it looks like you're a veggy, for instance.  SGing your bot so that it's stronger against viruses is another example.  I'd like to section the DNA away from the body so that these aren't really issues anymore.  Info shots and viruses are still going to wreck havoc inside the genome, but you can deal with that damage in many ways.  Primary defenses on the outside, cleanup work on the inside.

Quote
Custom labels would work, probably. You could also just make evobots name the codules from a list, which, could either as an easter egg be populated with joke names, or they could just be things like a, b, aa, etc. Either would honestly work, but defining codule names wouldn't allow any funny easter eggs in the game, would it?

I'll see what I can do

Quote
Understanding your idea on the call stack makes a lot of sense, now. I agree with that approach (Why do I feel like I'm being converted, somehow?).

That is a danger of debating with me.  I'm pretty good at this

Quote
You also mentioned that nested conditions could be done without ending braces. The only way I can think of this would be having ridiculous numbers of codules pointing at each other, each representing one condition. Kinda like programming nested if-then-elses on my TI-83: you can do it, but only if you jury-rig it with a boatload of goto commands.

In terms of pop and push commands for recalling old stacks... It'd have to entirely repopulate the stack multiple times in one cycle for each and every bot if someone wrote something that called the pop command multiple times. I don't know if this would be a major performance hit, but even a small one, with enough bots doing it, would be kinda awful.

The way the program works, things like physics and bot vision are going to take like 98% of the CPU time for larger sims, because they have a O(n log n) growth curve (when they're optimized, O(n^2) otherwise).  In general, it's not worth sweating things that happens a constant number of times per bot.  It just hardly impacts the simulation speed.  Of course, a 15K bp monstrousity is something of an exception to that rule

But if the DNA is expressive enough you should be able to collapse that down anyway.

Here's an imaginary sample of using pushbool and popbool that simulates nesting:

Quote
*.nrg 5000 >

'basically a nested condition:
pushbool 'save a copy of the current bool stack and start a new one
*.eye5 0 = and
50 .repro store
else '(could also use "not".  Same thing)
100 .dn store
popbool 'restore the saved copy of the bool stack

10 .strbody store

Now, suppose that nested condition decides (through a fortuitous mutation) that it doesn't want to be nested anymore.  The above code turns into:
Quote
*.nrg 5000 >
 
 'basically a nested condition:
 pushbool 'save a copy of the current bool stack and start a new one
 *.eye5 0 =
 50 .repro store
 else '(could also use "not".  Same thing)
 100 .dn store
 popbool 'restore the saved copy of the bool stack
 
 10 .strbody store

And the original code could also be rewritten as:
Code: [Select]
  *.nrg 5000 >
  
  'basically a nested condition:
  pushbool 'save a copy of the current bool stack and start a new one
A
  popbool 'restore the saved copy of the bool stack
  
  10 .strbody store
end

A:
*.eye5 0 =
   50 .repro store
   else '(could also use "not".  Same thing)
   100 .dn store

To simulate a more human like method of coding.  The primary weakness is that you have to remember to both push and pop the conditions stack.  It's not necessarily reasonable to assume that evolution would always use them in pairs.  Of course, evolution might not even like to use strictly nested conditions like this, so it's hard to say.

It's still related to a closing brace, but it inverts the control structure.  Hope I've explained it well.

As a summary example, this shows a shorter method of writing the above that achieves the same effect, but without the need to push and pop the bool stack.

Quote
*.nrg 5000 >

'basically a nested condition:
dupbool 'duplicates the top boolean value in the bool stack
*.eye5 0 = and
50 .repro store
else '(could also use "not".  Same thing)
100 .dn store
'clear the top value in the bool stack

10 .strbody store

Not sure if we'd need a new command to clear the top value in the bool stack or if we could do it using AND, OR, NOT and XOR.
« Last Edit: July 19, 2007, 08:52:40 AM by Numsgil »

Offline googlyeyesultra

  • Bot Destroyer
  • ***
  • Posts: 109
    • View Profile
Bot DNA
« Reply #25 on: July 19, 2007, 09:17:57 AM »
I fail to see how doubling the number of commands a mutated bot needs to successfully nest conditions would actually reduce problems. Seriously, if it's gotta put pushbool in the right place, and popbool in the right place, wouldn't it be easier just to put one closing-brace esque command in the right place? I mean, the code would work, but it seems like an awfully complicated system. I thought we were trying to make it simpler so that mutations could actually have a chance?

In short (kindof), it's a neat solution, but I don't see how it would improve from the more basic option. I'd think that it'd be less intuitive for humans and harder for evo-bots to develop.

Offline Trafalgar

  • Bot Destroyer
  • ***
  • Posts: 122
    • View Profile
Bot DNA
« Reply #26 on: July 19, 2007, 09:29:01 AM »
Quote from: Numsgil
Not sure if we'd need a new command to clear the top value in the bool stack or if we could do it using AND, OR, NOT and XOR.

I don't think you could really pop something with just those.

The way I pop something on the regular stack is 'dup xor inc', or if I need to pop several things at once, I put adds (though ands, ors, or whatever would work too) before that statement. To pop 3 things: add add dup xor inc

(dup xor zeroes whatever's on the top of the stack, so that the inc will be working on no memory location)
« Last Edit: July 19, 2007, 09:30:05 AM by Trafalgar »

Offline Numsgil

  • Administrator
  • Bot God
  • *****
  • Posts: 7742
    • View Profile
Bot DNA
« Reply #27 on: July 19, 2007, 09:23:52 PM »
Quote from: googlyeyesultra
I fail to see how doubling the number of commands a mutated bot needs to successfully nest conditions would actually reduce problems. Seriously, if it's gotta put pushbool in the right place, and popbool in the right place, wouldn't it be easier just to put one closing-brace esque command in the right place? I mean, the code would work, but it seems like an awfully complicated system. I thought we were trying to make it simpler so that mutations could actually have a chance?

In short (kindof), it's a neat solution, but I don't see how it would improve from the more basic option. I'd think that it'd be less intuitive for humans and harder for evo-bots to develop.

It's actually not that different from a closing brace type system.  The pushbool and popbool are like opening and closing braces.  Primarily the difference is a matter of control.  In a more conventional system, condition A is commanding condition B on wether it can execute or not.  In this system, condition A is suggesting to condition B wether it should execute or not.  It's the job of condition B to follow that suggestion or not.

If we wanted multiple conditions in a single block, you would still need an opening brace to show that you're starting the body of the condition.  And if yoo lose a closing brace, then the entire genome beneath you becomes part of your condition.

I'm not so much trying to find the easiest method for nested conditions.  I'm trying to find a method for nesting conditions that is robust to mutations.  Take the current system.  If you had:

Code: [Select]
cond
start

cond
start

cond
start

And you lost the second cond, it just means that the second gene gets controlled by the condition right above it.  Mutations don't end up effecting global changes in the flow the DNA.

Offline googlyeyesultra

  • Bot Destroyer
  • ***
  • Posts: 109
    • View Profile
Bot DNA
« Reply #28 on: July 20, 2007, 12:17:30 PM »
I've just been thinking. . . Does it matter so much how we implement nested conditions? After all, mutations will almost never evolve conditions, much less complex/nested ones, and conditionals are often the first things to break. That is, unless you are planning a major overhaul in that respect, bots will break conditions, no matter how you nest 'em.

Offline Endy

  • Bot Overlord
  • ****
  • Posts: 852
    • View Profile
Bot DNA
« Reply #29 on: August 02, 2007, 05:48:52 AM »
They don't really break every single condition, some conditions are just too dangerous for them to break. The reproduction and turning conditions usually last forever. Other stuff like shooting constantly makes sense if there's enough food around. Breaking things like defense storage makes since they're surrounded by "friendlies" most of the time.

I do think "equals" might be highly susceptable to mutations. Basically it's less likely two random numbers are going to be equal than it is that one is going to be greater or less than the other. Either the condition will be broken or the "equals" will be changed.  Think alot of our problems stem from a disconnect between human and evolutionary logic. Evolution is based on likely/unlikely probabilities, human logic is based on certainity.