/* lemons -- they follow your every whim
 * by Dale Wick
 * 2000 08 29
 */
import java.applet.*;
import java.awt.*;
import java.awt.image.*;
import java.util.*;

public class Lemons extends Applet implements Runnable
{
	final int BGTILE=0;
	final int HTILE=1;
	final int VTILE=2;
	final int SQTILE=3;
	final int HEROTILE=4;
	final int BADTILE=5;
	final int ENTERANCE=6;
	final int EXITDOOR=7;
	final int TILECOUNT=8;

	final int TILEWIDTH=20;
	final int TILEHEIGHT=20;
	final int TILESACROSS=32;
	final int TILESDOWN=16;

	final int MAXLEMON=50;

	Image tileImage[]=new Image[8];
	final char tile[][] = {
	{ /* BGTILE */
		0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0,
		0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0,
		0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0,
		0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0,
		0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0,

		0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0,
		0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0,
		0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0,
		0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0,
		0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0,

		0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0,
		0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0,
		0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0,
		0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0,
		0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0,

		0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0,
		0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0,
		0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0,
		0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0,
		0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0,
	},{ /* HTILE */
		0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0,
		0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0,
		0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0,
		0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0,
		0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0,

		3,3,3,3,3, 3,3,3,3,3, 3,3,3,3,3, 3,3,3,3,3,
		3,3,3,3,3, 3,3,3,3,3, 3,3,3,3,3, 3,3,3,3,3,
		3,3,3,3,3, 3,3,3,3,3, 3,3,3,3,3, 3,3,3,3,3,
		3,3,3,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,3,3,3,
		3,3,3,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,3,3,3,

		3,3,3,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,3,3,3,
		3,3,3,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,3,3,3,
		3,3,3,3,3, 3,3,3,3,3, 3,3,3,3,3, 3,3,3,3,3,
		3,3,3,3,3, 3,3,3,3,3, 3,3,3,3,3, 3,3,3,3,3,
		3,3,3,3,3, 3,3,3,3,3, 3,3,3,3,3, 3,3,3,3,3,

		0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0,
		0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0,
		0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0,
		0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0,
		0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0,
	},{ /* VTILE */
		0,0,0,0,0, 3,3,3,3,3, 3,3,3,3,3, 0,0,0,0,0,
		0,0,0,0,0, 3,3,3,3,3, 3,3,3,3,3, 0,0,0,0,0,
		0,0,0,0,0, 3,3,3,3,3, 3,3,3,3,3, 0,0,0,0,0,
		0,0,0,0,0, 3,3,3,0,0, 0,0,3,3,3, 0,0,0,0,0,
		0,0,0,0,0, 3,3,3,0,0, 0,0,3,3,3, 0,0,0,0,0,

		0,0,0,0,0, 3,3,3,0,0, 0,0,3,3,3, 0,0,0,0,0,
		0,0,0,0,0, 3,3,3,0,0, 0,0,3,3,3, 0,0,0,0,0,
		0,0,0,0,0, 3,3,3,0,0, 0,0,3,3,3, 0,0,0,0,0,
		0,0,0,0,0, 3,3,3,0,0, 0,0,3,3,3, 0,0,0,0,0,
		0,0,0,0,0, 3,3,3,0,0, 0,0,3,3,3, 0,0,0,0,0,

		0,0,0,0,0, 3,3,3,0,0, 0,0,3,3,3, 0,0,0,0,0,
		0,0,0,0,0, 3,3,3,0,0, 0,0,3,3,3, 0,0,0,0,0,
		0,0,0,0,0, 3,3,3,0,0, 0,0,3,3,3, 0,0,0,0,0,
		0,0,0,0,0, 3,3,3,0,0, 0,0,3,3,3, 0,0,0,0,0,
		0,0,0,0,0, 3,3,3,0,0, 0,0,3,3,3, 0,0,0,0,0,

		0,0,0,0,0, 3,3,3,0,0, 0,0,3,3,3, 0,0,0,0,0,
		0,0,0,0,0, 3,3,3,0,0, 0,0,3,3,3, 0,0,0,0,0,
		0,0,0,0,0, 3,3,3,3,3, 3,3,3,3,3, 0,0,0,0,0,
		0,0,0,0,0, 3,3,3,3,3, 3,3,3,3,3, 0,0,0,0,0,
		0,0,0,0,0, 3,3,3,3,3, 3,3,3,3,3, 0,0,0,0,0,
	},{ /* SQTILE */
		0,0,0,0,0, 3,3,3,3,3, 3,3,3,3,3, 0,0,0,0,0,
		0,0,0,0,0, 3,3,3,3,3, 3,3,3,3,3, 0,0,0,0,0,
		0,0,0,0,3, 3,3,3,3,3, 3,3,3,3,3, 3,0,0,0,0,
		0,0,0,0,3, 3,3,3,3,3, 3,3,3,3,3, 3,0,0,0,0,
		0,0,3,3,3, 3,3,3,3,3, 3,3,3,3,3, 3,3,3,0,0,

		3,3,3,3,3, 3,3,3,3,3, 3,3,3,3,3, 3,3,3,3,3,
		3,3,3,3,3, 3,3,3,3,3, 3,3,3,3,3, 3,3,3,3,3,
		3,3,3,3,3, 3,3,3,3,3, 3,3,3,3,3, 3,3,3,3,3,
		3,3,3,3,3, 3,3,3,3,3, 3,3,3,3,3, 3,3,3,3,3,
		3,3,3,3,3, 3,3,3,3,3, 3,3,3,3,3, 3,3,3,3,3,

		3,3,3,3,3, 3,3,3,3,3, 3,3,3,3,3, 3,3,3,3,3,
		3,3,3,3,3, 3,3,3,3,3, 3,3,3,3,3, 3,3,3,3,3,
		3,3,3,3,3, 3,3,3,3,3, 3,3,3,3,3, 3,3,3,3,3,
		3,3,3,3,3, 3,3,3,3,3, 3,3,3,3,3, 3,3,3,3,3,
		3,3,3,3,3, 3,3,3,3,3, 3,3,3,3,3, 3,3,3,3,3,

		0,0,3,3,3, 3,3,3,3,3, 3,3,3,3,3, 3,3,3,0,0,
		0,0,0,0,3, 3,3,3,3,3, 3,3,3,3,3, 3,0,0,0,0,
		0,0,0,0,3, 3,3,3,3,3, 3,3,3,3,3, 3,0,0,0,0,
		0,0,0,0,0, 3,3,3,3,3, 3,3,3,3,3, 0,0,0,0,0,
		0,0,0,0,0, 3,3,3,3,3, 3,3,3,3,3, 0,0,0,0,0,
	},{ /* HEROTILE */
		0,0,0,0,0, 0,0,0,5,5, 5,5,0,0,0, 0,0,0,0,0,
		0,0,0,0,0, 0,0,0,5,5, 5,5,0,0,0, 0,0,0,0,0,
		0,0,0,0,0, 0,0,5,5,5, 5,5,5,0,0, 0,0,0,0,0,
		0,0,0,0,0, 0,5,5,5,5, 5,5,5,5,0, 0,0,0,0,0,
		0,0,0,0,0, 5,5,5,5,5, 5,5,5,5,5, 0,0,0,0,0,

		0,0,0,0,5, 5,5,5,5,5, 5,5,5,5,5, 5,0,0,0,0,
		0,0,0,5,5, 1,1,5,5,5, 5,1,1,5,5, 5,5,0,0,0,
		0,0,0,5,5, 1,1,1,5,5, 5,1,1,1,5, 5,5,0,0,0,
		0,0,0,5,5, 5,5,5,5,5, 5,5,5,5,5, 5,5,0,0,0,
		0,0,0,5,5, 5,5,5,5,5, 5,5,5,5,5, 5,5,0,0,0,

		0,0,0,5,5, 5,5,5,5,5, 5,5,5,5,5, 5,5,0,0,0,
		0,0,0,5,5, 5,5,5,5,5, 5,5,5,5,5, 5,5,0,0,0,
		0,0,0,5,5, 5,5,5,5,5, 5,5,5,5,5, 5,5,0,0,0,
		0,0,0,5,5, 1,1,5,5,5, 5,5,5,1,1, 5,5,0,0,0,
		0,0,0,0,5, 5,1,1,1,1, 1,1,1,1,5, 5,0,0,0,0,

		0,0,0,0,0, 5,5,1,1,1, 1,1,1,5,5, 0,0,0,0,0,
		0,0,0,0,0, 0,5,5,5,5, 5,5,5,5,0, 0,0,0,0,0,
		0,0,0,0,0, 0,0,5,5,5, 5,5,5,0,0, 0,0,0,0,0,
		0,0,0,0,0, 0,0,0,5,5, 5,5,0,0,0, 0,0,0,0,0,
		0,0,0,0,0, 0,0,0,5,5, 5,5,0,0,0, 0,0,0,0,0,
	},{ /* BADGTILE */
		0,0,0,0,0, 0,0,0,4,4, 4,4,0,0,0, 0,0,0,0,0,
		0,0,0,0,0, 0,0,0,4,4, 4,4,0,0,0, 0,0,0,0,0,
		0,0,0,0,0, 0,0,4,4,4, 4,4,4,0,0, 0,0,0,0,0,
		0,0,0,0,0, 0,4,4,4,4, 4,4,4,4,0, 0,0,0,0,0,
		0,0,0,0,0, 4,4,4,4,4, 4,4,4,4,4, 0,0,0,0,0,

		0,0,0,0,4, 4,4,4,4,4, 4,4,4,4,4, 4,0,0,0,0,
		0,0,0,4,4, 7,7,4,4,4, 4,7,7,4,4, 4,4,0,0,0,
		0,0,0,4,4, 7,7,7,4,4, 4,7,7,7,4, 4,4,0,0,0,
		0,0,0,4,4, 4,4,4,4,4, 4,4,4,4,4, 4,4,0,0,0,
		0,0,0,4,4, 4,4,4,4,4, 4,4,4,4,4, 4,4,0,0,0,

		0,0,0,4,4, 4,4,4,4,4, 4,4,4,4,4, 4,4,0,0,0,
		0,0,0,4,4, 4,4,4,4,4, 4,4,4,4,4, 4,4,0,0,0,
		0,0,0,4,4, 4,4,4,4,4, 4,4,4,4,4, 4,4,0,0,0,
		0,0,0,4,4, 7,7,4,4,4, 4,4,4,7,7, 4,4,0,0,0,
		0,0,0,0,4, 4,7,7,7,7, 7,7,7,7,4, 4,0,0,0,0,

		0,0,0,0,0, 4,4,7,7,7, 7,7,7,4,4, 0,0,0,0,0,
		0,0,0,0,0, 0,4,4,4,4, 4,4,4,4,0, 0,0,0,0,0,
		0,0,0,0,0, 0,0,4,4,4, 4,4,4,0,0, 0,0,0,0,0,
		0,0,0,0,0, 0,0,0,4,4, 4,4,0,0,0, 0,0,0,0,0,
		0,0,0,0,0, 0,0,0,4,4, 4,4,0,0,0, 0,0,0,0,0,
	},{ /* ENTERANCE */
		0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0,
		0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0,
		0,0,0,0,0, 0,0,6,6,6, 6,6,6,0,0, 0,0,0,0,0,
		0,0,0,0,0, 0,6,6,6,6, 6,6,6,6,0, 0,0,0,0,0,
		0,0,0,0,0, 6,6,6,6,6, 6,6,6,6,6, 0,0,0,0,0,

		0,0,0,0,6, 6,6,6,6,6, 6,6,6,6,6, 6,0,0,0,0,
		0,0,0,6,6, 6,6,6,6,6, 6,6,6,6,6, 6,6,0,0,0,
		0,0,6,6,6, 6,6,6,6,6, 6,6,6,6,6, 6,6,6,0,0,
		0,0,6,6,6, 6,6,6,6,6, 6,6,6,6,6, 6,6,6,0,0,
		0,0,6,6,6, 6,6,6,6,6, 6,6,6,6,6, 6,6,6,0,0,

		0,0,6,6,6, 6,6,6,6,6, 6,6,6,6,6, 6,6,6,0,0,
		0,0,6,6,6, 6,6,6,6,6, 6,6,6,6,6, 6,6,6,0,0,
		0,0,6,6,6, 6,6,6,6,6, 6,6,6,6,6, 6,6,6,0,0,
		0,0,0,6,6, 6,6,6,6,6, 6,6,6,6,6, 6,6,0,0,0,
		0,0,0,0,6, 6,6,6,6,6, 6,6,6,6,6, 6,0,0,0,0,

		0,0,0,0,0, 6,6,6,6,6, 6,6,6,6,6, 0,0,0,0,0,
		0,0,0,0,0, 0,6,6,6,6, 6,6,6,6,0, 0,0,0,0,0,
		0,0,0,0,0, 0,0,6,6,6, 6,6,6,0,0, 0,0,0,0,0,
		0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0,
		0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0,
	},{ /* EXITDOOR */
		0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0,
		0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0,
		0,0,0,0,0, 0,0,6,6,6, 6,6,6,0,0, 0,0,0,0,0,
		0,0,0,0,0, 0,6,6,6,6, 6,6,6,6,0, 0,0,0,0,0,
		0,0,0,0,0, 6,6,6,6,6, 6,6,6,6,6, 0,0,0,0,0,

		0,0,0,0,6, 6,6,6,6,6, 6,6,6,6,6, 6,0,0,0,0,
		0,0,0,6,6, 6,6,6,6,6, 6,1,1,6,6, 6,6,0,0,0,
		0,0,6,6,6, 6,6,6,6,6, 6,1,1,1,6, 6,6,6,0,0,
		0,0,6,6,6, 6,6,6,6,6, 6,6,6,6,6, 6,6,6,0,0,
		0,0,6,6,6, 6,6,6,6,6, 6,6,6,6,6, 6,6,6,0,0,

		0,0,6,6,6, 6,6,6,6,6, 6,6,6,6,6, 6,6,6,0,0,
		0,0,6,6,6, 6,6,6,6,6, 6,6,6,6,6, 6,6,6,0,0,
		0,0,6,6,6, 6,6,6,6,6, 6,6,6,6,6, 6,6,6,0,0,
		0,0,6,6,6, 6,6,6,6,6, 6,6,6,6,6, 6,6,6,0,0,
		0,0,6,6,6, 6,6,6,6,6, 6,6,6,6,6, 6,6,6,0,0,

		0,0,6,6,6, 6,6,6,6,6, 6,6,6,6,6, 6,6,6,0,0,
		0,0,6,6,6, 6,6,6,6,6, 6,6,6,6,6, 6,6,6,0,0,
		0,0,6,6,6, 6,6,6,6,6, 6,6,6,6,6, 6,6,6,0,0,
		0,0,6,6,6, 6,6,6,6,6, 6,6,6,6,6, 6,6,6,0,0,
		0,0,6,6,6, 6,6,6,6,6, 6,6,6,6,6, 6,6,6,0,0,
	} };

