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()
    {
        /*
        try
        {
            Frame F = (Frame)getParent();
            F.setCursor(Frame.CROSSHAIR_CURSOR);
        }
        catch (Error 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 (100);} 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;
            start();
        }
        return true;
    }
}