MATREM

An experiment in Artificial Life


Last update: Dec 8, 2001

Contents


Introduction

Matrem is a computer program that simulates life. It belongs to the emerging science of "artificial life", which studies evolution and complex systems in general by simulation. Matrem is also a game, where players compete to create the fittest lifeform. Their efforts are the driving force behind the program.
So what does the program do? It creates a little ecosystem, with land and water, trees, grass and rocks. This world is inhabited by creatures, which struggle to survive. They hunt and are hunted, they starve or multiply. All this is governed by simple rules, that say what creature is able to do and how their environment changes. Complexity can emerge from the interaction these animals have, as they try to defeat their rivals in the battle for fitness.
Artificial life uses the process of evolution to create complexity. I actually don't know anything else besides intelligence that can do that, which makes this a very interesting subject. Evolution exists in many things, but it still very hard to study, because the process of evolution usually takes a long time. With the emergence of computers more became possible, although the time limit keeps pressing. The trick in Matrem is that it does not use spontaneous mutation as a way to change properties of a creature. It is deliberately modified by humans, which speeds up 'evolution' a whole lot. But Darwin is always the gamemaster, killing those animals that are not adapted well.
'Playing the game' is easy: you create you own creature! This means you give it a few properties, and, what is most important, you decide how it will behave. To do this you have to program a little piece of code in c++, something I will explain about in the chapter 'How to be a Player'. Right now I'll just promise that it's very easy, and does not even cost a lot of time. You don't have to be a computer-wizard, and you don't need large amounts of experience in programming: a basic knowledge of programming is enough.
The source code of Matrem is all open, so you can check out how it works. It is also platform-independent: it should work with DOS, Windows, Linux and Unix. Hardware minimum is minimal: if you have a 386 or better, with a little bit of memory, you're ready to go! I have done a great deal of the programming on a machine I bought for $40 in a second-hand store. If you want to compile the program yourself you can do that with a compiler and graphics library that are available on the internet for free, and that I have been using for this program. They're great! Make sure to follow all the instructions when you install them.

DJGPP, a free 32-bit DOS-compiler:
http://www.delorie.com/djgpp/
Allegro, a game programming library:
http://www.talula.demon.co.uk/allegro/

After this introduction, maybe you want to take a look at the game first, before you read on about the rules. Well, there you go:

Download Matrem!

For the program Matrem and all it's parts that are available on this page, the gpl licence applies.

The Rules

I hope to explain all the rules as simply and clearly as possible, all the information about the game should be here on the web, so if you think something is missing, please tell me. This is all there is to it, it is really not all that complicated. I have omitted most of the specific numbers and details, they are described in another chapter: Details of the Program.

The World

The World where the game is played is square and flat, and is divided into tiles. The dimensions of this playing field are 256x256. In order to keep the animals from falling of the sides there is a wall around the entire field.

The Environment

Each tile has a landscape element, which can be one of the following:

Besides this, each tile can contain one (dead or living) animal.
This environment changes of course with time: there are fires and plants grow. The rules are:

If a creature stands on a tile, this tile cannot change. The world starts in a certain situation, which is read from a bitmapfile: map.bmp

Picking things up

All animals can pick up the elements on the tiles and then carry it around and put it down again. The specific rules are: When you put the item that you are carrying down again, it appears on the tile directly in front of you. You can only do this if the tile was empty. Exceptions: You can put WATER on FIRE, you can put WATERPLANT on RIVER, you can put WATER on RIVER (stays RIVER), you can put WATER on WATERPLANT (stays WATERPLANT), when you put WATERPLANT on VOID, you get WATER. After this you're of course not carrying anything any more.

The Creatures

The Properties

Here I will describe the general properties of the creatures, and how the rules apply to them. There are things that fixed for a certain creature, and there are things that change. Let's start with the first, each creature has: The things that change in the life of a creature are:
food:
This is the most important thing. Each time you do something you lose a small amount of food, proportional to your weight. When you multiply you lose an additional amount of food and what is left over is divided between mother and child. Eating something gives a certain amount of food, which is the weight of a dead animal for carnivores, or a certain constant for the other things. If your food drops below 0 zero, you're dead!
life:
When you are attacked you lose an amount of life equal to the power of the attacker. If this drops below 0, again, you're dead! Each turn life grows if it's less than hitpoints, and speed at which it grows is proportional to health.
direction:
The direction a creature is facing. Can be one of NORTH, WEST, SOUTH and EAST.

The Jobs

The game works with turns: each turn a creature can do something, he can do A Job. There are only 6 jobs:

How to be a player

So now I just have to prove that it is really easy to join the game and start playing. I will give all the information about the inner workings of the program, but now it's time for

A Quick Start

To get going, you first need to

Download Matrem for Linux (.tar.gz-file, 91k)
Download Matrem, source only (.zip file) (97k)
Download Matrem for DOS/Windows (255k)
Download Matrem for DOS/Windows, Visual C++ project (1384k), thanks to Abhinav Mathur
Debian package is available on repositories (as "matrem").

Note that you need the Allegro game-library to run or compile the game. For running without compiling you need only the binary version.

Unzip the files in one directory, and run matrem.exe (Dos) or matrem (linux). And there are the creatures, running for their lives already! Use the mouse to scroll around the map, use the right mouse button, or 'm' to get to a menu with options to get another view on the situation, adjust the speed, or do some divine intervention. 'q' quits. More information about how to control the program is in readme.txt.

Well, that was not too hard to get it running, was it? Now to get some insight in the program, take a look at the file "milkacow.cpp", conveniently mirrored here. It starts with some programming declaration rubbish, but then there it is: the milkacow::milkacow procedure. This is called a constructor: it initializes a milkacow. But what is of our interest is that all the properties that were described above are clearly quantified here, and are therefore easy to change. If you have already installed djgpp and allegro you can change something here and recompile the program, and your changes are in direct effect. Make sure to include all the *.cpp files in the project. I prefer to use Rhide, an editor/compiler that comes with djgpp, I open the project "matrem.gpr", and compile.
On to the next function: choosejob(). This function is called repeatedly in the program, and here is where the milkacow decides what to do. This is stored in the variable job. So for a test you can try to replace this function by:

void milkacow::choosejob()
{
  job=SLEEP;
}
And you will have cows sleeping all over the place.
The last thing I want to show here is how to change the way a cow is drawn. Open the file "crpic.bmp" in a picture editor, and again it is conveniently mirrored. Here you can see all the pictures for all the animals, and here you can change the cow into a duck, a fly, a vogelbekdier, or a dinosaur. Actually you don't need to recompile your program, you can just run matrem.exe and see the results.

The Program

Let's get to a bit more serious stuff. How does Matrem work? In the main routine, three functions are called subsequently over and over again. evolveland(), which changes the landscape according to the rules described above; callcreatures(), a function that calls the choosejob()-function of all the creatures that are alive, and then makes sure all the jobs are carried out; and draw_screen(), that puts takes care of the graphics output and also functions as an interface. This last function is in another file: "graphics.cpp", and is not very important, (and not exactly a jewel of neat programming). All the creatures are derived from a certain class, tentatively called 'creature', more about that later. First I will show you what you can use if you program a new creature. You can also skip this and use it as reference, and go to the explanation about how to make a new creature (which is of course very very easy).

Objects and pointers

Here I give some information about the structure of the creatures, and explain about objects and pointers. I assume that you know nothing about objects, and have a crude understanding of pointers, something that is very likely if you had some introductory lessons in programming. If you know all about these, you can skip the first part.

classes
An object or class is a way of organizing your variables and functions. It means you bundle some variables together and give that another name. For example:

class vector
{
public:
  int x,y,z;
};
"vector" is now a new type of variable. You can make new vectors and use them like this:
vector v1,v2;
v1.x=3;v1.y=5;v1.z=10;
And use them in function like this:
float magnitude (vector v)
{
  return sqrt(v.x*v.x+v.y*v.y+v.z*v.z);
}
The nice thing is that this function can be defined in the class itself, which makes a lot of sense, because it only applies to vectors. So define the class vector as:
class vector
{
public:
  int x,y,z;
  float magnitude()
  {
    return sqrt(x*x+y*y+z*z);
  }
};
And call this function with:
float m = v.magnitude();
Note: this function is usually implemented outside the class with the :: operator like this:
class vector
{
public:
  int x,y,z;
  float magnitude();
};

float vector::magnitude()
{
  return sqrt(x*x+y*y+z*z);
}
Now it is nice that we can make use of existing classes when we want to make a new class. Suppose we want to make a class of vectors that also have a color (I don't know why, but suppose). This new class has only one addition so we can derive it from the old vector class like this:
class cvector : public vector
{
public:
  int color;
};
And that's it! We can make variables of types both "vector" and "cvector".
I don't want to get too much into the details of classes, so I'll tell you quickly about constructors. A constructor is a function inside a class that has the same name as the class, and it is called if an object of this class is made. So if we had a constructor-function in our previous example, it would be called everytime we make a new variable of the type vector. Equivalently a destructor function is called if an object is deleted, for example when the program is finished. It too has the same name as the class, but there is a '~' in front. For example:
class vector
{
public:
  int x,y,z;
  vector();
  ~vector();
  float magnitude();
};

vector::vector()
{ etc...

pointers
Now pointers are things that people tend to get confused about, although it is not all that complicated. To refresh your memory: a pointer is a reference to the memory that is used by a variable. The type of the pointer is the type of the variable that occupies the memory, like this:

int *ptr;
int i,j;
i=1;
ptr=&i;
j=*ptr;   /*j=1*/
*ptr=3;   /*i=3*/
And there you have all the possible operations with * and &. So ptr is a pointer to an int-variable (first line). Then it is set to point to the memory of i with the & operator. The content of this memory is read by using *ptr, so in this case that is equivalent to the int variable i. Now, when it gets interesting is when you look at classes. A pointer can reference to any type of variable, so also to classes. Let's make a pointer to a vector:
vector v;
vector *vptr;
v.x=3;v.y=7;v.z=1;
vptr=&v;     /*vptr points to the variable v*/
(*vptr).x=1; /*v.x=1*/
vptr->x=1;   /*v.x=1*/
Pay attention to the last line: it is equivalent to the line just above it. The arrow(->) is used to make the program clearer. In matrem it is used a lot.

structures in matrem
All creatures are objects and derived from the base class that is called "creature", and which is defined in the file "creature.h". It is there, where all the function and variables that all the creatures have are defined. An example of a derived class is the "milkacow" class. In the derived class the functions that are declared virtual in the base class can be redefined. An example is the choosejob() function, that is redefined to make the milkacow behave in a certain way. I have worked a lot with pointers to creatures in the program, so to give an example about how to access functions and variables in objects in pointers:

milkacow cow;
creature *cr;
cr=&cow; /*the creaturepointer cr points to cow*/
         /*all the base class variables and    */
         /*functions are now available         */
if (cr->food<1000)
  cr->job=EAT;
cr->choosejob();
Most of how to use this you can see in the program itself. That was it for the introduction on objects and pointers in Matrem.

Global variables

All the global variables and the #defines are in the file "config.h". The ones that you may want to use are:

Global functions

Variables of the class creature

All creatures have an independent set of these variables. You can access these in your creature's functions.

Functions of the class creature

This is the complete list of functions that each creature can access or redefine. For programming a new creature the functions creature() and choosejob() are the most important. These and newcreature() are the only ones that must be programmed.

Rules for programming

Of course, giving away all the information about the programming code in Matrem makes a lot of room for cheating. There are no protections on the variables, so any function can access them and change them. I want to keep it that way, because doing it otherwise would slow down the program. The possibilities are limitless: killing other creatures in distance, teleporting, or just adding food. Of course this is all forbidden, no can do! The only variables you can change are job and dir, during gameplay, and species, hitpoints, power, health, speed, diet and terrain when creating a new animal. I can easily check this in everybody's code, so that won't be a problem. There is another rule: a creature cannot get information about tiles that are more than 3 coordinates away from then. So if a creature stands on the square (47,28) it can only 'see' the tiles in the range (44,25)-(50,31), a total number of 49 squares. Finally, creatures can only have MEAT, GRASS or WATERPLANT in their diet, they can't live of air.

How to create a new species?

Well, this is it! Be a God, and invent your own lifeform! I've made this easier for you by making an example-creature. It is called 'yourcreature' and you can see there are two files with these names: yourcreature.h and yourcreature .cpp. You can change everything about this creature by changing the routines in these files and recompiling the program. What you have to do first of all is to improve the 'choosejob()' function in yourcreature.cpp. You may also want to redraw the creature, because it is now only indicated by a mysterious question mark. So that's it, you can make your own right away!

If you want to make more than one creature you have to make one from scratch. With a little bit of copy and paste this is not too hard either. All you need to do is to take these simple steps:
1. choose a name for your species, let's call it 'unicorn' for this example,
2. copy the file "milkacow.cpp" and rename the copy to "unicorn.cpp", copy the file "milkacow.h" to "unicorn.h"
3. REPLACE "milkacow" everytime it appears by "unicorn" and "MILKACOW" by "UNICORN" in unicorn.cpp and in unicorn.h
4. Edit "config.h", and add in the list of all species the line:

#define UNICORN n
where you have to put the (old) number after N_OF_SPECIES in place of 'n'. This number is the number of the new species. Now increase the number after N_OF_SPECIES by one, so that it becomes n+1, capiche?
5. Edit "matrem.cpp", go to the function init() and add this line after the first time "MILKACOW" appears (in a line that is almost the same):
if (species==UNICORN)  firstcreature[species]=new unicorn;
Go to the start of "matrem.cpp" and add after all the #include lines:
#include "unicorn.h"

6. Open the file "crpic.bmp" in a picture editor. Draw pictures for your new animal (the unicorn) in the (n+1)'th column, where n is the number of your species. This is the first column of creatures that you don't see in the game. Enlarge the drawing if necessary to add an extra column of width 16 on the right. Draw and copy your creature 8 times, just like the other creatures.
7. Add the file "unicorn.cpp" to your project. If you use Dos, you can do it with Rhide, choose Project - Add file. If you are a linux worshipper, you can change the Makefile. Where milkacow.h, milkacow.o and milkacow.cpp appear, add unicorn.h, unicorn.o or unicorn.cpp in the same pattern.
8.Compile the program and run it!
Now you have a new creature, which is unfortunately nothing more than a mere copy of the milkacow. You can change the unicorn() constructor function, to give your unicorn different properties, and change the choosejob() function, to make it behave differently.

Now to be a REAL player, send your little invention to me by e-mail, so I can include it in the matrem-version here on the web. Now your creature can truly compete with the ones that other players made, and the struggle for life goes into a climax. This means you don't have to be able to compile the program yourself, if you send me the cpp file and a picture of your species, I compile it and put it in the matrem.exe file.

Details of the Program

I want to be as open as possible about all the little rules that are in the game, so here you'll find all the details and numbers that play a role in the game. So you don't have to look up how everything works in the source code.

The game starts...

The size of the map is 256x256.
The size of the pictures on the screen is 16x16.
At the start of the program 10% of the creatures is dead.
All creatures initially have an amount of food equal to a random number between 100 and 10 times their weight.

The land evolves...

Every turn 400 tiles are randomly chosen. Depending on what is on them, several things can happen:

Creatures are called...

All creatures that are alive are checked each turn:
If it has a life that is smaller that hitpoints, life will increase 1 for each multiple of 1000 in health, and has a chance to increase 1 of (the modulus of health, when it is divided by 1000) in (1000).
It has a chance of doing a job this turn of (speed) in (1000). (I mean if speed=500 it has 50% chance of doing a job.)
If a creature is attacked it loses an amount of life equal to the power of the attacker. It its life is less than 0, it dies.
When a creature eats another creature, its food increases by the weight of the creature that is eaten. The amount of food the prey had does not matter.
When a creature eats GRASS or GRAIN, it's food increases by 150.
The maximum amount of food a creature can have is weight*20. When a creature multiplies, it loses an amount of food equal to its weight. What is leftover is divided between mother and child.
The weight of a new creature is calculated by:
weight=hitpoints+power+health+speed+
    200*{number of items in diet}+200*{number of accessible terrains};
Each time the creature does a job, it loses an amount of food equal to 1/300 of its weight.

Who's playing?

There are four creatures in play now, made by me or Remco Veenstra, and one other:
mightyMouse was made by Harry Maierhofer: our very first external player!
If you like this game: don't just download it, please play with it, modify or make a creature and let me know. You might like it.

About...

I know, it is about time to introduce myself. My name is Mathijs Romans, I'm 21 years old and study physics at the University of Utrecht, the Netherlands. Currently I am on an exchange program at the University of Wisconsin-Madison, USA. I live in Madison at Nottingham.
There are two books that generated a lot of interest in complex systems and artificial life for me. In high school I read "The quark and the jaguar" by Murray Gell-Mann. This is a very understandable book about complexity and the ways it emerges in nature. Three years ago, I read "Artifical life: the quest for a new creation" by Steven Levy, which is the best introduction one can have in this subject. I started experimenting on the computer, because I knew a bit about programming.
But one night about a year ago, I was talking to my flatmate Remco, and we got the idea of making a game that is partly programmed by the people that play it. The idea for matrem was born. We used the first three letters of our names for the word matrem. I used parts of a program that I already made to start the first version of matrem. It was very crude, it looked very bad (especially because I started with pictures of creatures that were only 5x5 pixels) but nevertheless my flatmates liked it. Their enthusiasm and ideas made me go on and improve the program. I have always believed that programming is a great way to express creativity, and I know a lot of people don't agree with that. But there is a lot of freedom to make whatever you want, it's very playful. Matrem can be a very entertaining program, and interesting at the same time. Many ideas from ecology and evolutionary biology can be applied to the simulation. I have seen the creatures occupying different niches, how the addition of one species can mess up the entire ecosystem, the importance of mutations, and I hope to see much more. There is freedom to add and invent, to create and play. I hope everybody will enjoy it!

Madison, 12/17/1999 & Madison, 17/12/1999.

If you have any questions, comments, critique, suggestions, or you want to join the game, do not hesitate to contact me at matrem at romansland dot nl
Please copy the program for others and tell them about it.

Thanks!

Remco
For the programming and the crazy animals.

Michiel&Marieke
For enthusiasm and ideas, and a lot more.

Milan
For liking the game.

Mark, the man of 30 million colors
Thanks for your enthusiasm and the graphics.

Dinosaur Jr., Sonic Youth, DAAU, Vaudeville and other great bands
that kept me company when I was programming.

What's new?


Mar 1, 2000

- Updated the Who's playing new section


Jan 5, 2000

Matrem version 1.0 on the web! New improvements:
- Linux version is complete
- Resolution up to 1024x768
- Made a 'results' menu with average populations and biomasses
- Fixed some bugs
- Header files for all the creatures were made
- Yourcreature-example added
- Readme.txt with information about how to use the program added



Disclaimer

I would like to point out that this is just a hobby-project and that I cannot be held responsible for all the damage that this program is going to do to your computer, you, your free time and your world perspective.