// Ant applet // Carl E. Bredlau // Adapted from InAndOut.java // 1-30-01 Changed accessing the canvas in the board // and generation package geneticAnt; import java.awt.*; import java.applet.*; import java.awt.event.*; public class AntApplet extends Applet implements Runnable { // For synchronizing when to restart: private Semaphore restart_sem; // For synching user input: private Semaphore input_sem; private TextField txt; // for input private TextArea output; // for showing output private Button restart_button; // Stop-Restart public Canvas board_canvas; // Draw in here private GridBagLayout gridbag = new GridBagLayout(); private boolean running = false; // Tell button which state. Also if aborted public boolean DEBUG = false; // make true for System.out messsages private static final int SIZE = 400; // Size of board in pixels private int num_ANTS = 30; // default values private int num_STATES = 6; private String console = "N"; private int num_BOARD = 20; private int num_MOVES = 100; public void init() { // Set up interface: Font f = new Font("Helvetica",Font.PLAIN,20); Font f2 = new Font("TimesRoman",Font.BOLD,20); restart_button = new Button("XXXXXXXXXXX"); Label l1 = new Label("Input:"); l1.setFont(f2); txt = new TextField(10); txt.setFont(f); Label l2 = new Label("Output:"); l2.setFont(f2); Label l3 = new Label("Board:"); l3.setFont(f2); output = new TextArea(15,40); output.setEditable(false); output.setForeground(Color.white); output.setBackground(Color.gray); output.setFont(f); Panel board_panel = new Panel(); // To display the board board_canvas = new Canvas(); board_canvas.setSize(SIZE,SIZE); board_canvas.setBackground(Color.blue); board_panel.add(board_canvas); setLayout(gridbag); constrain(this,restart_button,0,0,8,1, GridBagConstraints.HORIZONTAL, GridBagConstraints.WEST,3,0, 10,10,10,10); constrain(this,l1,0,1,1,1); constrain(this,l2,1,1,1,1); constrain(this,l3,4,1,1,1); constrain(this,txt,0,2,1,1, 0,10,0,0); constrain(this,output,1,2,3,3); constrain(this,board_panel,4,2,4,4, GridBagConstraints.BOTH, GridBagConstraints.CENTER,1,3, 0,10,10,10); restart_button.addActionListener(new ButtonListener()); txt.addActionListener(new MyTextListener()); } //Thread for monitoring the application. private RunThread runnit = null; //Thread running the application. We need it known here for the stop button. private Thread antThread = null; public void start() { if (DEBUG) System.out.println("Starting...."); // I need someone to start a new thread if the Stop button kills the app // Get a thread to monitor our application if (runnit == null){ restart_sem = new Semaphore(0,DEBUG,"restart"); runnit = new RunThread(); runnit.start(); } } // Unlike InAndOut I dont' want to stop the thread public void stop() { //I prefer to stop the thread, but.. // runnit = null; // thread will kill itself // restart_sem.V(); // if it's waiting, wake it up } // Run method for the class public void run() { try { running = true; runapp(); // User app goes here... running = false; } catch (Exception e) { String s = "*** Program error: " + e.getMessage() + " ***"; showStatus(s); write_out(s); } finally {} ; } // A thread to monitor our app. class RunThread extends Thread { Semaphore re_sem = restart_sem; // If new app is started, we don't want to P the old // restart_sem // Old thread can still be waiting, since I don't clean up public void run() { Thread curr_thread = Thread.currentThread(); while (runnit == curr_thread) { restart_button.setLabel("Stop"); restart_button.setForeground(Color.white); // Nescape Communicator does not make it red unless I click in the page restart_button.setBackground(Color.red); AntApplet.this.setVisible(true); // Sync input input_sem = new Semaphore(0,DEBUG,"input_sem"); // This thread runs the app: antThread = new Thread(AntApplet.this); Thread antLocalThread = antThread; // for checking the right version below antThread.setPriority(Thread.MIN_PRIORITY); antThread.start(); // Sleep for a while; then see if the app thread is still running and I'm still current while (antLocalThread.isAlive() && runnit == curr_thread) try { Thread.sleep(1000);} catch (InterruptedException e) {} ; if (antLocalThread.isAlive()) { antLocalThread.stop(); // stop app thread if my thread is not current // if restart InAndOutThread is a new object. Need check local copy. if (DEBUG) System.out.println("Just killed " + antLocalThread); } if (runnit != curr_thread) { if (DEBUG) System.out.println(curr_thread + " is no longer current"); break; // kill thread if leaving page } if (running) { // we aborted so... write_out("*** STOPPED! ***\n\n"); running = false; // Tell button we have stopped. } restart_button.setLabel("Start Over"); restart_button.setBackground((Color.green).darker()); AntApplet.this.setVisible(true); // wait for button re_sem.P(); } // while if (DEBUG) System.out.println(curr_thread + " is done"); } // run() } // end of class private String input = ""; // handle events... class ButtonListener implements ActionListener { public void actionPerformed(ActionEvent e) { if (!running) { restart_sem.V(); // we got the restart button pushed return; } else { write_out("\n\n*** Trying to stop. Please be patient ***"); showStatus("Trying to stop!!"); restart_button.setLabel("Stopping"); restart_button.setBackground(Color.orange); AntApplet.this.setVisible(true); antThread.stop(); // Stop the program } } } class MyTextListener implements ActionListener { public void actionPerformed (ActionEvent e) { input = txt.getText(); showStatus(input); write_out(input); txt.setText(""); input_sem.V(); // tell user data is there } } // For the user public String get_input() { while (true) { input_sem.P(); // wait for input if (input != "") { String temp = input; input = ""; return temp; } } } // For the user... public void write_out(String s) { output.insert(s + '\n', output.getText().length()); } public void write_out(String s, String prompt) { // write_out(s); output.insert(s + ' ', output.getText().length()); txt.setText(prompt); } // From Hooked on Java Ex 5-4 public void constrain(Container container, Component component, int grid_x, int grid_y, int grid_width, int grid_height, int fill, int anchor, double weight_x, double weight_y, int top, int left, int bottom, int right) { GridBagConstraints c = new GridBagConstraints(); c.gridx = grid_x; c.gridy = grid_y; c.gridwidth = grid_width; c.gridheight = grid_height; c.fill = fill; c.anchor = anchor; c.weightx = weight_x; c.weighty = weight_y; if (top+bottom+left+right > 0) c.insets = new Insets(top, left, bottom, right); ((GridBagLayout)container.getLayout()).setConstraints(component, c); container.add(component); } public void constrain(Container container, Component component, int grid_x, int grid_y, int grid_width, int grid_height) { constrain(container, component, grid_x, grid_y, grid_width, grid_height, GridBagConstraints.NONE, GridBagConstraints.NORTHWEST, 0.0, 0.0, 0, 0, 0, 0); } public void constrain(Container container, Component component, int grid_x, int grid_y, int grid_width, int grid_height, int top, int left, int bottom, int right) { constrain(container, component, grid_x, grid_y, grid_width, grid_height, GridBagConstraints.NONE, GridBagConstraints.NORTHWEST, 0.0, 0.0, top, left, bottom, right); } // Ant code is here... void runapp() { write_out("Genetic Ant algorithm...\n\nNote defaults.\n"); write_out("Output to Java Console (Y/N)?",console); console = get_input().trim().toUpperCase(); write_out("Number of ants?", String.valueOf(num_ANTS)); num_ANTS = Integer.parseInt(get_input()); write_out("Number of states?",String.valueOf(num_STATES)); num_STATES = Integer.parseInt(get_input()); write_out("Size of board?",String.valueOf(num_BOARD)); num_BOARD = Integer.parseInt(get_input()); write_out("Number of moves for an ant?",String.valueOf(num_MOVES)); num_MOVES = Integer.parseInt(get_input()); write_out("Generating ants. Please be patient."); Ants pop = new Ants(num_ANTS,num_STATES); do { Board b = new Board(num_BOARD,board_canvas); // allow graphic display b.show(); try { Thread.sleep(2000);} catch (InterruptedException e) {} ; // b.board_canvas = null; // turn off display; -- Pegasus complained b.setCanvas(null); // turn off display; pop.generate(b,num_MOVES); write_out("Best ant for generation " + pop.generation() + " has fitness " + pop.pop[0].fitness); // Text output to console: if (console.compareTo("Y") == 0) { pop.show(); pop.pop[0].show(true); Board c = (Board) b.clone(); pop.pop[0].walk(c,num_MOVES); c.show(); } // Graphic displaay // b.board_canvas = board_canvas; // show last walk b.setCanvas(board_canvas); // show last walk pop.pop[0].walk(b,num_MOVES); try { Thread.sleep(1000);} catch (InterruptedException e) {} ; } while (true); } }