/*******************/
/*Set © t.heyn 2000*/
/*******************/

import java.awt.*;
import java.awt.event.*;
import java.applet.*;

public class SetApplet extends Applet implements ActionListener
	{
   final int BREITE=100,HOEHE=160,TOTAL=81,ZEIT=420,STRAFE=20;			//einige Konstanten
   int stapel,score,aktive,nr;
   long startzeit,jetztzeit;
   boolean fertig=false;
	int set[] = new int[3];
   Karte karte[] = new Karte[TOTAL];
	Karte tempKarte = new Karte();
 	AudioClip laugh, applaus, beep;
 	Image setKarte, setRahmen, setSymbole;
  	TextArea text = new TextArea("",15,12,TextArea.SCROLLBARS_NONE);
   Label uhr = new Label("",Label.CENTER);
  	String kommentar="";
  	ZeitThread zeitThread = new ZeitThread();
  	Image HintergrundBild = null;
   Graphics HintergrundGrafik = null;
   Dimension HintergrundGroesse = null;

   public void init()
   	{
		showStatus("Lade Bilder...");
		laden();
		kreiereKarten();
		showStatus("Set © t.heyn 2000");
		addMouseListener(new MyMouse());
    	setLayout(new BorderLayout());
    	Panel anzeige = new Panel();
    		anzeige.setLayout(new BorderLayout());
    		add("East",anzeige);
     	Label titel = new Label("SET Trainer",Label.CENTER);
			titel.setBackground(Color.yellow);
			titel.setFont(new Font("SansSerif",Font.BOLD,18));
			anzeige.add("North",titel);
    	anzeige.add("Center",text);
    		text.setEnabled(false);
    		schreiben();
    	Panel controls = new Panel();
    		controls.setLayout(new BorderLayout());	
    		anzeige.add("South",controls);
     	Button neu= new Button("Start");
    		neu.addActionListener(this);
    		controls.add("South",neu);
     	Button tipp= new Button("Tipp");
    		tipp.addActionListener(this);
    		controls.add("North",tipp);
			uhr.setFont(new Font("Serif",Font.BOLD,18));
			controls.add("Center",uhr);
		}

	public void paint(Graphics g)
		{
 		for (int i=0;i<TOTAL;i++)
 			{
			if (karte[i].istOffen) karte[i].paint(g);
			if (karte[i].istAktiv) g.drawImage(setRahmen,karte[i].x,karte[i].y,this); //einrahmen
			}
		}

	public void actionPerformed(ActionEvent e)
		{
		if (e.getActionCommand() =="Start") neuesSpiel();
		if (e.getActionCommand() =="Tipp" && jetztzeit>STRAFE) hatEsEinSet(true);
		}
		
	public void stop()
		{
		if (zeitThread != null) zeitThread.interrupt();
		}
		
	public final void update(Graphics g) //Flimmerfreie Grafik mit Double Buffering
		{
		Dimension dim = getSize();
		if((HintergrundBild==null) || (dim.width != HintergrundGroesse.width) || (dim.height != HintergrundGroesse.height)) 
			{
			HintergrundBild = createImage(dim.width, dim.height);
			HintergrundGroesse = dim;
			HintergrundGrafik = HintergrundBild.getGraphics();
			}
		HintergrundGrafik.clearRect(0, 0, HintergrundGroesse.width, HintergrundGroesse.height);
		paint(HintergrundGrafik);
		g.drawImage(HintergrundBild,0,0,null);
		}	
		
	private class MyMouse extends MouseAdapter
		{	
		public void mousePressed(MouseEvent e)
			{
			if (fertig) return;
			int x=e.getX();
			int y=e.getY();
 			for (int i=0;i<TOTAL;i++)
 				{
				if (karte[i].x==(int)(x/BREITE)*BREITE && karte[i].y==(int)(y/HOEHE)*HOEHE)
					{
					nr=i;
					if (! karte[i].istOffen) return;
					if (karte[i].istAktiv)	//deaktivieren
						{
						karte[i].istAktiv=false;
						if (i==set[0])
							{
							set[0]=set[1];
							set[1]=set[2];						
							set[2]=-1;
							}
						if (i==set[1])
							{
							set[1]=set[2];						
							set[2]=-1;
							}
						if (i==set[2])
							{
							set[2]=-1;
							}
						aktive--;
						}
					else							//aktivieren
						{
						aktive++;
						karte[i].istAktiv=true;
						set[aktive-1]=i;
						}
					update(getGraphics());
					schreiben();
					break;
					}
				}
			if (aktive==3) auswertung();
			}
		}
		
	private class ZeitThread extends Thread
		{
		public void run()
			{
			while (! fertig)
				{
				jetztzeit=ZEIT - (int)((System.currentTimeMillis()-startzeit)/1000);
				if (jetztzeit<0)
					{
					uhr.setText("0:00");
					schluss("Du verlierst!");
					}
				else uhr.setText(""+(int)(jetztzeit/60)+":"+((int)((jetztzeit%60)/10))+((jetztzeit%60)%10));
				//schlafen
				try
     	       	{
					sleep(1000);
					}
				catch (InterruptedException e) 
					{
					break;
					}
				}
			}
		}

	private void neuesSpiel()
		{
		score=0;
		fertig=false;
		kommentar="";
		stapel=TOTAL;
		startzeit = System.currentTimeMillis();
		jetztzeit=ZEIT;
		zeitThread = new ZeitThread();
		zeitThread.start();
		for (int i=0;i<TOTAL;i++)
 			{
			karte[i].reset();
			}
		resetSet();
		mischen();
		legen();
		schreiben();
		update(getGraphics());
		}
		
	private void schluss(String schlusstext)
		{
		kommentar=schlusstext;
		schreiben();
		fertig=true;
		if (zeitThread != null) zeitThread=null;
		if (jetztzeit<=0) laugh.play();
			else applaus.play();
		}
	
	private void auswertung()
		{
		if (istEsEinSet(set[0],set[1],set[2]))
			{
			beep.play();
			for(int i=0;i<3;i++)
				{
				karte[set[i]].istAktiv=false;
				karte[set[i]].istOffen=false;
				if (stapel>12) //neue karten vom stapel nehmen
					{
					tempKarte = karte[set[i]];
					karte[set[i]] = karte[stapel-i-1];
					karte[stapel-i-1] = tempKarte;
					karte[set[i]].istOffen=true;
					karte[set[i]].setPosition(tempKarte.x,tempKarte.y);
					}
				}
			score++;
			stapel-=3;
			if (! hatEsEinSet(false)) //wenn kein set dann tauschen
				{
				if (stapel<=12) schluss("Bravo! Kein Set mehr da. Du hast es geschafft!");
				else legen();
				}
			}
		resetSet();
		schreiben();
		update(getGraphics());
		}
		
	private void resetSet()
		{
		aktive=0;
		for(int i=0;i<3;i++)
			{
			if (set[i]>=0) karte[set[i]].istAktiv=false;
			set[i]=-1;
			}
		}
		
	private boolean istEsEinSet(int nr1, int nr2, int nr3)
		{
		if (karte[nr1].form + karte[nr2].form + karte[nr3].form != 3*karte[nr1].form
		 && karte[nr1].form + karte[nr2].form + karte[nr3].form != 1+3+9) return false;
		if (karte[nr1].farbe + karte[nr2].farbe + karte[nr3].farbe != 3*karte[nr1].farbe
		 && karte[nr1].farbe + karte[nr2].farbe + karte[nr3].farbe != 1+3+9) return false;
		if (karte[nr1].textur + karte[nr2].textur + karte[nr3].textur != 3*karte[nr1].textur
		 && karte[nr1].textur + karte[nr2].textur + karte[nr3].textur != 1+3+9) return false;
		if (karte[nr1].anzahl + karte[nr2].anzahl + karte[nr3].anzahl != 3*karte[nr1].anzahl
		 && karte[nr1].anzahl + karte[nr2].anzahl + karte[nr3].anzahl != 1+3+9) return false;
		return true;
		}		
		
	private boolean hatEsEinSet(boolean tippGeben)
		{
		for(int nr1=0;nr1<12;nr1++)
			{
			for(int nr2=nr1+1;nr2<12;nr2++)
				{
				for(int nr3=nr2+1;nr3<12;nr3++)
					{
					if (! karte[nr1].istOffen || ! karte[nr2].istOffen || ! karte[nr3].istOffen) continue;
					if (istEsEinSet(nr1,nr2,nr3))
						{
						if (tippGeben)
							{
							resetSet();
							karte[nr1].istAktiv=true;
							karte[nr2].istAktiv=true;
							set[0]=nr1;
							set[1]=nr2;
							aktive+=2;
							update(getGraphics());
							startzeit-=STRAFE*1000;
							}
						return true;
						}
					}
				}	
			}
		return false;
		}		

	private void mischen()
		{
		for(int i=0;i<200;i++)//mischen durch tauschen
			{
			int erste=(int)(Math.random()*TOTAL);
			int zweite=(int)(Math.random()*TOTAL);
			tempKarte = karte[erste];
			karte[erste] = karte[zweite];
			karte[zweite] = tempKarte;
			}
		}
		
	private void legen()
		{
		while (! hatEsEinSet(false)) //probieren bis ein set dabei ist
			{
			if (set[0] == -1) break;
			int erste=set[(int)(Math.random()*3)]; //nur leere plätze ersetzen
			int zweite=(int)(Math.random()*(stapel-12)+12);
			karte[erste].istAktiv=false;
			karte[erste].istOffen=false;
			tempKarte = karte[erste];
			karte[erste] = karte[zweite];
			karte[zweite] = tempKarte;
			karte[erste].istOffen=true;
			karte[erste].setPosition(tempKarte.x,tempKarte.y);
			}
		for(int i=0;i<4;i++) //legt 12 karten hin
			{
			for(int j=0;j<3;j++)
				{
				karte[3*i+j].setPosition(BREITE*i,HOEHE*j);
				karte[3*i+j].istOffen=true;
				}
			}
		}
		
	private void kreiereKarten()
		{
		int i;
		int koord[]={61,36,11};
		int werte[]={1,3,9};	//werte zuweisen: zahlen 1, 3 und 9 für form, farbe, textur und anzahl
		Graphics tempGraphics;
		for (int form=0;form<3;form++)
			{
			for (int farbe=0;farbe<3;farbe++)
				{
				for (int textur=0;textur<3;textur++)
					{
					i= form+3*farbe+9*textur;
					for (int anzahl=0;anzahl<3;anzahl++)
						{
						Image tempImage = createImage(BREITE,HOEHE);
						tempGraphics = tempImage.getGraphics();
						tempGraphics.drawImage(setKarte,0,0,this);
						for (int t=0;t<=anzahl;t++)
							{
							tempGraphics.drawImage(setSymbole,0,koord[anzahl]+t*50,BREITE,koord[anzahl]+t*50+38, 0,38*i,BREITE,38*(i+1), this);
							}		
						karte[anzahl*27+i]=new Karte(tempImage,werte[form],werte[farbe],werte[textur],werte[anzahl]);
						karte[anzahl*27+i].reset();
						}
					}
				}
			}			
		}

	private void schreiben()
		{
		text.setText("Finde soviele Sets wie möglich. Du hast "+ZEIT/60+" Minuten Zeit."+"\n\n"
						+"Für jeden Tipp, den du kriegst, werden dir 20 Sekunden abgezogen."+"\n\n"
						+"Wenn du nicht weisst, was ein Set ist, dann schau die Spielregeln an."+"\n\n\n"						
						+"Noch "+(81-3*score)+" Karten \n\n"
						+"Sets: "+score+"\n\n\n\n");
		text.append(kommentar);
		}	
		
	private void laden()
		{
		beep=getAudioClip(getCodeBase(),"beep.au");
		laugh=getAudioClip(getCodeBase(),"laugh.au");
		applaus=getAudioClip(getCodeBase(),"applaus.au");
 		MediaTracker tracker=new MediaTracker(this);
	   setKarte = getImage(getCodeBase(),"SetKarte.gif");
    	tracker.addImage(setKarte,1);
  	   setRahmen = getImage(getCodeBase(),"SetRahmen.gif");
    	tracker.addImage(setRahmen,1);
	   setSymbole = getImage(getCodeBase(),"SetSymbole.gif");
    	tracker.addImage(setSymbole,1);
    	try
    		{
    		tracker.waitForAll();
    		}
    	catch(InterruptedException e) {}
		}
	}