/** * Written by Josh Lifton 10MAY2000. * Copyright (c) Josh Lifton 2000. * The GUI for a flocking applet. */ import java.applet.*; import java.awt.*; import java.awt.event.*; import java.util.*; public class FlockGUI extends Applet implements Runnable, ActionListener, ComponentListener, WindowListener { private Thread thread; public boolean pauseFlag; public Flock flock; public Panel buttons, room; private Button pause, reset, GAMode; private TextField initialNumber, numberOfTeams; private Label initialNumberLabel, numberOfTeamsLabel, meanHeadingLabel, meanSpeedLabel, meanXLabel, meanYLabel, meanHeading, meanSpeed, meanX, meanY, boutLabel, bout, generationLabel, generation, timeLabel, timeDisplay; private int time, height, width; /** Method called when used as an application. */ public static void main(String args[]) { FlockGUI flockGUI = new FlockGUI(); flockGUI.init(); Frame frame = new Frame("Genetically Engineered Battle Boids"); frame.addWindowListener(flockGUI); flockGUI.room.addComponentListener(flockGUI); frame.setSize(flockGUI.getSize()); frame.setVisible(true); frame.add("Center", flockGUI); flockGUI.start(); } public void init() { time = 0; height = 500; width = 500; setLayout(new BorderLayout()); setSize(width+200, height); setBackground(Color.cyan); buttons = new Panel(); buttons.setSize(200, height); buttons.setLayout(new GridLayout(11,2)); buttons.setBackground(new Color(99,44,99)); buttons.setForeground(Color.yellow); room = new Panel(); room.setSize(width, height); room.setBackground(new Color(88,99,88)); pause = new Button("Pause"); pause.addActionListener(this); pause.setBackground(buttons.getBackground()); pause.setForeground(buttons.getForeground()); reset = new Button("Reset"); reset.addActionListener(this); reset.setBackground(buttons.getBackground()); reset.setForeground(buttons.getForeground()); GAMode = new Button("GA Mode"); GAMode.addActionListener(this); GAMode.setBackground(buttons.getBackground()); GAMode.setForeground(buttons.getForeground()); initialNumberLabel = new Label("Number per Team:"); initialNumber = new TextField("20", 6); initialNumber.addActionListener(this); numberOfTeamsLabel = new Label("Number of Teams:"); numberOfTeams = new TextField("2", 2); numberOfTeams.addActionListener(this); flock = new Flock((Integer.valueOf(initialNumber.getText())).intValue(), (Integer.valueOf(numberOfTeams.getText())).intValue(), height, width); meanHeadingLabel = new Label("Direction:"); meanHeading = new Label(String.valueOf(flock.getMeanHeading())); meanSpeedLabel = new Label("Speed:"); meanSpeed = new Label(String.valueOf(flock.getMeanSpeed())); meanXLabel = new Label("Mean X:"); meanX = new Label(String.valueOf(flock.getMeanX())); meanYLabel = new Label("Mean Y:"); meanY = new Label(String.valueOf(flock.getMeanY())); boutLabel = new Label("Bout:"); bout = new Label(); generationLabel = new Label("Generation:"); generation = new Label(); timeLabel = new Label("Time:"); timeDisplay = new Label(); buttons.add(initialNumberLabel); buttons.add(initialNumber); buttons.add(numberOfTeamsLabel); buttons.add(numberOfTeams); buttons.add(meanHeadingLabel); buttons.add(meanHeading); buttons.add(meanSpeedLabel); buttons.add(meanSpeed); buttons.add(meanXLabel); buttons.add(meanX); buttons.add(meanYLabel); buttons.add(meanY); buttons.add(timeLabel); buttons.add(timeDisplay); buttons.add(boutLabel); buttons.add(bout); buttons.add(generationLabel); buttons.add(generation); buttons.add(pause); buttons.add(reset); buttons.add(GAMode); add("Center", room); add("East", buttons); setVisible(true); pauseFlag = false; start(); } public void start() { if (thread == null) { thread = new Thread(this); thread.start(); } } public void stop() { if (thread != null) { thread.destroy(); thread = null; } } public void run() { while (true) { while(!pauseFlag) { if (flock.getGAFlag()) { runGA(); } else { time = time + 1; flock.moveMembers(); updateGUI(); repaint(); try { Thread.sleep(20); } catch (InterruptedException exception) { } } } } } public void runGA() { pause.removeActionListener(this); reset.removeActionListener(this); GAMode.removeActionListener(this); flock.setGAFlag(true); initialNumber.setEditable(false); numberOfTeams.setEditable(false); flock.setNumberOfTeams(2); initialNumber.setText("2"); flock.setNumberOfMembers(20); numberOfTeams.setText("20"); int population = 100; int totalBouts = 10; int generations = 100; BoidGene[] genes = new BoidGene[population]; BoidGene[] newGenes = new BoidGene[population]; BoidGene mom, dad; Random random = new Random(); int challenger; double beta = 0.1; for (int p=0; p maxSpeed) { maxSpeed = minSpeed; } turnRate = random.nextDouble(); accel = 0.15*random.nextDouble(); sRange = 0.25*flock.getWidth()*random.nextDouble(); cRange = 0.1*flock.getWidth()*random.nextDouble(); attackC = 5.0*random.nextDouble(); retreatC = 5.0*random.nextDouble(); genes[p] = new BoidGene( heading, speed, x, y, maxSpeed, minSpeed, Color.red, turnRate, accel, sRange, 10.0, // death range 0.23109, // death constant cRange, attackC, retreatC, flock); // home flock } for (int g=0; g0) { genes[p].setTrialsWon(genes[p].getTrialsWon() + 1); } else { genes[challenger].setTrialsWon(genes[challenger].getTrialsWon() + 1); } } } } } /* Reproduce and mutate. */ for (int p=0; p random.nextDouble()) { mom = null; } } while (dad == null) { dad = genes[(int) Math.floor(population*random.nextDouble())]; if (Math.exp(-beta*(1.0 - dad.getFitness())) > random.nextDouble()) { dad = null; } } newGenes[p] = mom.reproduceWith(dad); } genes = newGenes; } initialNumber.setEditable(true); numberOfTeams.setEditable(true); flock.setGAFlag(false); GAMode.addActionListener(this); reset.addActionListener(this); pause.addActionListener(this); bout.setText(""); generation.setText(""); } public void updateGUI() { meanHeading.setText(String.valueOf(flock.getMeanHeading())); meanSpeed.setText(String.valueOf(flock.getMeanSpeed())); meanX.setText(String.valueOf(flock.getMeanX())); meanY.setText(String.valueOf(flock.getMeanY())); timeDisplay.setText(String.valueOf(time)); } public synchronized void paint(Graphics g) { Enumeration e = flock.elements(); Boid boid; int[] xPoints = {0,0,0}; int[] yPoints = {0,0,0}; g = room.getGraphics(); g.clearRect(0, 0, room.getSize().width, room.getSize().height); while (e.hasMoreElements()) { boid = (Boid) e.nextElement(); g.setColor(boid.getColor()); xPoints[0] = (int) (boid.getX()+10.0*Math.cos(boid.getHeading())); yPoints[0] = (int) (boid.getY()+10.0*Math.sin(boid.getHeading())); xPoints[1] = (int) (boid.getX()+5.0*Math.cos(boid.getHeading() + (2.0/3.0)*Math.PI)); yPoints[1] = (int) (boid.getY()+5.0*Math.sin(boid.getHeading() + (2.0/3.0)*Math.PI)); xPoints[2] = (int) (boid.getX()+5.0*Math.cos(boid.getHeading() - (2.0/3.0)*Math.PI)); yPoints[2] = (int) (boid.getY()+5.0*Math.sin(boid.getHeading() - (2.0/3.0)*Math.PI)); g.fillPolygon(xPoints, yPoints, 3); } } public void update(Graphics g) { paint(g); } public void actionPerformed(ActionEvent event) { if (event.getSource() instanceof Button) { Button source = (Button) event.getSource(); if (source == pause) { pauseFlag = !pauseFlag; if (pauseFlag) { pause.setLabel("Resume"); } else { pause.setLabel("Pause"); } } if (source == reset) { flock.initializeFlock(); time = 0; } if (source == GAMode) { flock.setGAFlag(!flock.getGAFlag()); } } if (event.getSource() instanceof TextField) { TextField source = (TextField) event.getSource(); if (source == initialNumber) { flock.setNumberOfMembers((Integer.valueOf(initialNumber.getText())).intValue()); flock.initializeFlock(); time = 0; } if (source == numberOfTeams) { flock.setNumberOfTeams((Integer.valueOf(numberOfTeams.getText())).intValue()); flock.initializeFlock(); time = 0; } } } public void windowActivated(WindowEvent e) {} public void windowClosed(WindowEvent e) { System.exit(0); } public void windowClosing(WindowEvent e) {} public void windowDeactivated(WindowEvent e) {} public void windowDeiconified(WindowEvent e) {} public void windowIconified(WindowEvent e) {} public void windowOpened(WindowEvent e) {} public void componentHidden(ComponentEvent e) {} public void componentMoved(ComponentEvent e) {} public void componentResized(ComponentEvent e) { if (e.getSource() == room) { flock.setWidth(room.getWidth()); flock.setHeight(room.getHeight()); } } public void componentShown(ComponentEvent e) {} }