	final int BACK=0;
	final int HORI=1;
	final int VERT=2;
	final int SQUA=3;
	final int HERO=4;
	final int BADG=5;
	final int ENTE=6;
	final int DOOR=7;

	final String maze0[]={
		"+------------------------------+",
		"|i                   +    +    |",
		"|                   +      +   |",
		"|----+   +    --+--+        +--|",
		"|ll   llll l   l  ll  l  l  lll|",
		"|l    l    ll ll l  l l  l l   |",
		"|l    lll  l l l l  l ll l  ll |",
		"|l    l    l   l l  l l ll    l|",
		"+l    l    l   l l  l l  l    l|",
		"|llll llll l   l  ll  l  l lll |",
		"| ---+        --+--            |",
		"|                         o    |",
		"|+       +-----+--------+------|",
		"| +     +      |++++++++|      |",
		"|  +---+       |++++++++|      |",
		"+------------------------------+",
	};
	final String maze1[]={
		"+------------------------------+",
		"|i                   +    +    |",
		"|                   +      +   |",
		"|----+   +    --+--+        +--|",
		"|     +  |      |              |",
		"|      + |      |        o     |",
		"| __     |      |    ----------|",
		"|    +---+--    |              |",
		"+--  |          |           ---|",
		"|    |          |              |",
		"| ---+        --+--            |",
		"|                              |",
		"|+       +-----+--------+------|",
		"| +     +      |        |      |",
		"|  +---+       |        |      |",
		"+------------------------------+",
	};
	final String maze2[]={
		"+------------------------------+",
		"|                              |",
		"| o                            |",
		"|----+   +        ++        +--|",
		"|     +  |      +-+            |",
		"|      + |      |              |",
		"| __     |      +--------------|",
		"|    +---+--    |           i  |",
		"+--  |          |           ---|",
		"|    |          |              |",
		"| ---+        --+--        -   |",
		"|                              |",
		"|+       +-----+--+     +------|",
		"| +     +      |   +    |      |",
		"|  +   +       |    +   |      |",
		"+---   ------------------------+",
	};

