import java.applet.Applet;
import java.awt.Color;
import java.awt.Cursor;
import java.util.Date;
import java.awt.Event;
import java.awt.Frame;
import java.awt.Image;
import java.awt.Graphics;
import java.lang.Math;
import java.awt.MediaTracker;

public class alphabet extends Applet implements Runnable
{
	Image Img, Alphabet, LoveGame;
	String[] OrgWords = {"floorg+ames","morg+ue","org+anic","org+y","org+anisation",
		"forg+ery","metamorg+phosis","org+ator","tomorg+ow","psycholorg+y",
		"postmorg+dernism","colorg+","demorg+cracy","org+ology","org+ism","org+ogenesis",
		"org+one","org+istics","neoorg+ism","horg+oscope","morg+tor","morg+inal",
		"demorg+strations","lorg+nette","transforg+mation","org+asmic","epistemolorg+y",
		"metaorg+ics","worg+ames","cyborg+","inforg+mation","sorg+ciety","sorg+ciology",
		"psychorg+sis","gorg+eous","gorg+onzola","gorg+oils","gorg+onise","morpholorg+y",
		"patholorg+ic","org+atorium","elevatorg+","doorg+"};
	int[] Answer;
	int[][] SmallTalk = new int[7][];
	int Hits;
	int Seconds;
	long MilliSeconds;
	static Color OrgGreen = new Color (0xCBE2CD);
	

	Graphics IG;
	int CrossHairX, CrossHairY, ClipX, ClipY, Size;
	int Locked = 26, ClipNum = 0;
	int PlaceWord;
	int ClipCount = - 2;
	int[][] Info = new int[27][8];
	Thread Letter = null;
	boolean Waiting = true, NotShooting = true, NotShootingToo = false;

	public void init()
	{
		Frame F = (Frame)getParent();
		try
		{
			F.setCursor(Frame.CROSSHAIR_CURSOR);
		}
		catch (NoSuchMethodError e){}
		MediaTracker MT = new MediaTracker (this);
		Alphabet = this.getImage (this.getDocumentBase (), this.getParameter ("alphabet"));
		MT.addImage (Alphabet, 0);
		LoveGame = this.getImage (this.getDocumentBase (), this.getParameter ("lovegame"));
		MT.addImage (LoveGame, 1);
		InitiateWord();
		SmallTalk[0] = LetterCounter ("the word is");
		SmallTalk[1] = LetterCounter ("well done");
		SmallTalk[2] = LetterCounter ("you found the word");
		SmallTalk[3] = LetterCounter ("even if you");
		SmallTalk[4] = LetterCounter ("were slow");
		SmallTalk[5] = LetterCounter ("and");
		SmallTalk[6] = LetterCounter ("hit many innocent letters");
		Img = createImage (598, 284);
		try {MT.waitForAll();} catch (InterruptedException e){}
		DrawPlay();
	}

	public void InitiateWord()
	{
		Answer = LetterCounter(OrgWords[(int)(Math.random()*43)]);
		for (int i = 0; i < Answer[0]; i++)
		{
			Info[i][4] = Answer[i + 1];
		}
		for (int i = Answer[0]; i < 27; i++)
		{
			int s = (int)(Math.random() * 27);
			while (Used (Answer, s)) s = (int)(Math.random() * 27);
			Info[i][4] = s;
		}
		for (int i = 0; i < 27; i++)
		{
			Info[i][0] = (int)(Math.random() * 574) + 2;
			Info[i][1] = (int)(Math.random() * 225) + 35;
			if (i < Answer[0]) Info[i][5] = 1;
			else Info[i][5] = 0;
			Info[i][6] = 1;
		}
		ShiftLetters();
	}

	public int[] LetterCounter (String S)
	{
		int L = S.length() + 1;
		int I[] = new int[L];
		I[0] = L - 1;
		for (int j = 1; j < L; j++)
		{
			int k = Character.digit(S.charAt(j - 1), 36); 
			if (k > 9) I[j] = k - 9;
			else if (S.charAt(j - 1) == ' ') I[j] = 30;
			else I[j] = 0;
		}
		return I;
	}

	public boolean Used (int[] a, int s)
	{
		boolean b = false;
		for (int i = 1; i < a[0] + 1; i++)
		{
			if (s == a[i]) b = true;
		}
		return b;
	}

	public void ShiftLetters()
	{
		for (int i = 0; i < 27; i++)
		{
			for (int j = 2; j < 4; j++)
			{
				int k = (int)(Math.random() * 26);
				while (k == i) k = (int)(Math.random() * 26);
				Info[i][j] = k;
				if (Info[i][6] == 1) Info[i][7] = Distance(CrossHairX - 10, CrossHairX - 13,
					Info[i][0], Info[i][0]);
			}
		}
	}
	
