Evolv'artist is an open source computer game project on evolution.
To make the experience fit your profile, pick a username and tell us what interests you.
We found and based on your interests.
The five-steps simulation turned out to be faaaar to computationally heavy.
We decided to replace it with a fitness based simulation:
- the string genome is cut into genes
- each gene is associated with a function of environment descriptors giving its fitness
- survival and reproduction is decided by fitness
- at each step creatures are reproduce, die and new creatures are born into neighbouring spots.
DNA is the "blueprint" of most living organisms. It is at the crux of evolution as it defines -roughly speaking- the hereditary characteristics of a living being. Not familiar with DNA? Check out this video, this interactive website or this old-school lesson for info.
In our simulation, the behaviour of the Creatures is going to be determined mostly by their DNA, with a pinch of randomness here and there.
We have settled on a 3-bases single-strand genetic information structure. A chromosome will be represented by a string of letters. Possible letters will be A, the beginning of a gene, O, the end of a gene, and B, C and D, the bases. A gene will be any sequence of letters beginning by a A and finishing by a O, with only B's, C's and D's in between.
For example:
ABBCDDCBDBCO is a gene
ABCDBBDC is not a gene
BDCBCBDO is not a gene
ACBDBCACO is not a gene, but its substring ACO is
ADBABCDDBCOCBDDO is not a gene, but its substring ABCDDBCO is
With this structure, it is not possible to have a gene which is a substring of another gene.
For game design and performance purposes, for now we set the maximum length of a useful gene to be of 6 bases. Any gene longer than this will have not impact on its bearer.
So, the time has come to choose a first algorithm to move the Creatures in the World grid. For now, they move pretty stupidly, by alternating horizontal and vertical movements towards a target -the Spot with the highest score in their local environment-. The plan is to improve this by implementing an A* path-finding algorithm to determine where to go next.
A* is a very common pathfinding algorithm in graphs, which means it translates perfectly to pathfinding in grids. It does not require any preprocessing of the graph/grid, which is good for our part as we will never perform the pathfinding twice on the same grid.
A* is widely documented, so I will not detail it here. For reference, Wikipedia propose history and complexity information in addition to the pseudocode. On Ray Wenderlich's website you can find a tutorial for beginners complete with step-by-step illustrations of an example and an Obj-C pseudocode. And because it always help to be able to play around with new algorithms, here is a fantastic visualisation tool for pathfinding algorithms.
Part of our heuristic will relay on the evaluation of the environment, which we will probably discuss in a future log. For now, we are using the feeding power and the presence/absence of other Creatures to determine the score of a Spot during the local environment perception phase. If we could always reach our target immediately, this would not be necessary, but as it is possible that the Creature will only reach an intermediary point on the way to the target, we prefer to account for the convenience of each Spot.
We also want to account for the number of moves necessary to reach the target -in other words the Manhattan distance from the current position. This reflects the fact that we do not want to wander all over the grid before reaching our target.
In A*, the lower the heuristic the better. However, in our case the higher the score the better, so we set our heuristic function to be h(Spot) = ManhattanDistanceToDest(Spot) + MaximumPossibleScore - Score(Spot)
Our heuristic is admissible but not consistent/monotonous, so we will have to keep track of visited node (closed list) in our implementation.
In the simulation, each creature first perceives its local environment then move according to this local perception. Different creatures might not be able to "see" the same information from the map (temperature, presence of plants or other creatures, type of ground, ...) and their movements depends on their perceived value of each grid spot.
The naive implementation approach to this problem is to maintain one matrix of the real world grid plus one "perceived" copy per creature. However, this requires to generate as many world grid matrices as there are creatures. In this configuration, a lot of space is used for little information, as each creature only has information on a small sub-matrix of the grid. In addition to this, the time complexity of the move function is also sub-optimal, as for each and every creature the entire world grid must be looked at to determine the target for the move.
The best alternative I have found for now is to add in the definition of the creatures the maximum range of the perception. That is, the maximum value of the various perception capacities, vision, smell, thermosensing... Let's call it maxPercep. During the perception step, a matrix of size (2 * maxPercep + 1)^2 will be generated. It will be centered on the current position of the creature. There would be no border issues as the world grid is wrapping on itself. The perceived value of the grid spots outside of this local matrix is null. Depending on the size of the grid world and the maximum range of perception, this could save an enormous amount of space and quite a bit of time during the move step. The only downside is that it requires more careful implementation, but hey, I wouldn't be working on that project if I didn't like programming challenges!
Our general scheme for our evolution simulation is as follow. We maintain a list of the living creatures in the world and we iterate a five-step simulation over this list.
Each step is run for all creatures before the next step is computed. The order in which the creatures are considered for the computation of a step is random.
* Reproduction is happening by a mixing of DNAs. In the very basic models with are experimenting with right now, there is no DNA mechanism yet, so we'll devote another post for our plans for this part.
For a first draft of the evolution engine, we have settled on the followed world and creature characteristics:
We all know how daunting tackling a new project can be, or how frequent it is to give up in the middle because the end still feels so far away. For me, the best way to prevent that is to break down the project into small bricks from the start and to keep track of the status for each brick.
This is a tentative list of bricks of Evol'artist. Some bricks are divided further into smaller ones, and the goal is to never have a leaf brick of the tree seem to big to tackle.
>Game design:
>>Story/world
>>>Characters
>>>Storyline
>>>Creatures characteristics
>>Interface
>>>Planet modification interface
>>>Feedback on the creatures interface
>>>General menu interface
>>>Display orders
>Programming
>>Evolution motor
>>>Creature entities
>>>Life simulation
>>>>Fetching characteristics from DNA on birth
>>>>Simulate each step in life simultaneously for all creatures
>>>Reproduction simulation
>>>>Meiose
>>>>Mixing DNAs
>>Stats on creatures
>>>Dynamic stat display
>>>Stats on phenotype
>>>Stats on genotype
>>Game play engine
>>>General save/create/quit...
>>>Planet modification
>>>Order generation
>Art
>>Visuals
>>Audio
>>Name
>>Logo
Create an account to leave a comment. Already have an account? Log In.
Become a member to follow this project and never miss any updates