	char maze[] = new char[TILESACROSS*TILESDOWN];

	int enterX,enterY,doorX,doorY;
	int selected=-1;

	void resetmaze(String [] template)
	{
		int i,j;

		active=0;
		next=0;
		rescued=0;

		for(j=0;j<TILESDOWN;j++) {
			for(i=0;i<TILESACROSS;i++) {
				switch(template[j].charAt(i)) {
				case '|': maze[j*TILESACROSS+i]=VERT; break;
				case '-': maze[j*TILESACROSS+i]=HORI; break;
				case '+': maze[j*TILESACROSS+i]=SQUA; break;
				case 'l': maze[j*TILESACROSS+i]=HERO; break;
				case 'i': maze[j*TILESACROSS+i]=ENTE; enterX=i; enterY=j; break;
				case 'o': maze[j*TILESACROSS+i]=DOOR; doorX=i; doorY=j; break;
				default:  maze[j*TILESACROSS+i]=BACK; break;
				}
			}
		}
	}

	void rendertile(Graphics g,int col,int row,int id)
	{
		int i;
		int x,y;

		x=col*TILEWIDTH;
		y=row*TILEHEIGHT;

		//g.setColor(new Color(palette[id]));
		//g.fillRect(x,y,TILEWIDTH,TILEHEIGHT);
		g.drawImage(tileImage[id],
		  x,y,this);

		//System.out.println("Tile "+col+","+row+": "+id);
	}