	public int HitsLeft()
	{
		int j = 0;
		for (int i = 0; i < Answer[0]; i++)
		{
			j = j + Info[i][5];
		}
		return j;
	}

	public int WrongHitsLeft()
	{
		int j = 0;
		for (int i = Answer[0]; i < 27; i++)
		{
			j = j + Info[i][6];
		}
		return j;
	}

	public int[] Closest()
	{
		int a = 1000;
		int b = 0;
		for (int i = 0; i < 27; i++)
		{
			if ((Info[i][6] == 1) & (a > Info[i][7]))
			{
				a = Info[i][7];
				b = i;
			}
		}
		int[] T = {a,b};
		return T;
	}

	public int Distance (int x1, int y1, int x2, int y2)
	{
		return (int)Math.sqrt(Math.pow(x1 - x2, 2) + Math.pow(y1 - y2, 2));
	}

	public void NextPosition(int i)
	{
		Info[i][0] = Info[i][0] + (int)((Info[Info[i][2]][0] - Info[Info[i][3]][0])/100); 
		if (Info[i][0] < 8) Info[i][0] = 8;
		if (Info[i][0] > 570) Info[i][0] = 570;
		Info[i][1] = Info[i][1] + (int)((Info[Info[i][2]][1] - Info[Info[i][3]][1])/60); 
		if (Info[i][1] < 35) Info[i][1] = 35;
		if (Info[i][1] > 260) Info[i][1] = 260;
	}

	public void paint (Graphics g)
	{
		g.drawImage (Img, 0, 0, this);
	}

	public void update (Graphics g)
	{
		paint (g);
	}

	public void stop()
	{
		{
			if ((Letter != null) && Letter.isAlive())
			{
				Letter.stop();
				Letter = null;
			}
		}
	}
	
	public void start()
	{
		Letter = new Thread(this);
		Letter.start();
	}
			
	public void run()
	{
		while (Waiting)
			try {Letter.sleep (50);} catch (InterruptedException e){}

		try {Letter.sleep (300);} catch (InterruptedException e){}
		while (HitsLeft() > 0)
		{
			try {Letter.sleep (10);} catch (InterruptedException e){}
			if (Math.random() > 0.9) ShiftLetters();
			for (int i = 0; i < 27; i++)
			{
				if (Info[i][6] == 1)
				{
					DrawLetter (Info[i][0], Info[i][1], Info[i][4]);
					NextPosition(i);
				}
			}

			int [] C = Closest();
			if (C[0] < 10)
			{
				Info[C[1]][0] = CrossHairX - 10;
				Info[C[1]][1] = CrossHairY - 11;
			}

			if (Locked > - 1)
			{
				Info[Locked][0] = CrossHairX - 10;
				Info[Locked][1] = CrossHairY - 11;
			}

			if (ClipCount >  - 1)
			{
				if (ClipCount == 8) Info[Locked][6] = 0;
				if (ClipCount < 8) DrawClip (ClipCount, 1, ClipX, ClipY, 15);
				else DrawClip (ClipCount - 8, ClipNum, ClipX, ClipY, Size);
				ClipCount++;
				if (ClipCount == 16)
				{
					ClipCount = - 1;
					Info[Locked][5] = 0;
					NotShooting = true;
				}
			}
			DrawWord(SmallTalk[0], - 10, 10, 0);
			DrawWord(Answer, PlaceWord, 10, 0);
			DrawCrossHair();
			getGraphics().drawImage(Img, 0, 0, this);
			IG = Img.getGraphics();
			IG.setColor (Color.black);
			IG.fillRect (0, 0, 598, 284);
			IG.dispose();
			NotShootingToo = true;
		}
		boolean Slow = (MilliSeconds - new Date().getTime() < 0);

		RoseMovie();
		DrawWord(SmallTalk[1], 40, 50, 150);
		DrawWord(SmallTalk[2], 40, 100, 150);

		if (Slow)
		{
			DrawWord(SmallTalk[3], 40, 150, 150);
			DrawWord(SmallTalk[4], 270, 150, 150);
			if (WrongHitsLeft() < 25 - Answer[0])
			{
				DrawWord(SmallTalk[5], 470, 150, 150);
				DrawWord(SmallTalk[6], 40, 200, 150);
			}
		}
		else if (WrongHitsLeft() < 25 - Answer[0])
		{
			DrawWord(SmallTalk[3], 40, 150, 150);
			DrawWord(SmallTalk[6], 40, 200, 150);
		}
		try {Letter.sleep (2500);} catch (InterruptedException e){}
		DrawPlay();
		getGraphics().drawImage(Img, 0, 0, this);
		InitiateWord();
		ClipCount = - 2;
	}

