Simple Bot

From WikiManual
Jump to: navigation, search
'Simplebot 1
'Gene 1. Simple search pattern part 1 
cond
*.eye3 *.eye5 >
start -25 .aimdx store
stop
'Gene 2. Simple search pattern part 2
cond 
*.eye7 *.eye5 >
start
25 .aimdx store
stop

'Gene 3. Move forward
cond
start
5 .up store
stop

'Gene4. Shoot the food
cond 
*.eye5 40 >
start
-1 .shoot store
stop

'Gene 5. Reproduce
cond
*.nrg 5000 >
start
50 .repro store
stop

end

Available as Simplebot1.txt

If you try this little robot out you will discover very quickly that it really isn't very good. It finds food reasonably well providing it is fairly near to the center of it's field of vision. It even feeds and reproduces OK so what is it that makes this little guy so totally useless?

His main problem is that he can't tell the difference between food and friends so he eats everything he sees, including his children / parents.

We can easily fix this little problem by adding a new gene to make him avoid his own family. Try adding this gene to the robot. Doesn't matter where you put it as long as it is after the two search pattern genes. That is because this gene also uses .aimdx to rotate the robot. Whichever gene we want to take priority must always come last. As avoiding conspecifics is more important than finding food (including conspecifics) we have to put it later in the genome. For now, just type in the gene right at the end. (make sure you put it before the "end" statement though.) When you have typed it in and saved the file, restart the simulation and see how Simplebot has changed.

'Gene 6. Avoid conspecifics cond *.refeye 5 = start 180 .aimdx store stop Available as Simplebot2.txt

See how much more efficient he is now? We have turned a pretty useless little robot into a pretty good one. He already beats the heck out of some of the more basic robots such as C-Ancestralis and even gives good old Preservans a good run. With a few minor alterations, we could probably make him really good. Let the program run for a couple of thousand cycles and see what the population reaches. He should max out at around 120 or so. The only problem is that he won't stop spinning around all the time. Why is that? And why does he only stop spinning when there is food nearby?

The reason he spins is that *.refeye does NOT get refreshed in each cycle of the program. This means that once our robot sets eyes on one of his own family, he just keeps on seeing the same thing every cycle until something different crosses his field of view. This can be a real pain sometimes but with a bit of careful thought and some clever programming you can make very good use of this seemingly nasty bug in the program. Check out the top robots such as Devincio Eversor and Vex Pefidiosus and you will find this feature exploited mercilessly to create a world beater.

Do we really want our little Simplebot to keep spinning around or don't we? I propose that we explore both possibilities to see which one works out best.

The NON-Spinning approach. OK then. How do we stop Simplebot from spinning? We need to make sure that the new gene that makes him spin is only activated under certain circumstances and not all the time. We put the gene in to make him turn away from his family members so I guess we need to make sure he only turns when he is actually looking at one of them and not at a permanent afterimage.

Try adding the following line to the condition section of gene 6.

  • .eye5 0 >

You will also need to change the value of the other line in this gene from.

This is because we have added another eye cell to the genome. Save the file and restart the simulation again. Let it run for a couple of thousand cycles to see what the robot population reaches. It should max out at around 115 if the veg reseed value is set to 10. That is a little worse but still pretty respectable.

Do you notice how some of the robots are going !!POOF!! every now and then for apparently no reason whatsoever? They are obviously running out of energy and dying. Try pausing the program then double clicking one of them. Try to choose one that is right out in the middle of nowhere. That way it won't be trying to change direction. This will bring up an information box showing energy and a few other useful things about the robot. Click the button marked "Open console" and a new box will open. Drag it away from the first box so that you can see the robot's energy value. Remember this number. Now click on the button with the circular arrow. This will run the entire program for one cycle. Do this a few times and note how much energy Simplebot is expending just to stay alive and search for food. He loses a little over six energy points every single cycle. We really need to improve that a lot. Now, where do you think that Simplebot expends the most energy?

The food finding routines are pretty cheap. He only has a couple of conditions which cost 0.02 each and a single store command which costs 2. Anyway our robot can't see anything at the moment so it isn't rotating at all. About the only thing he is doing is moving forward. Well he isn't actually moving as such. What he is actually doing is accelerating in the direction in which he is facing. Go to the bottom line in the console window and type in ".vel" then press return. If your robot is at full speed the console will output a value of 30. Cycle it forward once more and look again. It's still 30 isn't it? How much did we just put into the .up location? 5 wasn't it? Yet he is still going the same speed. That is because 30 is as high as you can go in DB. Perhaps we need to add a condition to stop Simplebot from accelerating at all when he is already at a velocity of 30. We presently don't have a condition at all in gene 3. He just moves at every cycle. Try adding the following to the condition part of gene 3.

