Damn local minima!
So, here’s the game, implemented in game.java. A certain number of cycles is chosen, between a minimum amount, 10 at the moment, and a maximum, 50. Then a coin is flipped that determines whether the light is on or off for this round. One port will, when called, set b to 1 if the light is on, and -1 if it’s off. So far so good. This is enough for the figures to have the simplest eye imaginable. They can detect whether or not the light is on, something that even single cells are capable of. Next, we attempt to get them to react to whether or not the light is on, again, something that some of the simplest life forms can do.
At first, I had a port for looking, and only one port for playing the game. If it’s called while the light is on, the figure is given some energy, and mutation is turned off for that figure and its family. If the port is called while the light is off, energy is removed, and the family is exposed to mutations again. A figure can call the port as often as they want, but it only counts the first time during any given round. Results have been less than overwhelming.
I experimented with several variations on this game, but nothing has worked thus far. If I let it run for a lengthy time, up to 1000 extinctions, what we get are small bursts of 1 or 2-thousand correct port calls. The good calls will keep the lead, and then nothing changes for a good long while, until the next little burst of a few thousand good calls over bad ones. There is a bias, an advantage to getting the game right, but it doesn’t seem to be enough to allow a population to evolve into light sensing, light responding little creatures. So, what’s the problem, and how do we fix it?
For one thing, with just one port to call for the game, while the light is off, there is nothing a figure can do to protect itself and its children from mutations. To fix the problem, I changed the game. Now there is one port “guess on,” that will provide energy and protection from mutation if called while the light is on. The other port, “guess off,” does the same thing if called while the light is off. In both cases, if the wrong port is called at the wrong moment, the family is exposed to mutations and energy is lost. Meanwhile, there’s the port “look.” The look port doesn’t provide or take energy, or protection; it just provides feedback on whether or not the light is on.
Still, no joy.
While watching some runs go by, I noticed that the figures aren’t actually playing the game all that often. Several extinctions can happen, figures are born live and die, and none of them play the game at all. I tried changing the game so that more than one guess can be made during any given round. When the figures are allowed to play as often as they like, the number of times they play the light game goes up, but not by much, and apparently, not enough to make the difference.
What if we evolve the population in several stages? We can set it up so that if a population calls the ports that are going to be part of the game, mutation gets shut off. If we do that, in a very short time, the population learns to call the given port early and often. Then, switch on the game, and let them go. Unfortunately, the first time, everybody died.
I was actually reusing a population from an earlier experiment. It had already learned to call one port and avoid another one. I retasked the port that it had learned to call as the look port. Once the game was running, the program would branch, based on whether or not the light is on or not. While the population was learning to call the port, there was no branching in their program, no light to react to, no such reactions. Unused to what was happening, that population couldn’t survive the change. So, do it again, but this time, leave the game on while the population learns how to look. That way, it will be used to the different reactions. Stored in look0.pop, that population is able to look for the light, and survive what it sees.
good 0
bad 0
looks 199,993
guess on 0
guess off 0
plays 0
Realm size=30
population=5
Longest=100,001
most 0
Mutations 0
Figure births 99,996
extinctions 0
Elapsed time=0 hours, 0 minutes and 58 seconds
As you can see from the output, look0 is looking, but not playing.
Now that look0 is in the habit of looking around, let’s see if look0 can be mutated to play the game. So, let’s run it again, using look0 as a seed population, and instead of being protected when the look port is called, one of the guess ports will provide immunity from mutation.
good 99,790
bad 100,201
looks0
guess on 199,991
guess off 0
plays 199,991
Realm size=30
population=5
Longest=100,001
most 0
Mutations 0
Figure births 99,996
extinctions 0
Elapsed time=0 hours, 0 minutes and 59 seconds
That was look1.pop. As you can see, she only calls the one port. She stopped calling the look port at all. The game results are roughly fifty fifty. That’s to be expected when the silly little figures aren’t even looking!
It’s interesting that look0 mutated such that she went from looking and not playing, to playing and not looking, but that’s not the behavior we’re after.
Instead of turning off mutation when one port is called, suppose we provide protection if and only if a figure both looks and plays?
Let’s see what happens.