	void renderinfo(Graphics g)
	{
		g.setColor(Color.white);
		g.fillRect(0,TILEHEIGHT*TILESDOWN,TILEWIDTH*TILESACROSS,TILEHEIGHT*2);
		// Now 4 lines of status text
		g.setColor(Color.black);
		g.drawString("Lemons Status - "+next+" of "+MAXLEMON+". "+rescued+" rescued. "+active+" left.",
			5,TILEHEIGHT*TILESDOWN+TILEHEIGHT/2);
		if(selected!=-1 && lemonType[selected]!=S_INACTIVE) {
			String s="Selected lemon "+selected+": ";
			switch(lemonType[selected]) {
			case S_WALK: s+="Walk"; break;
			case S_CLIMB: s+="Climb"; break;
			case S_PARACHUTE: s+="Parachute"; break;
			case S_PARACLIMB: s+="Paraclimb"; break;
			case S_BUILD: s+="Build"; break;
			case S_EXPLODE: s+="Explode"; break;
			case S_STOP: s+="Stop"; break;
			}
			s+=" @"+lemonX[selected]+","+lemonY[selected];
			g.drawString(s,5,TILEHEIGHT*TILESDOWN+TILEHEIGHT);
		} else {
			g.drawString("No lemons selected",5,TILEHEIGHT*TILESDOWN+TILEHEIGHT);
		}
		g.drawString("b - Build | c - Climb | e - Explode",5,TILEHEIGHT*TILESDOWN+TILEHEIGHT*3/2);
		g.drawString("p - Parachute | s - Stop",5,TILEHEIGHT*TILESDOWN+TILEHEIGHT*2);
		
	}

