» next  » last 

Jump to:


Emergent Behaviour and Artificial Life

After several days of wracking my brains over what I should talk about at the September UKBUG meeting I decided upon "Something to do with A-life". A-Life has always been a topic that's interested me and it's great fun to play with. It's not very serious though, or, for that matter, very practical. But A-life systems does demonstrate an important characteristic: Emergent Behaviour.

Due to time considerations I haven't had chance to write a very serious article to accompany the talk, but I have put together this article, which is more of a journal, documenting the design and implementation of the demo programs Animal Kingdom and Animal Deliveries. The contents of this article are, more or less, a transcription of the posts I made on the Logical Genetics Forums during the two weeks leading up to the talk.

Animal Kingdom and Animal Deliveries are based on a program that I wrote for a second year project at university with a guy called Nick Johnson. That program was called Donkey World and consisted of a flat square world of small square tiles. The tiles all had a certain amount of grass on them, which grew as time went by. Donkeys were allowed to roam the world randomly, eating the grass as they went. Donkeys had no idea about the shape of the world, or in fact of anything other than the tile they were standing on and the eight tiles around them. They were able to reproduce if they found a suitable mate and able to eat grass to survive. Despite the fact that the donkeys only had a very simple rule based "intelligence" they still formed groups and created a sustained population.

The aim of Animal Kingdom is to develop a more complex system where different types of animal interact in a similar world.

1. Animal Kingdom



The first task is to develop a class heirarchy for animals and another for the map. The first screen shot, shown in figure 1, shows the map view. The map view is based on a TDrawGrid. The OnDrawCell event has been overridden to allow various bitmap files to be drawn.

The map
Figure 1: The map


Note that I've added water squares round the edge of the map. This means that land animals can't walk off the edge of the world.

Figure 2 shows a similar map (with a view of another part of the coastline). I have now populated the map with a set of creatures. The pink ones are girls and the blue ones are boys (obviously). The creatures are of class TRabbit, but I haven't got round to drawing a rabbit bitmap yet!

The
Figure 2: The "rabbit" population


I have also implemented a details dialog, so you can see the creature details.

The details dialog is displayed when a tile is double clicked
Figure 3: The details dialog is displayed when a tile is double clicked


The next step is to get the rabbits to move around, eat and bonk. That just means adding a few routines to allow animals to detect food and other animals in their 8-neighbourhood (i.e. the eight squares around them), decide whether they are fit for a bonk and then initiate the bonk itself. Once a bonk has been successful (which is based on a probability) the females are pregnant for a number of turns before giving birth. Only creatures of 16 turns old or older will be allowed to bonk. This is not just for the sake of decency, it's to stop male babies immediately impegnating their mothers after they are born!

Figure 4 shows the population after a birth explosion.

Population explosion leads to a lack of food and death for the rabbits
Figure 4: Population explosion leads to a lack of food and death for the rabbits


With the original Donkey World we managed to get the population to reach an equilibrium - albeit a sinusoidal one. The important thing is to get the eating and grass growing rates to even out so that the population doesn't crash to nothing aftwer the rabbits eat all the grass.

Figure 5 shows another screen shot with a graph to show the population size of male and female rabbits over time.

The new population graph, showing populations of male and female rabbits
Figure 5: The new population graph, showing populations of male and female rabbits


At this point in development I noticed a bug which caused all the rabbits to move to the top corner of the map. This was because of the way the "RandomTile" method was implemented. "RandomTile" is supposed to return a reference to the first tile in the animal's 8-neighbourhood on which the animal is able to survive. The method itterated through the neighbouring tiles clockwise from north. This meant that habitable tiles in a general north-eastery direction were favoured. In order to compensate for this it was necessary to itterate through the directions at random. A friend of mine suggested the following technique (listing 1) which seemed to work well.

function TAnimal.RandomTile: TTile;
var
i, j, Temp : Integer;
Dirs : array [0..7] of Integer;
DirAllowed : array [0..7] of Boolean;
begin
for i := 0 to 7 do
  DirAllowed[i] := True;

for i := 0 to 7 do
begin
  j := Random(8);

  while DirAllowed[j] = false do
    j := (j + 1) mod 8;

  Dirs[i] := j;
  DirAllowed[j] := False;
end;