Now save the Simplebot file and restart the simulation. Open up the console as before and take a look at his energy expenditure now. He hardly uses any at all does he? About once every 4 or five cycles he boosts his speed by five points to keep his speed up but the rest of the time he just coasts along. Even this isn't really satisfactory though. He still spends five points on acceleration when he only really needs to use one. How can we fix that? Why not let him run for a couple of thousand cycles to see how high the population gets while we think about possible improvements. He reaches about 145 robots on my system. That is quite an improvement over the previous number.

So how do we improve him still further?

Maybe there is some way we can use the value in .vel to calculate a suitable acceleration automatically. That would let Simplebot accelerate really hard when he needs to and cruise effortlessly once he reaches a good speed.

Try changing the action line in gene 3 from..

5 .up store to 30 *.vel sub .up store Available as Simplebot5.txt

What does this line do? Well first we need to remember the order in which these calculations are carried out in Reverse Polish Notation. First we place 30 onto the top of the stack just by typing in the number 30. next we place the value stored in the memory location pointed at by the label .vel onto the stack. The * in front of the label means that we are using the value in the location rather than the number of the location. So now the stack has 2 numbers in it. First there is 30 then there is whatever value *.vel represents. The next thing we see in the code is the word sub. This tells the program to subtract the top number in the stack from the next number in the stack. In doing so both numbers are removed from the stack. The result of the subtraction is then placed on top of the stack again. So in effect we could have written something like a = 30 - *.vel if we had been using algebra. Next we take the number on top of the stack and move it to the .up memory location by using the store command.

Try it out and see what happens. Oh Dear! It seems that Simplebot's overall efficiency has gone down a lot. He only reaches about 70-80 population now. I wonder why that last idea didn't work? It seemed like a really good idea. Let's go in and look at a close up of a robot again to see how much energy he is expending each cycle. Well when he is out hunting it looks pretty good but look what happens when he reproduces. Both the parent and the offspring seem to engage in a tug of war until either one of them dies of exhaustion or the reproduction tie disappears after the gestation period. During this tugging phase they both expend around 30 points of energy each cycle. Work it out. Velocity is pretty close to zero so 30 + 0 = 30 doesn't it. This is going to be tricky to fix. OK then. We either have to cut short the gestation period or stop the robots from pulling on the tie. We can actually do either one but cutting short the gestation period is something to be addressed much later. For now let's figure out a way to stop them pulling on the tie and wasting 30 energy points each cycle. Any ideas?

No? Well here is one possible way to address the problem. We just stop the acceleration while ties are present. Luckily we have an easy way to detect the presence of ties with the new .numties function. This function automatically places a value into the .numties memory position every cycle so all we have to do is read it.

Try adding this line to the condition part of gene 3, right underneath the *.vel 30 < line.

This will prevent the activation of the gene as long as there are any ties attached to the robot. Load up your new version and try it out. AAH! That's better. Now they don't rip each other to pieces when they reproduce. They just drift along until the tie dissolves then they fly off to find food. They still only get up to about 120 robots though so they aren't any better than they used to be. Why is that? The reason is that once there are enough simplebots floating around the screen then they tend to see each other quite often. Every time they do so, they change direction so their forward velocity is no longer 30. This means that they will accelerate at whatever rate it takes in order to get up to full speed again. This is quite a useful feature when dogfighting with another species of robot but is counterproductive when trying to get top movement and feeding efficiency.

There are a number of ways to substantially improve Simplebot6. These include improving his food finding genes, possibly by adding an extra 2 genes to look at wider angle eyes such as *.eye1 and *.eye9. Look at the chart in appendix 2 to see where the eyes are able to see and which course changes to apply to .aimdx or .aimsx. You could also experiment with his acceleration genes by dividing the acceleration amount by 2 or 3 so he expends less energy.

Why don't you try developing Simplebot6 a little for yourself before continuing with this tutorial.

