//Linda MacPhee-Cobb //www.timestocome.com //herselfsai.com //Creative Commons Attribution Non-Commercial Share Alike //genetic life forms //we have a square board with some plants, herbivores, and carnivores // //herbivores eat plants in squares they move into and gain 1 energy point for each plant //carnivores eat herbivores and gain 2 energy points for each carnivore eaten // //when herbivores or carnivores reach breeding energy a new one is born //junior inherits 2 of parents weights ( plant, herbivore, carnivore ) //and one random weight // //herbivore and carnivore choose a direction to move one square by using a very //simple fixed neural net. Three inputs for each of eight surrounding squares //inputs are 1 for ( plant|herbivore|carnivore ) in the square 0 otherwise //neural net has 3 hidden weights between -1 and 1 one for plants, one for herbivores, one for carnivores //all three inputs for each square are multiplied by their weights and the square with the heightest //score is the square we move into. //weights are ranomly set for first generation. // //edges lead off end of world one must turn around or die //carnivores and herbivores die if energy reaches zero //I haven't found the numbers for a self sustaining village yet. //Plants fully replenish themselves each round, no reason things //can't be selfsustaining. At these numbers sometimes the carnivores //get wiped out and sometimes they do not. import java.util.*; public class GeneticLife{ static int boardSize = 20; static int maxCarnivores = 3; static int maxHerbivores = 300; static int maxPlants = 300; static int maxDays = 200; static int board[][][] = new int[boardSize][boardSize][3]; // x, y, plant, herbivore, carnivore static int mateEnergyCarnivore = 300; static int mateEnergyHerbivore = 35; public static void main ( String[] args ) { //****************** // set up game board //****************** //***************************************** //set up lists of carnivores //***************************************** LinkedList carnivores = new LinkedList(); for ( int i=0; i< maxCarnivores; i++){ Carnivore carnivore = new Carnivore(); int placed = 0; //position on board while ( placed == 0 ){ int x = (int)(Math.random() * boardSize); int y = (int)(Math.random() * boardSize); if ( board[x][y][2] == 0 ){ board[x][y][2] = 1; carnivore.x = x; carnivore.y = y; placed = 1; } }//end while carnivores.add( carnivore ); }//end for maxCarnivores //*************************************************** // set up list of herbivores //*************************************************** LinkedList herbivores = new LinkedList(); for ( int i=0; i= mateEnergyCarnivore ){ Carnivore junior = c.mate(); carnivores.add ( junior ); } // age one cycle c.age(); //see how much energy we have left if ( c.energy <= 0 ){ //we die carnivores.remove(c); numberOfCarnivores--; } } //for each herbivore int numberOfHerbivores = herbivores.size(); for ( int i=0; i= mateEnergyHerbivore ){ Herbivore junior = h.mate(); herbivores.add( junior ); } // age one cycle h.age(); //see if he has enough energy to stay alive if ( h.energy <= 0 ){ //time to die herbivores.remove(h); numberOfHerbivores--; } } //grow more plants on the board growPlants(); //update board with herbivores and carnivores //first clean out the board for ( int k=0; kmaxPlants }//end grow plants /////////////////////////////////////////////////////// // Pick a direction for carnivores and avoid the edges // if edge of board or carnivore in that direction ignore that route // we can't occupy that spot // this is a neural net input ( 1|0 if plant|carnivore|herbivore in spot ) // 1 * weight = weight so no point in extra step // then the plant + herbivore + carnivore is added for each possible direction // we can move to. static int pickDirectionCarnivore ( Carnivore c ) { int currentx = c.x; int currenty = c.y; double direction[] = new double[9]; // center|nw|n|ne|e|w|e|sw|s|se int nogohere = -20; // set low enough that we don't move to squares off edge of board or already containing carnivores int move = 0; // 0 is center square stay put if no better options for ( int i=0; i<9; i++){ direction[i] = 0; } //check north direction[2] if ( currenty > 0 ){ if ( board[currentx][currenty-1][0] == 1 ){ direction[2] += c.plant; } if ( board[currentx][currenty-1][1] == 1 ){ direction[2] += c.herbivore; } if ( board[currentx][currenty-1][2] == 1 ){ direction[2] += c.carnivore; } }else { direction[2] = nogohere; } // don't run off end of board //check north east - direction[3] if (( currentx < ( boardSize-1) ) && ( currenty >0)){ if ( board[currentx+1][currenty-1][0] == 1 ){ direction[3] += c.plant; } if ( board[currentx+1][currenty-1][1] == 1 ){ direction[3] += c.herbivore; } if ( board[currentx+1][currenty-1][2] == 1 ){ direction[3] += c.carnivore; } }else { direction[3] = nogohere; } //check east direction[5] if ( currentx < (boardSize-1) ){ if ( board[currentx + 1][currenty][0] == 1 ){ direction[5] += c.plant; } if ( board[currentx + 1][currenty][1] == 1 ){ direction[5] += c.herbivore; } if ( board[currentx + 1][currenty][2] == 1 ){ direction[5] += c.carnivore; } }else { direction[5] = nogohere; } //check south east direction[8] if ( ( currentx < (boardSize-1)) && ( currenty < (boardSize - 1))){ if ( board[currentx + 1][currenty + 1 ][0] == 1 ){ direction[8] += c.plant; } if ( board[currentx + 1][currenty + 1 ][1] == 1 ){ direction[8] += c.herbivore; } if ( board[currentx + 1][currenty + 1 ][2] == 1 ){ direction[8] += c.carnivore; } }else { direction[8] = nogohere; } //check south direction[7] if ( currenty < (boardSize-1 )){ if ( board[currentx][currenty + 1 ][0] == 1 ){ direction[7] += c.plant; } if ( board[currentx][currenty + 1 ][1] == 1 ){ direction[7] += c.herbivore; } if ( board[currentx][currenty + 1 ][2] == 1 ){ direction[7] += c.carnivore; } }else { direction[7] = nogohere; } //check south west direction[6] if ( (currentx > 0 ) && ( currenty < (boardSize-1)) ){ if ( board[currentx -1][currenty + 1][0] == 1 ){ direction[6] += c.plant; } if ( board[currentx -1][currenty + 1][1] == 1 ){ direction[6] += c.herbivore; } if ( board[currentx -1][currenty + 1][2] == 1 ){ direction[6] += c.carnivore; } }else { direction[6] = nogohere; } //check west direction[4] if ( currentx > 0 ) { if ( board[currentx-1][currenty][0] == 1 ){ direction[4] += c.plant; } if ( board[currentx-1][currenty][1] == 1 ){ direction[4] += c.herbivore; } if ( board[currentx-1][currenty][2] == 1 ){ direction[4] += c.carnivore; } }else { direction[4] = nogohere; } //check north west direction[1] if ( (currentx > 0 ) && ( currenty > 0 )){ if ( board[currentx-1][currenty -1 ][0] == 1 ){ direction[1] += c.plant; } if ( board[currentx-1][currenty -1 ][1] == 1 ){ direction[1] += c.herbivore; } if ( board[currentx-1][currenty -1 ][2] == 1 ){ direction[1] += c.carnivore; } }else { direction[1] = nogohere; } //total up directions and get best option //if all options blocked stay put double choice = 0; for ( int i=0; i<8; i++){ if ( direction[i] > choice ){ choice = direction[i]; move = i; } } return move; } ////////////////////////////////////////////////////// // Pick a direction for herbivores static int pickDirectionHerbivore ( Herbivore h ) { int currentx = h.x; int currenty = h.y; double direction[] = new double[9]; // center|nw|n|ne|e|w|e|sw|s|se int nogohere = -20; // set low enough that we don't move to squares off edge of board or already containing carnivores int move = 0; // 0 is center square stay put if no better options for ( int i=0; i<9; i++){ direction[i] = 0; } //check north direction[2] if ( currenty > 0 ){ if ( board[currentx][currenty-1][0] == 1 ){ direction[2] += h.plant; } if ( board[currentx][currenty-1][1] == 1 ){ direction[2] += h.herbivore; } if ( board[currentx][currenty-1][2] == 1 ){ direction[2] = nogohere; } //we can't move here already occupied }else { direction[2] = nogohere; } // don't run off end of board //check north east - direction[3] if (( currentx < ( boardSize-1) ) && ( currenty > 0 )){ if ( board[currentx+1][currenty-1][0] == 1 ){ direction[3] += h.plant; } if ( board[currentx+1][currenty-1][1] == 1 ){ direction[3] += h.herbivore; } if ( board[currentx+1][currenty-1][2] == 1 ){ direction[3] = nogohere; } }else { direction[3] = nogohere; } //check east direction[5] if ( currentx < (boardSize-1) ){ if ( board[currentx + 1][currenty][0] == 1 ){ direction[5] += h.plant; } if ( board[currentx + 1][currenty][1] == 1 ){ direction[5] += h.herbivore; } if ( board[currentx + 1][currenty][2] == 1 ){ direction[5] = nogohere; } }else { direction[5] = nogohere; } //check south east direction[8] if ( ( currentx < (boardSize-1)) && ( currenty < (boardSize - 1))){ if ( board[currentx + 1][currenty + 1 ][0] == 1 ){ direction[8] += h.plant; } if ( board[currentx + 1][currenty + 1 ][1] == 1 ){ direction[8] += h.herbivore; } if ( board[currentx + 1][currenty + 1 ][2] == 1 ){ direction[8] = nogohere; } }else { direction[8] = nogohere; } //check south direction[7] if ( currenty < (boardSize-1 )){ if ( board[currentx][currenty + 1 ][0] == 1 ){ direction[7] += h.plant; } if ( board[currentx][currenty + 1 ][1] == 1 ){ direction[7] += h.herbivore; } if ( board[currentx][currenty + 1 ][2] == 1 ){ direction[7] = nogohere; } }else { direction[7] = nogohere; } //check south west direction[6] if ( (currentx > 0 ) && ( currenty < (boardSize-1)) ){ if ( board[currentx -1][currenty + 1][0] == 1 ){ direction[6] += h.plant; } if ( board[currentx -1][currenty + 1][1] == 1 ){ direction[6] += h.herbivore; } if ( board[currentx -1][currenty + 1][2] == 1 ){ direction[6] = nogohere; } }else { direction[6] = nogohere; } //check west direction[4] if ( currentx > 0 ) { if ( board[currentx-1][currenty][0] == 1 ){ direction[4] += h.plant; } if ( board[currentx-1][currenty][1] == 1 ){ direction[4] += h.herbivore; } if ( board[currentx-1][currenty][2] == 1 ){ direction[4] = nogohere; } }else { direction[4] = nogohere; } //check north west direction[1] if ( (currentx > 0 ) && ( currenty > 0 )){ if ( board[currentx-1][currenty -1 ][0] == 1 ){ direction[1] += h.plant; } if ( board[currentx-1][currenty -1 ][1] == 1 ){ direction[1] += h.herbivore; } if ( board[currentx-1][currenty -1 ][2] == 1 ){ direction[1] = nogohere; } }else { direction[1] = nogohere; } //total up directions and get best option //if all options blocked stay put double choice = 0; for ( int i=0; i<8; i++){ if ( direction[i] > choice ){ choice = direction[i]; move = i; } } return move; } ////////////////////////////////// // print game board ////////////////////////////////// static void printBoard() { for ( int i=0; i< boardSize; i++){ for ( int j=0; j matingEnergy //create clone but randomize one of ( plant|herbivore|carnivore ) //give junior half our energy Carnivore mate() { double p, h, c; int randomGene = (int)(Math.random() * 3 ); int changeSign = (int)(Math.random() * 20 ); if ( randomGene == 1 ){ p = Math.random(); if ( changeSign % 2 == 0 ){ p *= -1; } h = herbivore; c = carnivore; }else if ( randomGene == 2 ){ h = Math.random(); if ( changeSign % 2 == 1 ){ h *= -1; } p = plant; c = carnivore; }else{ p = plant; h = herbivore; c = Math.random(); if ( changeSign%2 == 0 ) {h *= -1; } } Carnivore junior = new Carnivore( p, h, c, energy/2 ); energy /=2; offspring++; //System.out.println( "Carnivore: Plant " + p + ", Herbivore " + h + ", Carnivore " + c + ", Parent's Age: " + age ); return junior; } } class Herbivore { int age = 0; int energy = 10; int offspring = 0; int x, y; double plant, herbivore, carnivore; //set weights, initial energy, board position and age Herbivore() { //set weights plant = Math.random(); herbivore = Math.random(); carnivore = Math.random(); if ( (int)(Math.random() * 10)%2 == 0 ){ plant *= -1; } if ( (int)(Math.random() * 10)%2 == 0 ){ herbivore *= -1; } if ( (int)(Math.random() * 10)%2 == 0 ){ carnivore *= -1; } } //junior comes with preset weights Herbivore ( double p, double h, double c, int e ) { plant = p; herbivore = h; carnivore = c; energy = e; } //move to a new square void move ( int d ){ if ( d == 0 ){ //stay put do nothing }else if ( d == 1 ){ x--; y--; // nw }else if ( d == 2 ){ y--; // n }else if ( d == 3 ){ x++; y--; // ne }else if ( d == 4 ){ x--; // w }else if ( d == 5 ){ x++; // e }else if ( d == 6 ){ x--; y++; // sw }else if ( d == 7 ){ y++; // s }else if ( d == 8 ){ x++; y++; // se } } // add one to our energy if we find a plant void foundFood() { energy += 5; //System.out.println ( " **ate plant, age= " + age + ", energy " + energy); } //add one to our age each round void age() { energy--; age++; } //if energy > matingEnergy //create clone except randomize of of the three ( plant|herbivore|carnivore ) //give junior half our energy Herbivore mate() { double p, h, c; int randomGene = (int)(Math.random() * 3 ); int changeSign = (int)(Math.random() * 20 ); if ( randomGene == 1 ){ p = Math.random(); if ( changeSign % 2 == 0 ){ p *= -1; } h = herbivore; c = carnivore; }else if ( randomGene == 2 ){ h = Math.random(); if ( changeSign % 2 == 1 ){ h *= -1; } p = plant; c = carnivore; }else{ p = plant; h = herbivore; c = Math.random(); if ( changeSign%2 == 0 ) {h *= -1; } } Herbivore junior = new Herbivore( p, h, c, energy/2); energy /= 2; offspring++; //System.out.println( "Herbivore: Plant " + p + ", Herbivore " + h + ", Carnivore " + c + ", Parent's Age: " + age ); return junior; } }