for i := 0 to 7 do
begin
  if Assigned(Tile.Neighbours[Dirs[i]]) and
     CanSurviveOn(Tile.Neighbours[Dirs[i]]) and
     (Population.AnimalAt(Tile.Neighbours[Dirs[i]].Row,
                      Tile.Neighbours[Dirs[i]].Col) = nil) then
  begin
    Result := Tile.Neighbours[Dirs[i]];
    Exit;
  end;
end;

Result := nil;
end;


I managed to get the population to stabilise as soon as the random movement method was fixed. Figure 6 shows the graph that was produced after I left the simulation running for the time it takes to buy and eat a flapjack from the food van.

A stable population of rabbits
Figure 6: A stable population of rabbits


Figure 7 is another screen shot. It shows the results of altering the rabbits class so that they behave in the following way.

if Hungry and FoodOnThisTile then
  Eat
else if Hungry then
  MoveToTileWithMostFood
else
  MoveRandomly


This is an alteration from the previous code.

if Hungry and FoodOnThisTile then
  Eat
else
  MoveRandomly


The goal seeking element of the new algorithm, which causes hungry bunnies to move to the tile with the most food, allows bunnies to live longer. The goal seeking, combined with the random exploration which occurs when rabbits which aren't hungry move to a random tile, causes the population to spread much more evenly across the map. A much larger population can be sustained, with little or no fluctuations after the initial "baby boom". The rabbits eat almost all the food on the map though, quickly finding and devouring any pockets of grass they find.

The rabbit population with the new behaviour
Figure 7: The rabbit population with the new behaviour


So now I have a working version of Donkey world. The next step is to develop some predator animals to see if I can reproduce some interesting interactions between two species. Figure 8 shows a fox.

After the addition of foxes to the simulation
Figure 8: After the addition of foxes to the simulation


In first experiments, 20% of the initial population were foxes. Foxes bonk and reproduce in much the same way as rabbits (exactly the same way in fact) but, obviously enough, don't eat grass. Instead they eat rabbits.

Initially the fox population crashed almost immediately, as they moved randomly and didn't actively seek either food or sex. Figure 9 shows the rise and fall of the fox population. Note also the addition of the population "Mini Map" which shows the distribution of the animals around the world.

Figure 9: 


In order to try to extend the life of the fox population I implemented some goal seeking (for food and sex) for the foxes. Getting the two populations to stabilise was a very hard problem indeed. In fact I didn't manage to get a stable fox and rabbit simulation running at all. The problem is that foxes are dependant on rabbits, but rabbits are not dependant on foxes, so the foxes are inherently the weaker species. Figures 10 and 11 show the foxes slightly extended lifespan with the new heuristic (goal seeking) behaviour. Unfortunately in these cases they wipe out the rabbit population and their dependancy on the rabbits for food causes them all to die.

The fox population crashes due to a lack of food
Figure 10: The fox population crashes due to a lack of food


Another crashing fox population
Figure 11: Another crashing fox population


Figure 12 shows an animation of the Mini Map over time. White dots are rabbits and blue dots are a new species of animal: Hares. Hares are very similar to rabbits, but are more intelligent and faster, i.e. they goal seek bonking opportunities and move two squares per cycle.

Animation of a population of rabbits and hares over time
Figure 12: Animation of a population of rabbits and hares over time


At this point I also added new graphics for rabbits and hares. Hares are the ones with longer legs. Blue creatures are male and pink creatures are female.

Hares and rabbits
Figure 13: Hares and rabbits


I descovered early on that the hares "intelligence" allowed them to quickly dominate, wiping out the rabbits by eating all the food and outliving the foxes. Watch the animation in figure 14 to see the hares take over the world. As far as I can tell, the reasons they do this are:

  1. They goal seek bonking, so they are able to cope with being widely dispersed accross a relatively empty map - unlike the rabbits
  2. They move faster than the rabbits, thus beating them to the food
  3. They do not rely on a high population of other creatures for survival, like the foxes do
  4. [/listsmilie:4c4654858f]

    Hare dominating in a population of all three species
    Figure 14: Hare dominating in a population of all three species


    Suprisingly, even after lowering the probability of a lady hare getting pregnant to just 10% they still seemed to dominate.

    » next  » last 

    Jump to: