/* * SwarmApplet.java * * (C) 2005, Alex S. */ import java.applet.*; import java.awt.*; import java.awt.image.*; import java.util.*; class Ant { public float x; public float y; public float speed; public float direction; public int mode; public static final int SEEKING = 0; public static final int CARRYING = 1; public float pheromone; public Ant(float x,float y,float speed,float direction,int mode,float pheromone){ this.x = x; this.y = y; this.speed = speed; this.direction = direction; this.mode = mode; this.pheromone = pheromone; } public int getX(){ return (int)Math.floor(x); } public int getY(){ return (int)Math.floor(y); } } class StateProps { public float value; public int type; public static final int NEUTRAL = 0; public static final int GIVING = 1; public static final int TAKING = 2; public StateProps(float v){ value = v; type = NEUTRAL; } } class World { public int width,height; public StateProps[] states; public Vector ants; public World(int w,int h){ width = w; height = h; states = new StateProps[w * h]; for(int i=0;i vals[i].value){ min = i; } if(lastval.value != vals[i].value){ allsame = 0; } } if(allsame == 0){ return (float)Math.atan2(ys[min],xs[min]); } return dir; } public void moveants(){ Enumeration enum = ants.elements(); while(enum.hasMoreElements()){ Ant ant = (Ant)enum.nextElement(); StateProps box = getVal(ant.getX(),ant.getY()); // adjust ant's pheromone (via learning rule; goes down to 0.5) ant.pheromone = (float)(ant.pheromone + 0.01 * (0.5 - ant.pheromone)); if(box.type == box.GIVING){ ant.mode = Ant.CARRYING; ant.pheromone = (float)1.0; }else if(box.type == box.TAKING){ ant.mode = Ant.SEEKING; ant.pheromone = (float)0.0; }else{ // adjust current box's value (via a learning rule on this ant's value) box.value = (float)(box.value + 0.01 * (ant.pheromone - box.value)); } if(ant.mode == Ant.CARRYING){ ant.direction = findmindir((int)ant.x,(int)ant.y,ant.direction); }else if(ant.mode == Ant.SEEKING){ ant.direction = findmaxdir((int)ant.x,(int)ant.y,ant.direction); } float sin = (float)Math.sin(ant.direction); float cos = (float)Math.cos(ant.direction); float nx = ant.x + cos * ant.speed; float ny = ant.y + sin * ant.speed; if(nx > width-1){ nx -= width; //cos = -cos; } if(nx < 0){ nx += width; //cos = -cos; } if(ny > height-1){ ny -= height; //sin = -sin; } if(ny < 0){ ny += height; //sin = -sin; } //ant.direction = (float)Math.atan2(sin,cos); ant.x = nx; ant.y = ny; } } } /** * BufferedCanvas */ class BufferedPixCanvas extends Canvas { private Applet parent = null; private Image image; private Graphics buffer = null; private Thread t; private Rectangle r = new Rectangle(0, 0, 0, 0); private World world; public boolean renderAnts = true; public boolean renderSeeking = true; public boolean renderCarrying = true; public BufferedPixCanvas(Applet p){ parent = p; } public void update(Graphics g) { if (r.width != bounds().width || r.height != bounds().height) { image = parent.createImage(bounds().width, bounds().height); buffer = image.getGraphics(); r = bounds(); init(); } world.moveants(); render(buffer); if (image != null){ g.drawImage(image,0,0,this); } } // initialize swarm, and food sources (food destinations). public void init(){ world = new World(r.width / 4,r.height / 4); world.getVal((int)(world.width * 1.5/4.0), (int)(world.height * 2.5/4.0)).type = StateProps.GIVING; world.getVal((int)(world.width * 1.5/4.0), (int)(world.height * 2.5/4.0)).value = (float)1.0; world.getVal((int)(world.width * 2.5/4.0), (int)(world.height * 1.5/4.0)).type = StateProps.TAKING; world.getVal((int)(world.width * 2.5/4.0), (int)(world.height * 1.5/4.0)).value = (float)0.0; for(int i=0;i<1000;i++){ if(Math.random() > 0.5){ world.ants.addElement( new Ant( (float)(Math.random()*world.width), (float)(Math.random()*world.height), (float)1, (float)(Math.random()*Math.PI*2), Ant.CARRYING, (float)1.0 ) ); }else{ world.ants.addElement( new Ant( (float)(Math.random()*world.width), (float)(Math.random()*world.height), (float)1, (float)(Math.random()*Math.PI*2), Ant.SEEKING, (float)0.0 ) ); } } } /** * does the rendering (except for background) */ public void render(Graphics g){ float xr = r.width / world.width; float yr = r.height / world.height; for(int y=0;y