The Spinning Approach Well. That will do for the straight swimmer approach. Now let's take a look at the spinning approach. How do we make Simplebot spin again? Easy. Just take out the *.eye5 0 > line from gene 6 and change the .refeye value back to 5. This will reset his conspecifics sensing after removing the eye5 function. Try this out yourself or just load up simplebot8.txt and let him run for a while. He isn't very good again is he? Why is that? He was better than this before when he was in spinning mode. When you have finished tearing out handfuls of your own hair, have a really good look at the way he spins. There is something not quite right about it. Can you see what? Yup! That's it. He is constantly accelerating as he spins. He must be moving at less than 30 velocity. Duh! Course he is. He is spinning around on the spot isn't he so how fast could he be going? We have to go in and change that acceleration gene again. I know! Let's add the same condition to the acceleration gene as the one that makes him spin, except in reverse. We only let him accelerate when the value in .refeye DOESN'T equal 5. Add this line to the condition step of gene 3. and run Simplebot again.

That is much better isn't it. He spins perfectly now and hardly expends any energy at all while he is doing it. He effectively goes into a kind of shut down state and waits for food to drift by then pounces on it when it does. The little guy easily reaches 170 individuals in less than 2000 cycles. Just for fun let's add one of the old top bots to the fray and see what happens.

I CHOOSE YOU I_FLAMMA Sorry. Been watching too much Pokemon.

Just load up I_Flamma. Give him a different color than Simplebot9 and 5 individuals at 3000 starting energy. Disable his mutation and start the simulation. Now let them fight it out for a while.

Our little Simplebots dont do too badly but in the end, the flaming ones beat them all. Dont worry we will get our revenge a little later.

What do you think the reason is that Simplebot loses? One thing I notice is that his food search pattern is too narrow so he isn't aggressive enough in chasing down his food or his enemy. Another thing is that trick that we added a while back to stop him pulling on his ties. That dormant period isn't working out too well with competition on the field. First of all let's go back and delete the *.numties 0 = line in gene 3. The next thing we will do is to reduce Simplebot's acceleration a little bit. That will allow him to tug on his ties a little longer without depleting his energy reserves. Change the action line in gene 3 from 30 *.vel sub .up store to 30 *.vel sub 2 div .up store. This will divide his acceleration in half before it is applied to the .up command. Available as Simplebot10.txt

Simplebot still loses out to I_Flamma. OK then. Let's try adding a couple more food finding genes and see where that gets us. Add the following two genes to the end of the genome.

' Gene 7 wide search 1 cond *.eye1 *.eye5 > start -100 .aimdx store stop

' Gene 8 wide search 2 cond *.eye9 *.eye5 > start 100 .aimdx store stop Available as Simplebot11.txt

Why do you think we are comparing the outer eyes (1 and 9) with the central eye (5)? It is because we dont want simplebot rotating when he has a victim in the middle of his sights already. By only turning if .eye1 or .eye9 are bigger than .eye5 we make sure that doesn't happen Try it out and see what happens. Not very good is it? Simplebot eats his own kind again just like he used to in the early days. Why is that? It is because we added 4 more eye functions without changing the .refeye function to allow for it. We need to go back and change the .refeye functions in gene 3 and gene 6 from 5 to 9. Available as Simplebot12.txt

Either make the changes or load up simplebot12.txt and start the simulation again. If you loaded simplebot12 then make sure that you disabled mutations. WOW! That made a lot of difference didn't it. Simplebot12 whooped I_Flamma completely. Amazing! And there is still at least one major flaw in his design. Anyone spotted it yet? Let him carry on for a few thousand cycles to see what his population reaches while you think about it.

Look carefully at the way he searches for food. Check it by cycling through the console as he approaches a veg. You will often see gene one activate to rotate him a small amount toward his target then gene 7 will also activate to rotate him a lot. The result is that gene 7, which is situated later in the genome than gene 1, place its value into the same .aimdx location that gene 1 already did. Since only one value can exist in .aimdx (or any other memory location) at any one time, the gene 7 value overwrites the smaller gene 1 value. Think about it a bit and you will see that the smaller gene 1 value is the one that needs to be set last. It is far more important to home in on a target near to the center of the field of vision than it is turn towards one in peripheral vision when there is already one near to the center. We obviously need to cut and paste those two new genes so that we can put them before the first two. Go ahead and do that but first let's take a look at simplebot12's population. It is up to about 170 again. Pretty good but we can do better. Try moving the two genes as described above if you haven't already. Alternatively just load up Simplebot13.txt

Run the simulation again. Poor old Flamma doesn't stand a chance does he? We are still at around 170 robots after 5000 cycles though. This is because all we really changed was simplebot's hunting efficiency. This means he makes a much better start and is more aggressive than he was but once the robot / veg population ratio reaches an equilibrium point this aggressive behaviour doesn't help much any more.

We could try fine tuning the rotation rates and maybe change the acceleration rate too but we aren't going to squeeze much more out of our simplebot with simple coding. If we want to improve him further then we are going to have to get technical.

