
import java.awt.*;
import java.util.*;
import java.awt.event.*;



public class BugWorld extends Frame implements WindowListener, MouseListener
       {
         public static final int NUM_ROWS = 4;
         public static final int NUM_COLS = 4;
         public static final int CELL_WIDTH = 40;
         public static final int CELL_HEIGHT = 40;
         public static final int INIT_HEALTH = 4;
         public static final int CELL_FOOD_CAPACITY = 4;
         public static final int COST_OF_STAYING_STILL = 3;
         public static final int COST_OF_MOVING = 4;
         private static int num_bugs;
         private static int t=0;        // Counter for number of time steps.
         private static Graphics g;
         private static BugWorld this_world;

         private static LinkedList allBugs = new LinkedList();
         public static LinkedList cells[][] =
                        new LinkedList[NUM_COLS][NUM_ROWS];



         public static void main(String [] arguments) throws Exception
			  {

			    this_world = new BugWorld();
			    boolean end = false;
			    while(!end)
			       {
			         Thread.sleep(100);   //  Pause between screen updates
			         t++;                //  Time moves ahead
			         feed_Bugs();
			         squash_Bugs();       //
			         remove_dead_bugs();
			         this_world.paint(g);    // Re-paint everything.
			         move_Bugs();
			   }

			  }


         public BugWorld()
             {
                super("  Splat! World  ");  //  Create and name window
                setSize(NUM_COLS*CELL_WIDTH+15,NUM_ROWS*CELL_HEIGHT+10);
                                         //  Set initial size
                setBackground(Color.yellow.brighter()); // Initial back. color
                setVisible(true);                //  Display it!

                addWindowListener(this); //  Tell Java runner that this frame
                addMouseListener(this);  //   obj will handle Window events
                                    //   and mouse events, so give them
                                    //   to us!

                allBugs.add(new Jeffsbug());

		        num_bugs = allBugs.size();

		        for(int i=0; i<NUM_ROWS;i++)
		            for(int j=0; j<NUM_COLS;j++)
		                cells[i][j] = new LinkedList();

		        for(int i=0;i<num_bugs;i++)
		            {
				      Bug current_bug = (Bug) allBugs.get(i);
		              current_bug.row = (int) (Math.random() * NUM_ROWS);
		              current_bug.column = (int) (Math.random() * NUM_COLS);
		              cells[current_bug.row]
		                   [current_bug.column].add(current_bug);
		   			}

                t= 0;                      //  Start timer at 0.
                g = getGraphics();

		  	  }

 		 private static int [] neighborhood(Bug a_bug)
	 	       {
				 int row = a_bug.row;
				 int column = a_bug.column;

				 int north = row-1;
				 int south = row+1;
				 int east = column-1;
				 int west = column+1;

				 north = (NUM_ROWS+north)%NUM_ROWS;  // implement wrap-around
				 south = (NUM_ROWS+south)%NUM_ROWS;
				 east = (NUM_COLS+east)%NUM_COLS;
				 west = (NUM_COLS+west)%NUM_COLS;

				 int von_Neumann[] = new int[10];

				 von_Neumann[0]=cells[row][column].indexOf(a_bug);
				 von_Neumann[1]=cells[north][west].size();
				 von_Neumann[2]=cells[north][column].size();;
				 von_Neumann[3]=cells[north][east].size();
				 von_Neumann[4]=cells[row][west].size();
				 von_Neumann[5]=cells[row][column].size();
				 von_Neumann[6]=cells[row][east].size();
				 von_Neumann[7]=cells[south][west].size();
				 von_Neumann[8]=cells[south][column].size();
				 von_Neumann[9]=cells[south][east].size();

				 return von_Neumann;
			   }

         public static void move_Bugs()
		      {
				num_bugs = allBugs.size();
				Bug current_bug;
	            for(int i=0; i<num_bugs; i++)
	                {
				      current_bug = (Bug) allBugs.get(i);
					  current_bug.make_move(neighborhood(current_bug));
				    }
		      }

		 public static void feed_Bugs()
		      {
			   num_bugs = allBugs.size();
			   Bug current_bug;
			   int pos_in_stack;
               for(int i=0; i<num_bugs; i++)
                   {
					current_bug = (Bug) allBugs.get(i);
					pos_in_stack =
					     cells[current_bug.row][current_bug.column].indexOf(current_bug);
					if(pos_in_stack   < CELL_FOOD_CAPACITY)
					     current_bug.health += CELL_FOOD_CAPACITY - pos_in_stack;
				    }
		       }

         public static void squash_Bugs()
               {
				 Bug current_bug;
				 int row; int column;
				 int num_above;  // number of bugs on your back.
				 for(int i=0; i<allBugs.size(); i++)
				    {
					  current_bug = (Bug) allBugs.get(i);
					  row = current_bug.row;
					  column = current_bug.column;
					  num_above = cells[row][column].size() - 1
					               - cells[row][column].indexOf(current_bug);
					  if(Math.random()*5 < num_above)
					    {
						  current_bug.health = -100;
						  System.out.println("The bug "+
						                      current_bug.getName()+
						                      " gets squished!");
					     }
				     }


			    }

	     public static void remove_dead_bugs()
	           {
				 Bug current_bug;
				 for(int i=0; i< allBugs.size(); i++)
				     {
					   current_bug = (Bug) allBugs.get(i);
					   if(current_bug.health < 0)
					      {
							current_bug.epitath();
							allBugs.remove(current_bug);
							cells[current_bug.row]
							     [current_bug.column].remove(current_bug);
					      }
				      }
				}

         public void paint(Graphics g)
              {
				g.clearRect(0,0,NUM_COLS*CELL_WIDTH,NUM_ROWS*CELL_HEIGHT);
				num_bugs = allBugs.size();
                for (int i=0; i < num_bugs; i++)
                     {
					Bug current_bug =  (Bug) allBugs.get(i);
         //            ((Bug) allBugs.get(i)).paint(g);
                        current_bug.paint(g);
                        System.out.println("health = " + current_bug.health);
				  }

              }

  //  Methods needed to implement the "WindowListener" interface

     public void windowOpened(WindowEvent win_ev)  {}
     public void windowClosing(WindowEvent win_ev)  // Catches click on
                 {                                  //  the window's "X"
                  dispose();
                  }
     public void windowClosed(WindowEvent win_ev)   {}
     public void windowActivated(WindowEvent win_ev)  {}
     public void windowDeactivated(WindowEvent win_ev)  {}
     public void windowIconified(WindowEvent win_ev)  {}
     public void windowDeiconified(WindowEvent win_ev)  {}

  //  Methods needed to implement the "MouseListener" interface

     public void mouseClicked(MouseEvent me)
                  {
                    System.out.println("mouse click at " +
                                       me.getX() + ", " + me.getY());
                    }
     public void mouseEntered(MouseEvent me)  {}
     public void mouseExited(MouseEvent me)  {}
     public void mousePressed(MouseEvent me)  {}
     public void mouseReleased(MouseEvent me)  {}


        }

