When I was learning to program, I tried to make a toy artificial life evolution simulation. Particle organisms on a 2D plane had 'dna' which was a list of heritable traits, like size, speed, number of offspring. Bigger organisms could eat smaller organisms, but they burn energy faster. 0 energy = death. When two organisms of opposite gender collided and had sufficient energy, they'd give some of their energy split among the offspring, with each offspring's 'dna' values set to one of the parent's +/- 5%.
As I was developing this, I hadn't figured out how I wanted to do food yet, so as an easy first step, I just had a constant amount of energy that was split amongst all organisms on the screen. Lots of little dots buzzing around, was kind of neat but nothing too special. I left it to run overnight.
When I came back I was very surprised: previously i was running at about 30FPS - now it was running at about 4 seconds per frame. The screen was filled with dense expanding circles of tiny slow organisms emanating from where organisms had mated and nothing else.
My simulation evolved to outsmart my simple food algorithm: when food is divided equally among all organisms, the best strategy is to use minimal energy and maximize offspring count. I had populated the world with a default offspring count of ~5 and they had evolved to the tens of thousands. The more offspring an organism had, the greater the amount of the energy pool would go to their offspring.
It was a very cool "Life, uh, finds a way" moment - that such a simple toy simulation of evolution was able to find an unanticipated optimal solution to the environment I created overnight was very humbling and gave me a lot of respect for the power of evolution.
I worked on a similar project. One of the heritable traits I had was a quantity of energy that would be passed on to a child. A mother and father organism contributed a random half of their stats to a new child and both parents deducted their caretaker energy and increased the child's energy by the same amount.
I had a lot of different graphs to show me stats as the simulation continued. One thing I noticed was that after a while of this simulation "average age" started to go way up.
At first, I was proud. I thought I had evolved creatures that could live indefinitely in my simulated environment. I kind of had - but it didn't work like I thought. At some point the creatures seemed to become immortal and all new creatures died off. I was monitoring "average age at death" which confirmed all the dying creatures were very young and "average generation count" which showed it stabilized midway through the simulation and then locked in place. They got to a place where new organisms died off and there were a bunch of immortal organisms running around.
I finally figured out what had gone wrong. The stats, including caretaker energy, could be randomly modified by a small random value up or down whenever a child was produced. Nothing prevented caretaker energy from going negative, and indeed, that's what would happen. The simulation would work for a while while only a small number of organisms had negative caretaker energy, but eventually these guys would take over and become the whole population. They could indefinitely sustain themselves by having children, but their children (spawned by two parents who passed on negative energy) would instantly die.
Decades ago I read about a simulation aiming to evolve creatures that could walk, or one day run. The fitness function that determined how many offspring you get was “maximum speed ever attained in your life”.
They let it run for a while and came back to find all the creatures had evolved into extremely tall, thin stalks that would tip over and never move again. The top would be moving very fast before it hit the ground.
Our own human intelligence could also seen this kind of side effect. The purpose of it being for us to be better at hunting other animals and gathering extra food. Instead, in just several hundred thousand years we’ve built a bunch of ‘buildings’ and we managed to throw the entire ecosystem out of balance.
There is a 2018 paper called "The Surprising Creativity of Digital Evolution" which is a collection of similar anecdotes: https://arxiv.org/abs/1803.03453
Thanks, great paper!
"Many researchers in the field of digital evolution have observed their evolving algorithms and organisms subverting their intentions, producing unexpected adaptations, or exhibiting outcomes uncannily convergent with ones in nature. Such stories routinely reveal creativity by evolution in these digital worlds."
My goal with this project was to be able to seed the world with a single proto-organism and have two distinct species - one predator and one prey - evolve to create a stable ecosystem.
I eventually localized food sources and added a bunch of additional rules, but was never able to realize this goal. I think for predator-prey relationships to evolve in my system it would have required sensory organs and methods to react to local environment.
Seems like ALiEn is able to simulate food chains with distinct species - and alas I don't have a CUDA GPU - but curious if they've been able to create an ecosystem where predators and prey can coexist in a balanced stable ecosystem. (In my experiments, it was very easy to get predator population explosion, all of the prey gets eaten, and then all of the predators die)
I think this probably happens sometimes in the real world. However, there usually aren't ecosystems with only two species. Most predators eat multiple prey species, so a predator may hunt the "easy" species to extinction leaving only the harder-to-hunt species remain, which causes the predator population to fall as only a subset of the predators are able to succeed in these harder conditions.
Cicadas could be another example of a strategy to deal with prey-decimation - by only emerging every N years, food sources have time time to regenerate between cycles. Similarly, many large predators are nomadic - so as they reduce prey availability in one area, they choose to look elsewhere, giving the prey in that area time to recover.
I think geography and terrain also helps a lot in the real world: prey is usually smaller than predators and thus has more hiding spots. Maybe I should have implemented a 'turtling' mode, where organisms could spend part of their time immobile and invulnerable, but also not gaining energy, as a way to prevent predation. I think sensory organs would still probably be necessary to make that strategy work.
Yeah, I was able to achieve short temporary equilibria, but in every case the predators would slowly die out (and re-evolve later, and die out again), or they'd be too successful and kill everything.
I too implemented GOL at some point (when I had a look at SDL) and for fun changed the (boolean) game field to integers that I mapped to grayscale (and later RGB). So instead of killing/giving birth to cells you just decrease/increase their integer value. The result looks like a spreading fungus (with the classic horizontal/vertical/diagonal patterns) which can be very chaotic when numbers start to overflow and underflow.
It's a really fun and engaging way to play with 2d graphics and simulation.
My dad, who was teaching me, wrote the canvas+js 2D visualization for me, while I built the engine that managed the state of the world. When you're learning asking for help from those who are more experienced than you is huge. Also, don't be shy about taking someone else's thing and modifying it until it does what you want it to do: these are educational projects, you don't really need to worry about licensing or those kinds of things. I learned a lot from 'hacking' in-browser web games before trying to write my own: cheat at the game, then add a button that improves Qol, then try to add a feature.
Try to simulate something that you're interested in! Everyone has their own interests, but I find these kinds of problems a lot of fun to work on.
When you're learning, it forces you to make reductive approximations and simplifications - you just can't do it the "right" way, so try to find a way to get something similar with something close to it. Trying to model a bunch of simplistic rules that replicate a phenomenon. Flocking/crowd/traffic behavior, spread of memes or viruses, growing plants, etc. - the sorts of problems were you have a bunch of tiny particle/cells that each have simple behavior but they can interact with each other are very rewarding to get working because simple rules can produce complex system behavior.
As I was developing this, I hadn't figured out how I wanted to do food yet, so as an easy first step, I just had a constant amount of energy that was split amongst all organisms on the screen. Lots of little dots buzzing around, was kind of neat but nothing too special. I left it to run overnight.
When I came back I was very surprised: previously i was running at about 30FPS - now it was running at about 4 seconds per frame. The screen was filled with dense expanding circles of tiny slow organisms emanating from where organisms had mated and nothing else.
My simulation evolved to outsmart my simple food algorithm: when food is divided equally among all organisms, the best strategy is to use minimal energy and maximize offspring count. I had populated the world with a default offspring count of ~5 and they had evolved to the tens of thousands. The more offspring an organism had, the greater the amount of the energy pool would go to their offspring.
It was a very cool "Life, uh, finds a way" moment - that such a simple toy simulation of evolution was able to find an unanticipated optimal solution to the environment I created overnight was very humbling and gave me a lot of respect for the power of evolution.