	void rendermaze(Graphics g)
	{
		int i,j,k;
		int id;
		for(j=0;j<TILESDOWN;j++) {
			for(i=0;i<TILESACROSS;i++) {
				id=maze[j*TILESACROSS+i];
				for(k=0;k<next;k++) {
					if(i==lemonX[k] && j==lemonY[k] && lemonType[k]!=S_INACTIVE) {
						id=(k==selected)?BADG:HERO;
						if(k==selected) break;
					}
				}
				rendertile(g,i,j,id);
			}
		}
	}

	final int S_INACTIVE=0;
	final int S_WALK=1;
	final int S_PARACHUTE=2;
	final int S_CLIMB=3;
	final int S_PARACLIMB=4;
	final int S_BUILD=5;
	final int S_STOP=6;
	final int S_EXPLODE=7;

	int lemonType[]=new int[MAXLEMON];
	int lemonX[]=new int[MAXLEMON];
	int lemonY[]=new int[MAXLEMON];
	int lemonDir[]=new int[MAXLEMON];
	int lemonFallen[]=new int[MAXLEMON];
	int lemonExplode[]=new int[MAXLEMON];

	int next=0;
	int active=0;
	int rescued=0;

	boolean invalid[]=new boolean[TILESACROSS*TILESDOWN];

