import com.nttdocomo.ui.*;
import com.nttdocomo.io.*;
import com.nttdocomo.util.*;

import java.util.Random;
/**
 *
 * Spiral Game for NTT Docomo iAppli platform
 *
 * (C) 2001 Beartronics 
 * Author: Henry Minsky (hqm@alum.mit.edu)
 *
 * Licensed under terms "Artistic License"
 * http://www.opensource.org/licenses/artistic-license.html
 *
 */

public class TailApp extends IApplication {
	public void start() {
	    Canvas c = new TailCanvas(this);
	    Display.setCurrent(c);
	}
}

class TailCanvas extends Canvas implements TimerListener{
    private IApplication app;

    static final int CELLSIZE = 2;

    byte[][] points;

    int drawPtr = 0;
    int erasePtr = 0;

    int time = 0;
    
    int x;
    int y;

    // computer opponent
    int cx;
    int cy;
    int cdx;
    int cdy;

    int dx = 0;
    int dy = 0;

    int xmax;
    int ymax;
    int screenWidth;
    int screenHeight;

    Timer t;
    int speed;
    static final int START_SPEED = 100;

    Random rand;
    boolean newGame = true;

    TailCanvas(IApplication app) {
	screenWidth = getWidth();
	screenHeight = getHeight();
	xmax = (screenWidth / CELLSIZE) -1;
	ymax = (screenHeight / CELLSIZE) -1;
	points = new byte[xmax+1][ymax+1];
	t = new Timer();
	this.app = app;
        setSoftLabel(Frame.SOFT_KEY_1, "Exit");
	rand = new Random();
	newGame();
    }

    void newGame() {
	x = xmax / 2;
	y = ymax / 2;
	cx = Math.abs(rand.nextInt()) % (xmax-1);
	cy = Math.abs(rand.nextInt()) % (ymax-1);
	switch (rand.nextInt() % 4) {
	    case 0:
		cdx = -1;
		cdy = 0;
		break;
	    case 1:
		cdx = 1;
		cdy = 0;
		break;
	    case 2:
		cdx = 0;
		cdy = -1;
		break;
	    case 3:
		cdx = 0;
		cdy = 1;
		break;
	}
	switch (rand.nextInt() % 4) {
	    case 0:
		dx = -1;
		dy = 0;
		break;
	    case 1:
		dx = 1;
		dy = 0;
		break;
	    case 2:
		dx = 0;
		dy = -1;
		break;
	    case 3:
		dx = 0;
		dy = 1;
		break;
	}

	time = 0;
	speed = START_SPEED;

	for (int i = 0; i < xmax+1; i++) {
	    for (int j = 0; j < ymax+1; j++) {
		points[i][j] = 0;
	    }
	}

	newGame = true;
	repaint();

	t.setRepeat(true);
	t.setTime(speed);
	t.setListener(this);
	t.start();

    }

    int wrap (int val, int bound) {
	if (val < 0) {
	    return bound;
	} else if (val > bound) {
	    return 0; 
	} else {
	    return val;
	}
    }

    public void timerExpired (Timer source) {
	if (((time % 5) == 0) && (speed > 10)) {
	    speed -= 1;
	}
	time++;

	int wall;

	////////////////////////////////////////////////////////////////
	// Play the computer opponent

	if ((time % 10) == 0) {
	    // change direction
	    if (cdx == 0) {
		switch ((rand.nextInt() % 3)) {
		case 0: 
		    cdx = 1;
		    cdy = 0;
			break;
		case 1:
		    cdx = -1;
		    cdy = 0;
			break;
		case 2: 
			break;
		}
	    } else {
		switch ((rand.nextInt() % 3)) {
		case 0: 
		    cdy = 1;
		    cdx = 0;
		    break;
		case 1:
		    cdy = -1;
		    cdx = 0;
		    break;
		case 2: 
		    break;
		}
	    }
	}

	int tcx = cx + cdx;
	int tcy = cy + cdy;

	tcx = wrap(tcx, xmax);
	tcy = wrap(tcy, ymax);

	wall = points[tcx][tcy];
	// If computer is about to hit a wall, turn.
	// 		if ((rand.nextInt() % 2) == 0) {
	if (wall != 0) {
	    int whatsUp = points[cx][wrap(cy-1,ymax)];
	    int whatsDown = points[cx][wrap(cy+1,ymax)];
	    int whatsLeft = points[wrap(cx-1, xmax)][cy];
	    int whatsRight = points[wrap(cx+1, xmax)][cy];
	    if (whatsUp == 0) {
		cdx = 0;
		cdy = -1;
	    } else if (whatsDown == 0) {
		cdx = 0;
		cdy = +1;
	    } else if (whatsLeft == 0) {
		cdx = -1;
		cdy = 0;
	    } else if (whatsRight == 0) {
		cdx = 1;
		cdy = 0;
	    } 
	}

	cx = wrap(cx+cdx, xmax);
	cy = wrap(cy+cdy, ymax);

	wall = points[cx][cy];
	if (wall != 0) {
	    endGame(true);
	}

	x = wrap(x+dx, xmax);
	y = wrap(y+dy, ymax);

	wall = points[x][y];
	if (wall != 0) {
	    endGame(false);
	}

	points[cx][cy] = 1;
	points[x][y] = 1;

        repaint();
    }

    public void processEvent(int eventType, int param) {

	if (Display.KEY_PRESSED_EVENT == eventType) {
	    if ((param == Display.KEY_LEFT) ||
		(param == Display.KEY_1)){
		dx = -1;
		dy = 0;
	    } else if ((param == Display.KEY_RIGHT) ||
		       (param == Display.KEY_3)){
		dx = 1;
		dy = 0;
	    } else if ((param == Display.KEY_UP) ||
		       (param == Display.KEY_2)){
		dy = -1;
		dx = 0;
	    } else if ((param == Display.KEY_DOWN) ||
		       (param == Display.KEY_5)){
		dy = 1;
		dx = 0;
	    }

            if (param == Display.KEY_SOFT1)
                app.terminate();
	}
    }

    Dialog wonDialog = new Dialog(Dialog.DIALOG_INFO, "You Won!!");
    Dialog lostDialog = new Dialog(Dialog.DIALOG_INFO, "You Lost!!");

    void endGame(boolean playWins) {
	Dialog dialog;
	t.stop();
	if (playWins) {
	    dialog = wonDialog;
	} else {
	    dialog = lostDialog;
	}
	dialog.setText("Score "+time+" Squiral - hqm@ai.mit.edu");
	dialog.show();
	newGame();
    }

    public void paint(Graphics g) {
	g.lock();
	if (newGame) {
	    g.setColor(g.getColorOfRGB(0,0,0));
	    g.fillRect(0, 0, screenWidth, screenHeight);
	    newGame = false;
	}
	g.setColor(g.getColorOfRGB(0xFF,0xFF,0xFF));
	g.fillRect(x * CELLSIZE, y * CELLSIZE, CELLSIZE, CELLSIZE);
	g.setColor(g.getColorOfRGB(0xFF,0x7F,0x2F));
	g.fillRect(cx * CELLSIZE, cy * CELLSIZE, CELLSIZE, CELLSIZE);
	Font f = Font.getDefaultFont();
	g.unlock(true);
   }

}