	public void RoseMovie()
	{
		for (int i = 0; i < 200; i++)
		{
			for (int k = 0; k < 3; k++)
			{
				DrawClip ((int)(Math.random() * 8),(int)(Math.random() * 2) + 2, (int)(Math.random() * 600),
					(int)(Math.random() * 250), 15 * (int)(Math.random() * 2) + 15);
			}
			getGraphics().drawImage(Img, 0, 0, this);
		}
	}

	public void DrawPlay()
	{
		IG = Img.getGraphics();
		IG.setColor (Color.black);
		IG.fillRect (0, 0, 598, 284);
		IG.clipRect (250, 145, 100, 100);
		IG.drawImage (LoveGame, - 710, 145, this);
		IG.dispose();
	}

	public void DrawTask()
	{
		IG = Img.getGraphics();
		IG.setColor (Color.black);
		IG.fillRect (0, 0, 598, 284);
		IG.dispose();
		MilliSeconds = 6000 * Answer[0] + new Date().getTime();
		PlaceWord = 570 - 20 * Answer[0];
		DrawWord(SmallTalk[0], - 10, 10, 150);
		DrawWord(Answer, PlaceWord, 10, 300);
	}

	public void DrawLetter (int x, int y, int n)
	{
		IG = Img.getGraphics();
		IG.clipRect (x, y - 5, 20, 33);
		IG.drawImage (Alphabet, x - 20 * n, y, this);
		if (n == 0)
		{
			IG.drawImage (Alphabet, x - 20 * n, y + 5, this);
			IG.drawImage (Alphabet, x - 20 * n, y - 5, this);
		}
		IG.dispose();
	}

	public void DrawWord (int[] a, int x, int y, int d)
	{
		int PlaceX = x;
		for (int i = 1; i < a[0] + 1; i++)
		{
			if (a[i] == 0) PlaceX = PlaceX + 13;
			else PlaceX = PlaceX + 20;
			if (a[i] < 30) DrawLetter (PlaceX, y, a[i]);
			try {Letter.sleep (d);} catch (InterruptedException e){}
			if (d > 0) getGraphics().drawImage(Img, 0, 0, this);
		}
	}

	public void DrawClip (int i, int j, int x, int y, int s)
	{
		IG = Img.getGraphics();
		IG.clipRect (x - s, y - s, s * 2, s * 2);
		IG.drawImage (LoveGame, x - s - s * 2 * (8 * j + i), y - s, 70 * s, 2 * s, this);		
		IG.dispose();
	}

	public void DrawCrossHair ()
	{
		IG = Img.getGraphics();
		IG.setColor (OrgGreen);
		IG.drawLine (CrossHairX, 35, CrossHairX, CrossHairY - 15);
		IG.drawLine (CrossHairX, CrossHairY + 15, CrossHairX, 280);
		IG.drawLine (CrossHairX - 15, CrossHairY - 2, CrossHairX - 15, CrossHairY + 2);
		IG.drawLine (CrossHairX + 15, CrossHairY - 2, CrossHairX + 15, CrossHairY + 2);
		IG.drawLine (4, CrossHairY, CrossHairX - 15, CrossHairY);
		IG.drawLine (CrossHairX + 15, CrossHairY, CrossHairX + 38, CrossHairY);
		IG.drawLine (CrossHairX + 160, CrossHairY, 598, CrossHairY);
		IG.drawString("L: " + HitsLeft() + "  M: " + (27 - WrongHitsLeft() - Answer[0]) + 
			"  T: " + (MilliSeconds - new Date().getTime()), CrossHairX + 60, CrossHairY + 5);
		IG.drawLine (CrossHairX - 2, CrossHairY - 15, CrossHairX + 2, CrossHairY - 15);
		IG.drawLine (CrossHairX - 2, CrossHairY + 15, CrossHairX + 2, CrossHairY + 15);
		IG.dispose();
	}

	public boolean mouseMove (Event e, int x, int y)
	{
		if ((y > 45) & (y < 275))
		{
			CrossHairX = x;
			CrossHairY = y;
		}
		return true;
	}

	public boolean mouseDown (Event e, int x, int y)
	{
		if ((ClipCount == - 1)&&(NotShooting)&&(NotShootingToo))
		{
			NotShooting = false;
			ClipX = x;
			ClipY = y;
			ClipCount = 0;
			int [] C = Closest();
			if (C[0] < 7)
			{
				Locked = C[1];
				if (Info[C[1]][5] == 1)
				{
					ClipNum = 2;
					Size = 15;
				}
				else
				{
					ClipNum = 0;
					Size = 30;
				}
			}
			else
			{
				ClipNum = 0;
				Size = 15;
			}
		}
		if ((ClipCount == - 2) & ((x - 280) * (x - 280) + (y - 135) * (y - 135) < 2500))
		{
			DrawTask();
			ClipCount = - 1;
			Waiting = false;
		}
		return true;
	}
}