ADVANCED PROGRAMMING!

This is where things start to get fun. We are going to play around with some of simplebot's personality traits and we are going to teach him how to improve his efficiency at the expense of all around him.

First of all though I want you to think about this question. What is it that really stops simplebot's population from growing further?

The answer is simple too. He still expends too much energy, a lot of the time, just to keep living. He is also fraught with inefficiencies.

Where does that energy get spent? All over the place. That's where. Every store command that is executed costs 2 energy and every point put into acceleration (.up .dn .dx .sx) costs one point of energy too. Simplebot needs to go on a diet.

Take a look at the way he steers. We now have 4 steering genes placing values into .aimdx. Sometimes they might all activate in the same cycle. In such a case all 4 store commands are executed and each will cost him 2 energy. That's 8 points of energy in one cycle. On top of that what if he also sees one of his own family out there and stores 180 into .aimdx as well. That make 10 points just to spin on the spot. That sucks.

How do we fix that? Well first we have to make absolutely sure of the order in which all of our steering commands are placed. We have pretty much done that already but let's just recap it. We need to decide the hierarchy of the turning controls then place them with the lowest priority at the start of the genome and higher priorities later in the genome where they will overwrite the earlier ones. The priorities are as follows.

null null null null sure that if simplebot is already facing food then he does not turn at all. null nullnullnull 2. Avoid conspecifics. If this is overwritten then simplebot will just chase his family around and waste energy. 3. Turn toward food near to the center of his field of vision. 4. Turn toward food at the outer edges of his field of vision. Number 1 is new isn't it. We haven't directly addressed that one yet except to compare the eye cells with .eye5. That is usually all it takes unless we want to tell simplebot not to turn at all as long as something is in his .eye5 cell. We could easily add a gene to do that but for the moment we won't.

What we are going to do is to delve deep into the dynamics of the stack so that we can avoid all those store commands. Do you all remember what the stack is? It is a convenient area that each robot has, where he can place numbers in order to manipulate them at a later time. Normally that time is immediately after placing them. But it doesn't have to be, does it?

The stack is a LIFO (Last In First Out) structure that can hold up to 20 values at a given time. Once the stack is full then extra values just fall off to be lost forever. This is known as an overflow. It doesn't cause crashes within DarwinBots because the software has been designed to allow for these occurrences.

All we need to do is figure out how to put values into the stack in such a way as to make sure that the correct one is on top when we need to use it. Think about it. Each of these expensive store commands could be replaced by code that will place a value into the stack, then at the right time we can just use the top value to store into .aimdx. That's right, we can't avoid the store command altogether but we can make the genome a whole lot cheaper by just using it once to cover all of the possible rotation commands throughout the whole genome. But surely if we just keep putting values into the stack then it will fill up before long. That is where we have to get clever. Each time we put a value in, we also have to take one out. I will show you how to alter gene 7 (now the first gene in the genome) then you can alter all the others yourself.

Change.

' Gene 7 wide search 1 cond *.eye1 *.eye5 > start -100 .aimdx store stop

into

' Gene 7 wide search 1 cond *.eye1 *.eye5 > start mult -100 stop

Simple, isn't it? The mult operator takes the top two numbers in the stack, multiplies them together then puts the result back onto the stack. Two numbers become one so we have effectively removed the top number. There is no way in the gene code to actually remove a number without doing something with it so this is the best we can do. If this gene is activated then it leaves 100 as the top number on the stack without costing us a thing in energy. Go ahead and do the same thing with all the other steering genes and don't forget the one where simplebot avoids conspecifics.

Finished? OK then. Dont try simplebot out just yet. He won't work properly. There isn't a single .aimdx command left in his genome any more. We need to add another gene. Place this gene:

' gene 9 perform the rotation start .aimdx store stop

..at the end of the genome. It has to be after every one of our modified genes for it to work. Finish off the modifications and start up the simulation again. Of course you could always just load up Simplebot14.txt instead but that would just be lazy wouldn't it?

I am beginning to feel a little sorry for poor old I_Flamma. He is just getting his butt kicked up and down the screen all the time. So how is our population doing this time? It got up there around 170-180 pretty quickly but still seems to be rising a little bit. Looks like it topped out around 195. Not bad.

Hey! I just realized that simplebot is way up there on the Formula 2 league table by now. Perhaps we need to move on to the next rung. Try deleting I_Flamma and putting in I_Venia instead then run the simulation again.

Well that was a bit more of a battle. I_Venia came out on top eventually but simplebot put up a good fight.

