// http://herselfsai.com // Very simple demo of an ai that learns where the food is and whose children evolve with // similar characteristics // This ai has lines of food drawn on a grid and they learn and evolve to remain on the lines // and to follow the food lines // import java.awt.*; import java.awt.event.*; import java.util.*; //Main public class Bugs extends Frame implements Runnable, WindowListener { int dim = 530; // window size int max = 500; // allow for title bars and margins Thread animThread; // to continuously call repaint(); long delay = 0L; // speed up or slow down animation here ( 0-1000L ) int days = 0; // how many loops have we done so far int food[][] = new int[dim][dim]; // location of food int amount_of_bugs = max; // bugs initial count ArrayList bugs = new ArrayList(); // data structure to store the bugs int energy_per_food = 1000; // amount of energy per food unit starting value Random r = new Random ( System.currentTimeMillis() ); // jump start random number generator int max_lifespan = 330; // max days to live if don't breed or starve int energy_to_breed = 600; // how many units of energy needed to divide and reproduce boolean world_created = false; // don't start drawing loop till we get ourselves setup public static void main(String[] args) { new Bugs(); } //set up window, initial food and bugs and start animation public Bugs() { //create a window --------------------------------------------------------------- super ( " Bugs " ); setBounds ( 0, 0, dim, dim ); setVisible ( true ); addWindowListener ( this ); animThread = new Thread ( this ); animThread.start(); // Create food supply for bugs to eat--------------------------------------------- for ( int i=0; i 100 ) { energy_to_breed /=2; } }else if (( current_bug_count > amount_of_bugs * 2 )&&( energy_per_food > 10)){ energy_per_food /= 2; if ( energy_to_breed < 100 ) { energy_to_breed *= 2; } } // for each bug for ( int i=0; i b.genes[direction] )&&(direction < 7)){ direction++; } if ( direction == 0 ){ // lowest possible position if ( b.x > d ){ b.x -= d; } if ( b.y > d ){ b.y -= d; } }else if ( direction == 1 ){ if ( b.y > d ) { b.y -= d; } }else if ( direction == 2 ){ if ( b.x < (max-d) ) { b.x += d; } if ( b.y > d ) { b.y -= d; } }else if ( direction == 3 ){ if ( b.x < (max-d) ) { b.x += d; } }else if ( direction == 4 ){ if ( b.x < (max-d) ){ b.x += d; } if ( b.y < (max-d) ){ b.y += d; } }else if ( direction == 5 ){ if ( b.y < (max-d) ){ b.y += d; } }else if ( direction == 6 ){ if ( b.x > d ){ b.x -= d; } if ( b.y < (max-d) ){ b.y += d; } }else if ( direction == 7 ){ if ( b.x > d ){ b.x -= d; } }else{} // no move -- top is sometimes less than 100 makes for a lazy bug // eat if food available eat it and update energy // then increase the upper range or lower range of that particular direction b.energy -= (d); // remove 1 existing energy unit per move if ( food[b.x][b.y] == 1 ){ //found food b.energy += energy_per_food; food[b.x][b.y] = 0; if( r.nextInt()%2 == 0 ){ // learn what works and adjust our genetics b.genes[direction]--; // yes gene values may overlap but no harm done } else { b.genes[direction]++; } } // update age b.lifetime += 1; // die if energy == 0 or age > ? if (( b.energy <= 0 )||( b.lifetime > max_lifespan )){ bugs.remove( i ); current_bug_count--; } // have child by splitting into 2 and deleting original if ( b.energy >= energy_to_breed ) { bugs.add( new Bug( b, r )); bugs.add( new Bug( b, r )); current_bug_count += 1; bugs.remove( i ); } } }// end if world created } //*************************************************************************************************************** //animation loop public synchronized void run() { while ( true ) { //keep animating forever!!! try { updateBoard(); // calc location repaint( 0L ); // request redraw wait(); // wait for redraw Thread.sleep( delay ); // after if happens, wait a bit } catch( Exception ex ) { System.err.println( "Error: " + ex ); } } } public void update(Graphics g) { paint(g); } //repaint the scene public synchronized void paint(Graphics g) { //draw background g.setColor( Color.white ); g.fillRect( 0, 0, dim, dim ); // if you don't mind slowing down simulation just adjust colors by lifetime or by generation to see the evolution Color background = new Color( 240, 240, 240 ); Color food_color = new Color ( 0, 200, 0 ); Color bug_color_10 = new Color ( 250, 0, 0 ); //draw food on board ( allow for margin and title bar ) for ( int i=0; i 0 ) { // food g.setColor ( food_color ); g.fillRect ( i+15, j+25, 1, 1 ); } } } // draw bugs int current_bug_count = bugs.size(); g.setColor ( bug_color_10); for ( int i=0; i 100 ){ genes[gene_to_change] = 100; } //slightly decrease one gene gene_to_change = r.nextInt(8); genes[gene_to_change] -= 2; if ( genes[gene_to_change] < 0 ){ genes[gene_to_change] = 0; } //slightly increase or decrease distance int distance_change = r.nextInt(); if ( distance_change%2 == 0 ){ if ( ( distance - distance_change ) > 0 ){ distance = distance - distance_change; } else { distance = 1; } }else{ distance++; } } }