


import java.util.concurrent.Semaphore;

import info.gridworld.grid.Grid;
import info.gridworld.world.World;

/**
 *  Extend this world for a step-by-step simulation. Supply a run 
 *  method that occasionally calls pause.
 *  <p>
 *  copyright&copy; 2005 Cay S. Horstmann (http://horstmann.com)
 *
 *  @author Cay Horstmann
 */

public abstract class StepWorld<T> extends World<T> implements Runnable 
{  
   public StepWorld()
   {   
      init();
   }
   
   public StepWorld(Grid<T> grid)
   {
      super(grid);
      init();
   }
   
   public abstract void run();
   
   public void pause(String message)
   {
      setMessage(message);
      pause();
   }

   public void pause()
   {
      try
      {
         s.acquire();
      }
      catch (InterruptedException e)
      {
         Thread.currentThread().interrupt();
      }
   }
      
   public void step()
   {
      s.release();
      try
      {
         Thread.sleep(100);
      }
      catch (InterruptedException e)
      {
         Thread.currentThread().interrupt();
      }      
   }

   private void init()
   {
      setMessage("Click the Step button.");
      Thread t = new Thread(new 
            Runnable()
            {
               public void run()
               {
                  try
                  {
                     s.acquire();
                     StepWorld.this.run();
                     setMessage("Done.");
                  }
                  catch (InterruptedException ex)
                  {
                     // terminate thread
                  }
               }
            });
      t.start();
   }
   
   private Semaphore s = new Semaphore(0);
}