	void updateState()
	{
		int id,x,y,row,k;
		Graphics g=getGraphics();

		for(y=0;y<TILESDOWN;y++) {
			row=y*TILESACROSS;
			for(x=0;x<TILESACROSS;x++) {
				if(invalid[row+x]) {
					id=maze[y*TILESACROSS+x];
					for(k=0;k<next;k++) {
						if(x==lemonX[k] && y==lemonY[k] && lemonType[k]!=S_INACTIVE) {
							id=(k==selected)?BADG:HERO;
							if(k==selected) break;
						}
					}
					rendertile(g,x,y,id);
					//repaint(x*TILEWIDTH,y*TILEHEIGHT,TILEWIDTH,TILEHEIGHT);
					invalid[row+x]=false;
				}
			}
		}
		repaint(0,TILEHEIGHT*TILESDOWN,TILEWIDTH*TILESACROSS,TILEHEIGHT*2);
	}

	void nextState()
	{
		int id,oldX,oldY;

		for(id=0;id<next;id++) {
			oldX=lemonX[id];
			oldY=lemonY[id];
			nextState(id);
			if(oldX!=lemonX[id] || oldY!=lemonY[id]) {
				invalid[oldY*TILESACROSS+oldX]=true;
				invalid[lemonY[id]*TILESACROSS+lemonX[id]]=true;
			}
		}
	}

