// This applet creates, runs, and displays a simple // turing machine. The parameters it takes are a list// of rules, a starting tape, and the starting speed. // (See the start() method and html page for details.)//// Feel free to reuse, modify, and improve on this source, // all I ask is that you keep these comments at the top. // // Disclaimer: This is neither a commercial or even completely// finished project and so, simply put, use at your own risk; // I assume no responsibility for whatever this applet does. //// written by Robert Bradshaw 11/98// rwb00@flashmail.comimport java.awt.*;import java.awt.event.*;import java.applet.*;public class TuringMachineApplet extends Applet implements ActionListener {      TuringMachine theMachine;  TT machineThread;  private boolean isApplet;  private Frame ruleEditingFrame;  private Button stepBtn, slowBtn, normBtn, fastBtn, vfastBtn,          editBtn, resetBtn;  public  Button haltBtn;  // should be private but I get some access errors from some VMs that don't do inner classe right  private Image bufferImage;    // it can be run as an application too  public static void main(String[] args) {    TuringMachineApplet tma = new TuringMachineApplet();    if (args.length>=2) tma.setMachine(new TuringMachine(args[0], args[1]));    else tma.setMachine(new TuringMachine("0 0 0","  "));    tma.init(false);    tma.setBackground(Color.white);    Frame f=new Frame();        f.setTitle("Turing Machine");        f.setSize(500, 200);    f.add(tma);    f.addWindowListener(new WindowAdapter() {       public void windowClosing(WindowEvent e) {        System.exit(0);      }    });    f.show();  }      public void init() { init(true); }  public void init(boolean isApplet) {      this.isApplet=isApplet;        bufferImage=createImage(getSize().width, 50);        haltBtn=new Button("Halt");    haltBtn.addActionListener(this);    haltBtn.setEnabled(false);        stepBtn=new Button("Step");    stepBtn. addActionListener(this);        slowBtn=new Button("Slow");    slowBtn. addActionListener(this);        normBtn=new Button("Normal");    normBtn. addActionListener(this);        fastBtn=new Button("Fast");    fastBtn. addActionListener(this);        vfastBtn=new Button("Very Fast");    vfastBtn. addActionListener(this);        editBtn=new Button("Edit Rules...");    editBtn.addActionListener(this);        resetBtn=new Button("Reset");    resetBtn.addActionListener(this);            Panel p=new Panel(new FlowLayout(FlowLayout.RIGHT));   // for laying out the buttons at the bottem        p.add(haltBtn);    p.add(stepBtn);    p.add(slowBtn);    p.add(normBtn);    p.add(fastBtn);    p.add(vfastBtn);    p.add(new Label("      "));    if (isApplet) p.add(resetBtn);    //p.add(editBtn);        setLayout(new BorderLayout());    add(p, "South");    //add(p2, "North");        if (isApplet) reset();        ruleEditingFrame=new Frame();    ruleEditingFrame.setTitle("Rule Editor");    ruleEditingFrame.add(new TuringRuleEditorApplet(this));    ruleEditingFrame.addWindowListener(new WindowCloser());    ruleEditingFrame.setSize(600,300);    ruleEditingFrame.setLocation(50,50);        repaint();      }      public void start() {    String s=getParameter("state");    if (s!=null) theMachine.setState(Integer.parseInt(s));    String running=getParameter("running");    if (running!=null) {      if (running.charAt(0)=='s')        actionPerformed(new ActionEvent(slowBtn, ActionEvent.ACTION_PERFORMED, "slow"));      else if (running.charAt(0)=='n')        actionPerformed(new ActionEvent(normBtn, ActionEvent.ACTION_PERFORMED, "norm"));      else if (running.charAt(0)=='f')        actionPerformed(new ActionEvent(fastBtn, ActionEvent.ACTION_PERFORMED, "fast"));      else if (running.charAt(0)=='v')        actionPerformed(new ActionEvent(vfastBtn, ActionEvent.ACTION_PERFORMED, "vfast"));    }  }      public void stop() {    actionPerformed(new ActionEvent(haltBtn, ActionEvent.ACTION_PERFORMED, "Halt"));  }      public void reset() {    String tapeS=getParameter("tape");    String tapeIndexS=getParameter("tapeIndex");    String rulesS=getParameter("rules");    if (tapeS==null) tapeS="  ";    if (tapeIndexS==null) tapeIndexS="0";    if (rulesS==null) rulesS="";    theMachine=new TuringMachine(tapeS, Integer.parseInt(tapeIndexS), rulesS);        repaint();  }      public void actionPerformed(ActionEvent e) {    if (e.getSource() instanceof Button) {      if (e.getSource()==editBtn) {        ruleEditingFrame.show();      }      else {        if (machineThread!=null && machineThread.isAlive()) machineThread.halt();        if (e.getSource()==haltBtn || e.getSource()==resetBtn) machineThread=null;        else if (e.getSource()==stepBtn) {          if (theMachine.getState()==0) theMachine.setState(1);          theMachine.step();          machineThread=null;        }        else if (e.getSource()==slowBtn) machineThread=new ST(500);        else if (e.getSource()==normBtn) machineThread=new ST(100);        else if (e.getSource()==fastBtn) machineThread=new JT(3);        else if (e.getSource()==vfastBtn) machineThread=new JT(15);        if (machineThread!=null) machineThread.start();        else if (e.getSource()==resetBtn) reset();        haltBtn.setEnabled(machineThread!=null);        repaint();      }    }  }    void setMachine(TuringMachine tm) {    theMachine=tm;  }    void setMachineRules(TuringRule[] rules) {    if (machineThread!=null && machineThread.isAlive()) machineThread.halt();    machineThread=null;    theMachine.setRules(rules);  }    TuringRule[] getMachineRules() {    return theMachine.getRules();  }    void setMachineTape(TuringTape tape) {    if (machineThread!=null && machineThread.isAlive()) machineThread.halt();    machineThread=null;    theMachine.setTape(tape);    repaint();  }    void setMachineState(int i) {    if (machineThread!=null && machineThread.isAlive()) machineThread.halt();    machineThread=null;    theMachine.setState(i);    repaint();  }    public void update(Graphics g) {    paint(g);  }    public void paint(Graphics g) {    // the first couple lines of this belong in     // the update method, but on netscape in the NT lab    // update() doesn't alwasy get called before paint()    if (bufferImage==null || bufferImage.getWidth(this)<getSize().width)      bufferImage=createImage(getSize().width, 50);    Graphics bufferG=bufferImage.getGraphics();    bufferG.setColor(getBackground());    bufferG.fillRect(0, 0, getSize().width, 50);    theMachine.draw(bufferG, new Rectangle(0, 0, getSize().width-4, 50));    g.drawImage(bufferImage, 2, 0, this);  }      // inner class names shortened so class name not truncated      abstract class TT extends Thread {  // TuringThread    int curRule;    boolean halted;    public void halt() {      halted=true;    }    public void run() {      halted=false;      if (theMachine.getState()==0) theMachine.setState(1);    }  }    class ST extends TT {  // SleepyThread extends TuringThread    int t;    public ST(int t) { this.t=t; }    public void run() {      super.run();      try {        while (!halted && curRule>=0) {          curRule=theMachine.step();          repaint();          Thread.sleep(t);       }      } catch (Exception e) { e.printStackTrace(System.out); }      if (curRule<0) haltBtn.setEnabled(false);    }  }    class JT extends TT {   // JumpyThread extends TuringThread    int c;    public JT(int c) { this.c=c; }    public void run() {      super.run();      int i;      try {        while (!halted && curRule>=0) {                        for(i=0; i<c && !halted; i++){            curRule=theMachine.step();            Thread.yield();              }          repaint();          Thread.yield();        }      } catch (Exception e) { e.printStackTrace(System.out); }      if (curRule<0) haltBtn.setEnabled(false);    }  }    }