View League Table
Download Cellz
Developer Kit
This document explains how to specify and submit a controller for the Cellz game. Cellz is currently being run as a competition for GECCO 2004. One of the purposes of the Cellz, and of the GECCO contest, is to gain insights into what makes a good representation space in which to search for controllers of this type.
The Cellz toolkit comes with two representations: a perceptron style controller, and a general kind of neural network controller - simply a directed function graph.
The toolkit comes with a simple evolutionary algorithm (a random mutation hill-climber) that allows you to evolve controllers in either space. Note that to win the contest, you are encouraged to choose a better space to work in than either of these! The evolutionary algorithms contained in the toolkit are very simple, and are provided for demonstration purposes. Again, you should be able to do better!
The descriptions below are rather brief. For more details refer to the source code, which I hope you will find easy to understand. The code is structured into several packages and many simple classes. You will find the code easy to navigate if you use a modern Java IDE, such as Intellij Idea or Eclipse.
Controllers to be submitted to the GECCO contest must use either the perceptron or directed graph input format. Note that the directed function graph is a very general representation. Whichever space you choose to do your evolution in, you should then map your evolved controller to the directed graph format. Controllers specified in this format can be evaluated directly with the Cellz developer kit. You can do this either with a direct call to a Java method, or by writing your controller to a file, and then invoking the games.cellz.FitnessEvaluator command line program to evaluate it.
The perceptron input format is really for a bit of fun - it allows anyone to submit an entry simply by specifying 32 numbers! This idea of a simple entry route was inspired by Dan Ashlock's CEC 2004 contest on plant growth - a different contest, but with a very simple input format.
Conventional GP uses an expression tree. Here we use a simple general directed graph format. You can easily map any expression tree into this format (but be careful to use only the allowed set of function nodes, or choose functions that can be mapped into the allowed set).
This is implemented with the Network class - see the code in problems.neural.Network.java
A Network (i.e. directed function graph) is evaluated with the following method. The outputs are then read off from the top end of the net array.
public void eval(double[] ip) {
// set up the input nodes first
for (int i = 0; i < ip.length; i++) {
net[i] = ip[i];
}
// now evaluated the network
// note that the input nodes are not evaluated
for (int i = nInputs; i < maxNodes; i++) {
if (node[i] != null) {
net[i] = node[i].eval(net);
}
}
}
At each point in time your cell controller takes directional inputs from the game area (think of a wrap-around retina) and outputs a force vector. It is also given it's current mass and velocity.
The interface to the cell controller is specified in Java like this:
public interface SensorLogic {
/**
*
* @param food: food sensor array
* @param cell: cell sensor array
* @param v: current velocity vector of this cell
* @param mass: current mass of this cell
* @return the chosen force vector
*/
public Vector2d getForce(double[] food, double[] cell, Vector2d v, double mass);
}
The sensor arrays are 8-dimensional (think compass points), so these parameters end up as 19 numerical inputs to your controller. The sensor arrays are depicted below:

The nodes of the graph are functions drawn from the following set:
Where 'I' indicates a set of graph inputs (max 10 inputs per node), 'i' indicates a single graph input, and 'r' is a real-valued constant. Note that cells automatically split after they exceed a certain critical mass, specified in the Settings file.
The format is simple: each line specifies a node, giving it a number, a function, then its list of inputs.
Each cell is given 19 inputs, labelled 0 to 18.
Your function nodes then begin at number 19.
You are allowed a maximum of 250 function nodes. An example file is shown below.
When you have designed or evolved your own controller (or if you're in the process of evolving one), you can evaluate its fitness using the FitnessEvaluator class. This may be invoked from the command-line, or from within another Java program.
The command-line version is used as follows (in this example were running 10 experiments, each for 1,000 time-steps:
java games.cellz.FitnessEvaluator SampleDG.txt 1000 10
Made network with 89 total nodes Results summary: min = 483.44841591500034 max = 812.1678760590038 ave = 635.949299122832 sd = 107.90986011178774 se = 34.12409399434012 sum = 6359.4929912283205 sumsq = 4149115.9517323235 watch = null n = 10 1412 ms elapsed
To evaluate a controller from a Java program, import the games.cellz.FitnessEvaluator class, then call the static evaluate method of that class:
StatisticalSummary ss = FitnessEvaluator.evaluate(controller, timeSteps, nRuns);
where controller could be an instance of NeuralControl, which is a class that takes a neural network (directed function graph) and wraps it to implement the CellControl interface.
To help get you started, a random mutation hill-climber is supplied. This is set up to evolve either perceptron (default) or directed graph controllers. You can run this as follows:
java games.cellz.EvolveController <nGens> <timeSteps>
The Cellz game has a significant random element to it, so it's a good idea to base the fitness function (at least for the hill-climber) on many game runs - the default used by this program is 10 game runs per fitness evaluation. If you run the hill-climber for 1000 generations, it should evolve a reasonable controller when searching in perceptron space. Searching in Directed Graph space seems to be harder - but good luck with this!
The program will print out the best individual it found during the run of the hill climber. In the case of evolving a perceptron, this just prints out the weight matrix. Save this to a text file.
You can then run the ConvertPerceptron program to convert this to a directed graph representation, which may then be submitted as an entry to the competition.
Suppose you saved the weights to a file called EvoWeights.txt, then you can run the conversion program as follows:
java games.cellz.ConvertPerceptron EvoWeights.txt EvoDG.txt
This could produce a file containing text such as that shown in the appendix.
You can observe the behaviour of your evolved cell controller:
java games.cellz.DishController SampleDG.txt
You can overide the default options - should look something like this:

Note that if you miss off the filename, the system will run with a default hand-designed controller (working on the same sensor-based inputs).
java games.cellz.DishController
This has interesting behavior, in that it performs very well for a few thousand time-steps, and then completely freezes. Try it!
Note that you can also play against your evolved programs - set MouseController = true, and you'll have a species of yellow cell to control - the cells always head straight for the mouse pointer. With some skill and luck, you may be able to beat your own evolved controllers!
When you have a controller in the correct directed graph format, you can submit it to the web-based evaluation system. Just paste the textual specification of the controller into the web form, and click submit (note that nearer the competition deadline you'll also need to provide some registration details).
The submission form is here
If all goes well, you should get a response something like this:
Trying 10 experiments Each for 1000 time steps min = 527.1215983779816 max = 918.5496552099675 ave = 747.0635335229495 sd = 114.73990510637535 se = 36.28394386477305 sum = 7470.635335229495 sumsq = 5699526.443612331 watch = null n = 10 1792 ms elapsed Thank you for your submission
Below is a sample perceptron controller - simply specified as a set of 32 weights in the weight matrix connecting the 16 inputs with the two outputs:
-91.08398800672279 181.36371005075267 -46.70294024496973 110.84617492377723 99.20823198346234 -5.156549901404951 43.027384813844414 -319.1250595529542 178.30382832839948 45.862523930926336 99.83320181604208 -216.76474097449307 63.301287359780744 -40.7527129164992 -78.33699942251222 62.72863029677474 271.31993625545476 -222.7670199821426 432.4742500271704 -17.746681433059315 -42.0223492084727 -427.814325716213 -96.57975646348736 -411.089671736812 24.856269663769172 -87.51111336185215 -6.710333625137078 115.68385478744595 77.02414672665172 3.472136920894549 251.4568079030636 270.5703611905452
A sample controller (derived from an evolved perceptron) is shown below. Note that the behaviour is not identical - the perceptron output goes through some non-linearities (see games.cellz.WeightedSum), whereas the outputs of the directed graph are used directly.
You can evaluate this by pasting it into the text area on the web based evaluation service page, here
// sample DG from a simple perceptron controller // specify number of inputs and total number of nodes 19 89 // now the set of constants - // node number starts immediately after all inputs 19 Const -91.08398800672279 20 Const 181.36371005075267 21 Const -46.70294024496973 22 Const 110.84617492377723 23 Const 99.20823198346234 24 Const -5.156549901404951 25 Const 43.027384813844414 26 Const -319.1250595529542 27 Const 178.30382832839948 28 Const 45.862523930926336 29 Const 99.83320181604208 30 Const -216.76474097449307 31 Const 63.301287359780744 32 Const -40.7527129164992 33 Const -78.33699942251222 34 Const 62.72863029677474 35 Const 271.31993625545476 36 Const -222.7670199821426 37 Const 432.4742500271704 38 Const -17.746681433059315 39 Const -42.0223492084727 40 Const -427.814325716213 41 Const -96.57975646348736 42 Const -411.089671736812 43 Const 24.856269663769172 44 Const -87.51111336185215 45 Const -6.710333625137078 46 Const 115.68385478744595 47 Const 77.02414672665172 48 Const 3.472136920894549 49 Const 251.4568079030636 50 Const 270.5703611905452 // products - each one multiplies an input by a constant 51 Prod 0 19 52 Prod 1 20 53 Prod 2 21 54 Prod 3 22 55 Prod 4 23 56 Prod 5 24 57 Prod 6 25 58 Prod 7 26 59 Prod 8 27 60 Prod 9 28 61 Prod 10 29 62 Prod 11 30 63 Prod 12 31 64 Prod 13 32 65 Prod 14 33 66 Prod 15 34 67 Prod 0 35 68 Prod 1 36 69 Prod 2 37 70 Prod 3 38 71 Prod 4 39 72 Prod 5 40 73 Prod 6 41 74 Prod 7 42 75 Prod 8 43 76 Prod 9 44 77 Prod 10 45 78 Prod 11 46 79 Prod 12 47 80 Prod 13 48 81 Prod 14 49 82 Prod 15 50 // sum the products - limited fan-in // (as specified by GECCO contest) 83 Sum 51 52 53 54 55 56 57 58 84 Sum 59 60 61 62 63 64 65 66 85 Sum 67 68 69 70 71 72 73 74 86 Sum 75 76 77 78 79 80 81 82 // finally the outputs 87 Sum 83 84 88 Sum 85 86
You can download the following paper to appear in CEC 2004:
This gives more background on the game, though note that the precise details differ in a few ways to the setup for the GECCO contest.
The parameters that control the game, and the display / animation of the game are contained in the Settings class, listed below.
package games.cellz;
public class Settings {
public static boolean video = false; // show animation window if true
public static boolean sound = false; // generate sounds to accompany events?
public static boolean trace = false; // if true then each cell leaves a trace as it moves
public static int delay = 100; // the delay between frame updates in the animation
// next four relate to the physics model
public static double maxVelocity = 15;
public static double friction = 0.03;
public static double initMass = 50;
public static double maxForce = split / 10; // relate max force to max cell mass
// next four define game setup
public static int split = 80; // cells split when they reach this mass
public static int nFood = 10; // number of food particles
public static int nCells = 5; // initial number of cells
public static int foodSize = 4; // should specify the mass to be consistent
public static int timeLimit = -1; // cycle forever if '-1' - set a positive value for a limited run
public static boolean mouse = false; // if true, then add a human (mouse) controlled species
// there will be a sensor array for each species (food is considered a species)
public static int nSpecies = 2;
// maximum number of nodes allowed in the Directed Graph
public static int maxDAGNodes = 250;
public static int width = 640; // dimensions of play area (in screen pixels or meters)
public static int height = 480;
}