	void nextState(int id)
	{
		int r=(int)(Math.random()*3.99);
		int dist,x,y,dir;
		int min,max;

		x=lemonX[id];
		y=lemonY[id];
		dir=lemonDir[id];

		if(lemonType[id]==S_INACTIVE) return;

		/* Apply gravity */
		//System.out.print("lemon id "+id+": ");
		if(y<TILESDOWN-1) {
			if((lemonType[id]==S_CLIMB || lemonType[id]==S_PARACLIMB) && maze[(y+1)*TILESACROSS+x+dir]!=BACK) {
				//System.out.println("..C: Grip baby!");
				lemonFallen[id]=0;
			} else {
				switch(maze[(y+1)*TILESACROSS+x]) {
				case BACK:
				case ENTE:
					//System.out.println("..dropping");
					lemonY[id]++;
					lemonFallen[id]++;
					return;
				case DOOR:
					//System.out.println("..exiting");
					active--;
					rescued++;
					lemonType[id]=S_INACTIVE;
					invalid[y*TILESACROSS+x]=true;
					return;
				default:
					if(lemonFallen[id]>=4 && lemonType[id]!=S_PARACHUTE && lemonType[id]!=S_PARACLIMB) {
						/* Splat! */
						//System.out.println("..splat");
						active--;
						lemonType[id]=S_INACTIVE;
						invalid[y*TILESACROSS+x]=true;
						return;
					}
					lemonFallen[id]=0;
				}
			}
		} else {
			/* Death to the opposition! */
			active--;
			lemonType[id]=S_INACTIVE;
			invalid[y*TILESACROSS+x]=true;
			//System.out.println("..death to the opposition!");
			return;
		}

		if(dir==0) {
			lemonDir[id]=1;
			return;
		}
	
		switch(lemonType[id]) {
		case S_EXPLODE:
			lemonExplode[id]++;

			if(lemonExplode[id]>10) {
				lemonType[id]=S_INACTIVE;
				active--;
				invalid[y*TILESACROSS+x]=true;
				int dx,dy;
				//System.out.println("..E: kaboom!");
				for(dy=y-1;dy<=y+1;dy++) {
				for(dx=x-1;dx<=x+1;dx++) {
					maze[dy*TILESACROSS+dx]=BACK;
					invalid[dy*TILESACROSS+dx]=true;
				} }
				
				return;
			}
			/* fallthorugh */
		case S_STOP:
			//System.out.println("..S: still");
			break;
		case S_WALK:
		case S_PARACHUTE:
			switch(maze[y*TILESACROSS+x+dir]) {
			case BACK:
			case ENTE:
				lemonX[id]+=dir;
				//System.out.println("..W: walk");
				break;
			case DOOR:
				active--;
				rescued++;
				invalid[y*TILESACROSS+x]=true;
				lemonType[id]=S_INACTIVE;
				//System.out.println("..W: exit");
				break;
			default:
				switch(maze[(y-1)*TILESACROSS+x+dir]) {
				case BACK:
				case ENTE:
					lemonX[id]+=dir;
					lemonY[id]--;
					//System.out.println("..W: walk");
					return;
				case DOOR:
					active--;
					rescued++;
					invalid[y*TILESACROSS+x]=true;
					lemonType[id]=S_INACTIVE;
					//System.out.println("..W: exit");
					return;
				}
				//System.out.println("..W: @"+x+","+y+" looking "+dir+"; about face"+lemonDir[id]+"!");
				lemonDir[id]=-lemonDir[id];
				//System.out.println("..W: about face"+lemonDir[id]+"!");
				break;
			}
			return;
		case S_CLIMB:
		case S_PARACLIMB:
			switch(maze[y*TILESACROSS+x+dir]) {
			case BACK:
			case ENTE:
				lemonX[id]+=dir;
				//System.out.println("..C: walk");
				return;
			case DOOR:
				active--;
				rescued++;
				lemonType[id]=S_INACTIVE;
				invalid[y*TILESACROSS+x]=true;
				//System.out.println("..C: exit");
				return;
			default:
				switch(maze[(y-1)*TILESACROSS+x+dir]) {
				case BACK:
				case ENTE:
					lemonX[id]+=dir;
					lemonY[id]--;
					//System.out.println("..W: walk");
					break;
				case DOOR:
					active--;
					rescued++;
					lemonType[id]=S_INACTIVE;
					invalid[y*TILESACROSS+x]=true;
					//System.out.println("..W: exit");
					break;
				}
				/* if in doubt, climb it */
				if(y==1) {
					lemonDir[id]=-dir;
					//System.out.println("..C: About face!");
					return;
				}
				switch(maze[(y-1)*TILESACROSS+x]) {
				case BACK:
				case ENTE:
					lemonY[id]--;
					//System.out.println("..C: up we go");
					break;
				case DOOR:
					active--;
					rescued++;
					//System.out.println("..C: exit");
					invalid[y*TILESACROSS+x]=true;
					lemonType[id]=S_INACTIVE;
					break;
				default:
					/* if in doubt fall */
					lemonDir[id]=-dir;
					//System.out.println("..C: about face!");
					break;
				}
				return;
			}
			// break;
		case S_BUILD:
			switch(maze[y*TILESACROSS+x+dir]) {
			case BACK:
			case ENTE:
				if(y>0) {
					maze[y*TILESACROSS+x+dir]=SQUA;
					invalid[y*TILESACROSS+x+dir]=true;
					switch(maze[(y-1)*TILESACROSS+x+dir]) {
					case BACK:
					case ENTE:
						break;
					case DOOR:
						active--;
						rescued++;
						lemonType[id]=S_INACTIVE;
						invalid[y*TILESACROSS+x]=true;
						//System.out.println("..B: exit");
						return;
					default:
						lemonType[id]=S_WALK;
						//System.out.println("..B: to walker");
						return;
					}
					lemonX[id]+=dir;
					lemonY[id]--;
					//System.out.println("..B: walk");
				} else {
					lemonType[id]=S_WALK;
				}
				return;
			case DOOR:
				active--;
				rescued++;
				lemonType[id]=S_INACTIVE;
				invalid[y*TILESACROSS+x]=true;
				//System.out.println("..B: exit");
				return;
			default:
				switch(maze[(y-1)*TILESACROSS+x+dir]) {
				case BACK:
				case ENTE:
					lemonX[id]+=dir;
					lemonY[id]--;
					//System.out.println("..W: walk");
					return;
				case DOOR:
					active--;
					rescued++;
					invalid[y*TILESACROSS+x]=true;
					lemonType[id]=S_INACTIVE;
					//System.out.println("..W: exit");
					return;
				}
				dir=-dir;
				lemonDir[id]=dir;
				//System.out.println("..B: about face!");
				return;
			}
			// break;
		}
	}

	final int palette[]={ 0,0xff,0xff00,0xffff,0xff0000,0xffff00,0xff00ff,0xffffff };
	final int PALETTECOUNT=8;

	boolean appletActive;
	boolean endRun;
	boolean titleScreen=true;
	int tileData[]=new int[TILEWIDTH*TILEHEIGHT*8];

