
// David Eck, eck@hws.edu, August 1996

import java.awt.*;

public class SymmetricMosaicWalk extends java.applet.Applet implements Runnable {

         /*
                   Applet shows a window full of colored
                   squares.  A "disturbance" moves randomly around
                   in the window, randomly changing the color of
                   each square that it visits.  The program runs
                   in an infinite loop, and so will never end on its
                   own.  The mosaic is cleared after every STEPS steps.
                   This applet uses a symmetrical random mosaic,
                   with vertical and horizontal symmetry.
         */
                
   int ROWS = 10;    // number of rows of squares; can be reset by applet param named "rows"
   int COLUMNS = 20; // number of colums of squares; can be reset by applet param named "columns"
   int STEPS = 1000; // number of steps in one random walk; after each walk,the mosaic
                     //    is clearead and a new walk is started.

   int currentRow;       // row currently containing "disturbance"
   int currentColumn;    // column currently containing "disturbance"
   MosaicCanvas mosaic;  // the actual mosaic of colored squares

   Thread runner = null; // thread for running the moving disturbance animation
   
   public void init() {
      setLayout(new BorderLayout());
      String param;
      param = getParameter("rows");
      if (param != null) {
         try {
            ROWS = Integer.parseInt(param);
         }
         catch (NumberFormatException e) {
         }
      }
      param = getParameter("columns");
      if (param != null) {
         try {
            COLUMNS = Integer.parseInt(param);
         }
         catch (NumberFormatException e) {
         }
      }
      param = getParameter("steps");
      if (param != null) {
         try {
            STEPS = Integer.parseInt(param);
         }
         catch (NumberFormatException e) {
         }
      }
      mosaic = new SymmetricMosaicCanvas(ROWS,COLUMNS);
      add("Center",mosaic);
   }
   
   public void start() {
      if (runner == null) {
         runner = new Thread(this);
         runner.start();
      }
   }
   
   public void stop() {
      if (runner != null) {
         runner.stop();
         runner = null;
      }
   }
   
   public void run() {
      currentRow = ROWS / 2;
      currentColumn = COLUMNS / 2;
      while (true) {
         for (int i=0; i<STEPS; i++) {
            changeToRandomColor(currentRow,currentColumn);
            randomMove();
            try {
               Thread.sleep(25);
            }
            catch (InterruptedException e) {
            }
         }
         mosaic.clear();
         try {
            Thread.sleep(1000);
         }
         catch (InterruptedException e) {
         }
      }
   }
   
   void fillWithRandomColors() {  // NOT USED IN THIS PROGRAM
        // fill every square, in each row and column,
        // with a random color
        for (int row=0; row < (ROWS+1) / 2; row++) {
           for (int column=0; column < (COLUMNS+1) / 2; column++) {
              changeToRandomColor(row, column);  
           }
        }
   }  // end of fillWithRandomColors()
   
   void changeToRandomColor(int rowNum, int colNum) {
        // change the square in row number rowNum and
        // column number colNum to a random color.
        double red = Math.random();    // choose random levels in range
        double green = Math.random();  //     0.0 to 1.0 for red, green, 
        double blue = Math.random();   //     and blue color components
        mosaic.setColor(rowNum,colNum,red,green,blue);  
    }  // end of changeToRandomColor()
    
    void randomMove() {
        // randomly move the disturbance in one of
        // four possible directions: up, down, left, or right;
        // if this moves the disturbance outside the window,
        // then move it to the opposit edge of the window.
        int directionNum = (int)(4*Math.random());
             // direction num is randomly set to 0, 1, 2, or 3
        switch (directionNum) {
           case 0:  // move up 
              currentRow--;
              if (currentRow < 0)
                  currentRow = ROWS - 1;
              break;
           case 1:  // move right
              currentColumn++;
              if (currentColumn >= COLUMNS)
                currentColumn = 0;
              break; 
           case 2:  // move down
              currentRow ++;
              if (currentRow >= ROWS)
                  currentRow = 0;
              break;
           case 3:  
              currentColumn--;
              if (currentColumn < 0)
                  currentColumn = COLUMNS - 1;
              break; 
        }
    }  // end of randomMove()
    
} // end of class