What you are looking for here is a classifier system (CS) which is a combination of a genetic algorithm (GA) and selection method. A GA is a search algorithm, a way to select a set of genes through a fitness function. The CS reads the data from the environment, adjusts the GA parameters so that the selection process generates genes that matches the current environmental conditions. It may sound a bit complicated, but it is actually quite straight-forward. The difficulty is in the creation of the DNA code and assigning a fitness function.
GAs are quite easy to code (I have done a few over the years).
First you need to define the gene code. For example, suppose that you are creating an agent that can eat, move and reproduce. These are the actions that the CS would control within the environment based on the current environmental conditions. However, they don't define the genetic makeup of the agent, so you have define the basic genes that generate the behaviors. Some possible genes could be energy level generated from eating, reproduction level based on energy level and age, age of the agent in generations, and movement speed that would also be based on energy level or some other factor.
You could also approach the problem based on characteristics. For example, you could define a mouth that allows the agent to eat a certain amount, the number of legs that would determine the speed of the agent, the sex of the agent so that it could only mate with certain other agents, and so on. The gene structure depends on how you want to express the behaviors of the agent.
Once you define the gene code, you need to define a fitness function for the agent. What is the criteria for successful agents? For biological systems, success means reproduction, so the fitness function for something like an simulated agent would simply be surviving until it can reproduce. If you introduce a crowding factor into the simulation, that is more agents mean less food so the system is self limiting, you don't really need to define an external fitness function, since the crowding factor will act as a fitness function eliminating under-performing agents.
For the first generation, you simply generate x number of agents using randomly selected values for the genes. After that, you can use existing agents to generate new agents through reproduction, and occasionally introduce a random factor into the mix through mutation or spontaneous (random) generation.
The next thing to look at is the reproduction method. If reproduction is asexual, then you swap genes within the agent with a chance of mutation. In order for this to work, all of the gene criteria need to have the same meaning. For example, suppose you have a gene code of: energy | max age | speed. The values of each range from 1 to 100. These would represent percentages rather than actual numbers so that you are working with genes that relate to each other in a meaningful way. The actual numbers of the gene values could be anything, and different from one another, but making them percentage amounts within the gene definition enables you to manipulate the genes without worrying about range issues you might have with actual values.
So, to generate a new agent, you cut the gene randomly at a boundary. Say you randomly select the energy-max age boundary. This leaves you with energy and max age | speed. You then swap the genes, resulting in max age | speed | energy. These are then mapped into the new agent gene code so that energy < max age, max age < speed, speed < energy. This is why the gene code needs to be consistent since you are mapping the values of the old gene to the new gene.
Once the gene is mapped, you can see if a mutation occurs, a very small chance, and then adjust a characteristic by a small amount. This helps keep the gene pool from stagnating.
For sexual reproduction, you randomly swap genes from two agents to produce the new agent. In this case, the gene values do not have to be consistent, since you are working from two different genes and the transfer is from one characteristic to another characteristic, without crossing over. You could introduce crossover is you want, but again, the genes need to be consistent.
The CS would then take all the agents and perform the different defined behaviors for a cycle based on the gene values. These could be different for each agent or the same for all agents. They could be another set of genes in addition to the characteristics. The behaviors might be: die due to old age or starvation, eat, look for food, move to food, avoid predator and reproduce. The cycle would then repeat.