	public void init()
	{
		int i,j;
		resetmaze(maze0);
		titleScreen=true;

		for(i=0;i<TILECOUNT;i++) {		
			for(j=0;j<TILEWIDTH*TILEHEIGHT;j++) {
				tileData[TILEWIDTH*TILEHEIGHT*i+j]=
				  palette[tile[i][j]]|0xff000000;
			}
			tileImage[i]=createImage(new MemoryImageSource(
			  TILEWIDTH,TILEHEIGHT,tileData,
			  TILEWIDTH*TILEHEIGHT*i,TILEWIDTH));
		}
		endRun=false;
		appletActive=false;
	}

	public void start()
	{
		Graphics g=getGraphics();

		appletActive=true;

		rendermaze(g);
	}

	public void stop()
	{
		appletActive=false;
	}

	public void destroy()
	{
		appletActive=false;
		endRun=true;
	}

	boolean mazeWait=false;

	public void run() 
	{
		int dropTimer=1;

		while(!endRun) {
			// So sleep a little
			try {
				Thread.sleep(200);
			} catch(InterruptedException e) {
				break;
			}
			if(appletActive==false) continue;

			if(next<MAXLEMON) {
				if(dropTimer==0) {
					// A new lemon is born.
					lemonX[next]=enterX;
					lemonY[next]=enterY;
					lemonType[next]=S_WALK;
					lemonDir[next]=1;
					lemonFallen[next]=0;
					lemonExplode[next]=0;
					next++;
					active++;
					//System.out.println("Added lemon "+next+" at "+enterX+","+enterY);
					dropTimer=5;
				} else {
					dropTimer--;
				}
			}

			// Calculate the next round
			nextState();

			// Update display
			//System.out.println("Rendering."+active+"/"+rescued+"/"+next+"/"+MAXLEMON);
			updateState();

			// With victory prepare next level.
			if(next==MAXLEMON && active==0) {
				mazeWait=true;
				break;
			}
		}
	}

	public void paint(Graphics g)
	{
		rendermaze(g);
		renderinfo(g);
	}

	public boolean keyUp(Event e,int key)
	{
		System.out.println("Handling Key: "+key);
		if(selected==-1 || lemonType[selected]==S_INACTIVE) {
			return false;
		}
		//System.out.println("Key: "+key);
		switch(key) {
		case 'c':
			System.out.println("climber!");
			if(lemonType[selected]==S_PARACHUTE) {
				lemonType[selected]=S_PARACLIMB;
			} else {
				lemonType[selected]=S_CLIMB;
			}
			break;
		case 'p':
			System.out.println("parachute!");
			if(lemonType[selected]==S_CLIMB) {
				lemonType[selected]=S_PARACLIMB;
			} else {
				lemonType[selected]=S_PARACHUTE;
			}
			break;
		case 'b':
			System.out.println("build!");
			lemonType[selected]=S_BUILD;
			break;
		case 's':
			System.out.println("stop!");
			lemonType[selected]=S_STOP;
			break;
		case 'e':
			System.out.println("explode!");
			lemonType[selected]=S_EXPLODE;
			break;
		}	
		return true;
	}

	public boolean mouseUp(Event e, int x, int y)
	{
		int id;
		int cx=x/TILEWIDTH,cy=y/TILEHEIGHT;

		if(titleScreen) {		
			resetmaze(maze1);
			repaint();
			new Thread(this).start();
			titleScreen=false;
		}
		if(mazeWait) {		
			resetmaze(maze2);
			repaint();
			new Thread(this).start();
			mazeWait=false;
		}
		selected=-1;
		for(id=0;id<next;id++) {
			if(lemonType[id]!=S_INACTIVE && lemonX[id]==cx && lemonY[id]==cy) {
				selected=id;
				invalid[lemonY[id]*TILESACROSS+lemonX[id]]=true;
				return true;
			}
		}
		/* Now look for the nearest lemon (any within one square would do) */
		for(id=0;id<next;id++) {
			if(lemonType[id]!=S_INACTIVE && (lemonX[id]<cx?cx-lemonX[id]:lemonX[id]-cx)<2 && (lemonY[id]<cy?cy-lemonY[id]:lemonY[id]-cy)<2) {
				selected=id;
				invalid[lemonY[id]*TILESACROSS+lemonX[id]]=true;
				return true;
			}
		}

		return false;
	}
}
