/** An application that plays the game of Snake.
 *
 * @author	Jim Grundy
 * @version	$Revision: 1.7 $ */

import java.awt.Frame;			// Frames, i.e screen windows.
import java.awt.Color;			// Colors.
import java.awt.BorderLayout;		// Layout information in a frame.
import java.awt.event.KeyAdapter;	// Adaptable keyboard event handling.
import java.awt.event.KeyEvent;		// Things that happen on the keyboard.
import java.util.Random;// Random number generator.

public class Slither implements Runnable {
    
    private Frame display;		// Frame in which game is displayed.
    private ObjectField field;		// 
    private PlayerSnake player;		// The player's snake,
    private RobotSnake robot;		// The robot opponent's snake.
    private static final int MOVE_DELAY = 200;	// ms between moves.
    private static final int FOOD_FREQ = 10;	// twice av moves before food.
    private static final int WIDTH = 30;	// Width of a GrassField
    private static final int HEIGHT = 30;	// Height of a GrassField
    private static final int EDGE = 10;	// Edge length of a GrassField tile.
    private static final Color BACKGROUND = Color.black; // Background color.
    private static final Random RANDOM = new Random(); 
    
    /* Create a new Slither game. */
    private Slither() {
	/* Create a frame to display the game and a GrassField on which
	 * to play it.  Then, pack the field into the frame and display
	 * it.  */
	PlayingField tiles = new PlayingField(WIDTH,HEIGHT,EDGE,BACKGROUND);
	display = new Frame("Slither");
	display.setLayout(new BorderLayout());
	display.add("North",tiles);
	display.pack();
	display.show();
	
	/* Make snakes for the player and their opponent. */
	field = new ObjectField(tiles);
	player = new PlayerSnake(field,WIDTH/3,HEIGHT/2);
	robot = new RobotSnake(field,(2*WIDTH)/3,HEIGHT/2);
	
	/* Keyboard events in window are handled as follows: */
	tiles.addKeyListener
	    (new KeyAdapter()
	     {
		 public void keyPressed(KeyEvent e)
		     {
			 switch (e.getKeyCode()) {
			 case KeyEvent.VK_RIGHT:
			     synchronized (field) {
				 player.turnRight();
			     }
			     break;
			 case KeyEvent.VK_LEFT:
			     synchronized (field) {
				 player.turnLeft();
			     }
			     break;
			 case KeyEvent.VK_ESCAPE:
			     System.exit(0);
			     break;
			 case KeyEvent.VK_P:
			     System.out.println(field);
			     break;
			 }
		     }
	     });
    }
    
    /** Play the game of Slither. */
    public void run()
    {
	int foodMoves = 0;	// Moves until next food drop.
	do {
	    /* Drop some food. */
	    if ((RANDOM.nextInt() % FOOD_FREQ) == 0) {
		synchronized (field) {
		    new Food(field);
		}
	    }
	    synchronized (field) {
		player.move();
	    }
	    synchronized (field) {
		robot.think();
		robot.move();
	    }
	    try {
		Thread.sleep(MOVE_DELAY);
	    } catch (InterruptedException e) {
		/* Just ignore interruptions. */
	    }

	} while (player.isAlive());
	System.exit(0);
    }
    
    /** Create a Slither game and run it.
     *
     * @param args The command line arguments (ignored). */
    public static void main(String[] args) {
	Runnable game = new Slither();
	new Thread(game).start();
    }
    
}