Let's go back and really have a good look at how simplebot behaves. Just watch the program until one of the simplebots locks onto a veg then pause the game, double click the robot and open the console. Just step the program through a few cycles and watch the gene activations. He keeps reaching 5000 energy and attempting to reproduce. No baby appears but his energy still drops quite a bit. This is very inefficient behavior and need to be sorted out. How though?

Take a good look at gene 5 (the reproduction gene). The only condition to breeding is if the energy is high enough. Simplebot tries to reproduce when he doesn't have the space to do so. We can fix this in several ways but first let's try adding this line to gene 5 conditions.

  • .eye5 40 <

Don't forget that we now have 10 eye cells so you also have to change the .refeye functions too. Why not just load up Simplebot15.txt and save yourself the trouble of changing it all. Go on. I know you want to.

Well that really made a huge difference didn't it. No more energy wasted and the babies are that much stronger immediately after birth because the parent had more energy to start with. This also makes them better at fighting I_Venia and it's nasty secret leach weapon. But that's quite alright Mr. Infinite Forgiveness (Canada >_>) because Simplebot just whipped your butt and moved another rung up the ladder. That puts him in second place behind Circumversor Algificus if I'm not very much mistaken. The good thing is that I am SOOOOO not out of tricks yet. Up to now all we've really done is to streamline everything.

So where do you think the next weak point is in simplebot's genome? Well I think it is in the reproduction cycle. For 20 cycles the parent and child are tied together and are both unable to hunt efficiently. Why don't we just mess that up a bit with some clever programming. This is going to be simplebot's final improvement but it will be a BIG one. It involves some fairly complex concepts.

We are going to start by adding two new genes. Place them anywhere you like.

' Gene 10 tie to parent cond *.robage 0 = start .tie inc stop

' Gene 11 sever tie to parent cond *.robage 1 = start .delti inc stop

Note the free energy tie firing and deleting by using inc instead of store to place a value of 1 into both of these commands. All babies are born facing their parent and attached by a tie with a value of 0. We can't directly delete this as the tie deletion routine requires a non-zero value in .deltie. We have to find a way around it then. What we do is to make the first act of the new baby (*.robage 0 =) robot, to fire a tie at his parent. This overlays the existing tie and since only one tie can exist between any two robots the zero tie is now gone. The next thing the baby does on the following cycle (*.robage 1 =) is to delete his tie. This concept would be cool on its own but we aren't going to stop there. Go back to the reproduction gene and add these two lines to the action step.

mult 628 50 inc

Why? You ask. Well the first line should be obvious by now. We are making simplebot rotate by a value of 628 (or 180 degrees). Since reproduction, shooting, tie firing and just about everything takes place after rotation on each cycle, this means that simplebot will rotate 180 degrees then pop out a baby. The 50 inc line is a bit less obvious. What we are doing is setting a reference value that will be used next cycle to turn simplebot back the way he was originally facing and carry right on feeding. We use inc instead of store to save energy.

We also have to go into the condition step of the reproduction gene and take out the line that we added in the last step. You know. The one that only allows simplebot to reproduce when his eye5 cell is almost empty. We have to get rid of this or the whole improvement would be pointless. We want simplebot to reproduce while he is still actively feeding. Go ahead and delete that line now.

The final step is to add a new gene that will make simplebot rotate again when the value in memory location 50 is equal to 1 or more realistically greater than zero just in case it becomes 2 or more. Stranger things have happened. Add this gene BEFORE the reproduction gene. If you add it after it then the value of memory location cell 50 will be one on the same cycle that simplebot reproduces. We wouldn't want that would we?

' Gene 12 rotate back and continue feeding cond *50 0 > start mult 628 50 dec stop

Finally cut and paste gene 6 (avoid conspecifics) in between gene 4 (shoot the food) and your new gene 12. And don't forget to change all your .refeye values to 9 again. We deleted an eye cell. Remember? If this is all getting too much for you then just load up simplebot16.txt and start up the simulation again. Prepare to shout WOW! When you see how simplebot has improved.

Now simplebot really kicks butt. I_Venia is just a smear on the wall now (forgive that! sucker!). Simplebot really isn't that simple any more is he? Say hello to 200 plus robots. The scary thing is that there are still a bunch of minor adjustments that could be made to improve him still further. Try him out against Hunter3.14. We have made simplebot so good that he wins as many duels as he loses. That puts him into the top 4 all time great bots. WOAH! He actually shares a lot of Hunter's traits. I think I need to build a new Hunter.