import java.awt.Rectangle;
import java.awt.Graphics;
import java.awt.Color;
import java.awt.Event;
import java.awt.Font;
import java.lang.Math;
public class set extends java.applet.Applet {
	int totalWidth,totalHeight;
	int deck[] = new int[81];
	int deck1[] = new int[81];
	card display[][] = new card[3][5];
	card selected[] = new card[3];
	int nselected = 0;
	int valid=0;
	int cards,cardlen=4;
	int cardsize;
	int fontsize;
	Font myfont;
	Color colors[] = new Color[3],shades[] = new Color[3];
	mybutton accept, help, more;
	int helps,found,needmore;
	public void init(){
		int i,j;
		totalWidth = size().width;
		totalHeight = size().height;
		cardsize=totalWidth/6;
		fontsize=totalWidth/24;
		colors[0]=Color.red;
		colors[1]=Color.blue;
		colors[2]=Color.green;
		shades[0]=Color.cyan;
		shades[1]=Color.orange;
		shades[2]=Color.magenta;
		myfont = new Font("TimesRoman",Font.BOLD,fontsize);
		for (i=0 ; i<81 ; i++)deck1[i]=i;
		helps=found=0;
		cards=0;
		for (i=80 ; i>=0 ; i--){
			j=(int)Math.round(Math.random()*i);
			deck[cards++]=deck1[j];
			deck1[j]=deck1[i];
			}
		for (i=0 ; i<4 ; i++)
			for (j=0 ; j<3 ; j++){
				display[j][i]=new card(this,j,i,deck[--cards]);
				}
		for (j=0 ; j<3 ; j++)
			display[j][4]=new card(this,j,4,-1);
		needmore();
		accept = new mybutton(cardsize*4,cardsize/10+cardsize,cardsize,cardsize);
		help = new mybutton(cardsize*4,(cardsize/10+cardsize)*2,cardsize,cardsize);
		more = new mybutton(cardsize*4,(cardsize/10+cardsize)*3,cardsize,cardsize);
		}
void needmore(){
	int ii,jj,kk,i,j,k;
	valid=0;
	while(nselected>0)selected[--nselected].raised=false;
	for(ii=0 ; ii<(cardlen*3) ; ii++)
		for(jj=0 ; jj<(cardlen*3); jj++)
			for(kk=0 ; kk<(cardlen*3); kk++){
				if(ii==jj || ii==kk || jj==kk)
					continue;
				i=ii/3;
				j=ii%3;
				selected[0]=display[j][i];
				i=jj/3;
				j=jj%3;
				selected[1]=display[j][i];
				i=kk/3;
				j=kk%3;
				selected[2]=display[j][i];
				nselected=3;
				validate();
				if(valid==1){
					needmore=0;
					nselected=0;
					return;
					}
				}
	needmore=1;
	}
public void validate(){
	int i,j;
	valid=0;
	if(nselected != 3)return;
	j=0;
	for(i=0 ; i<3 ; i++)j|= (1<<selected[i].color);
	if(j!=1 && j!=2 && j!=4 && j!=7)return;
	j=0;
	for(i=0 ; i<3 ; i++)j|= (1<<selected[i].shade);
	if(j!=1 && j!=2 && j!=4 && j!=7)return;
	j=0;
	for(i=0 ; i<3 ; i++)j|= (1<<selected[i].shape);
	if(j!=1 && j!=2 && j!=4 && j!=7)return;
	j=0;
	for(i=0 ; i<3 ; i++){
		j|= (1<<selected[i].count);
		}
	if(j!=1 && j!=2 && j!=4 && j!=7)return;
	valid=1;
	}
public void paint(Graphics g){
	card c;
	int i,j;
	int cardsize= totalWidth/18;
	for(i=0 ; i<5 ; i++)
		for(j=0 ; j<3 ; j++){
			c=display[j][i];
			c.paint(g);
			}
	g.setFont(myfont);
	if(valid == 1){
	g.setColor(Color.gray);
	g.fillRect(accept.x,accept.y,accept.width,accept.height);
	g.setColor(Color.white);
	g.drawString("accept",accept.x+cardsize,accept.y+cardsize);
		}
	g.setColor(Color.gray);
	g.fillRect(help.x,help.y,help.width,help.height);
	g.setColor(Color.white);
	g.drawString("help",help.x+cardsize,help.y+cardsize);
	g.setColor(Color.gray);
	g.fillRect(more.x,more.y,more.width,more.height);
	g.setColor(needmore==1?Color.red:Color.white);
	g.drawString("more",more.x+cardsize,more.y+cardsize);
	g.setColor(Color.black);
	g.drawString(cards+" cards left",more.x,more.y+more.height+cardsize);
	g.drawString(found+" sets found",more.x,more.y+more.height+cardsize*2);
	g.drawString(helps+" helps called",more.x,more.y+more.height+cardsize*3);
	}
public boolean mouseDown(Event evt, int x, int y){
	int i,j,k;
	card c;
	for (i=0 ; i<cardlen ; i++)
		for(j=0 ; j<3 ; j++){
			c=display[j][i];
			if(c.inside(x,y)){
				if(c.raised){
					for(k=0 ; k<nselected ; k++)
						if(c == selected[k])break;
					selected[k]=selected[--nselected];
					c.raised=false;
					repaint();
					valid=0;
					return true;
					}
				else if(nselected<3) {
					selected[nselected++]=c;
					c.raised=true;
					validate();
					repaint();
					return true;
					}
				}
			}
	if(valid == 1 && accept.inside(x,y)){
		for(k=0 ; k < 3 ; k++){
			i=selected[k].i;
			j=selected[k].j;
			if(cardlen==5){
				if(i!=4)
				display[j][i]=new card(this,j,i,
				display[k][4].myvalue);
				display[k][4].myvalue= -1;
				}
			else display[j][i]=new card(this,j,i,
				(cards>0 ? deck[--cards] : -1 ));
			}
		found++;
		nselected=0;
		cardlen=4;
		needmore();
		valid=0;
		repaint();
		return true;
		}
	if(help.inside(x,y)){
		int ii,jj,kk;
		valid=0;
		nselected=0;
		while(nselected>0)selected[--nselected].raised=false;
		for(ii=0 ; ii<(cardlen*3) ; ii++)
			for(jj=0 ; jj<(cardlen*3); jj++)
				for(kk=0 ; kk<(cardlen*3); kk++){
					if(ii==jj || ii==kk || jj==kk)
						continue;
					i=ii/3;
					j=ii%3;
					selected[0]=display[j][i];
					i=jj/3;
					j=jj%3;
					selected[1]=display[j][i];
					i=kk/3;
					j=kk%3;
					selected[2]=display[j][i];
					nselected=3;
					validate();
					if(valid==1){
						selected[0].raised=true;
						selected[1].raised=true;
						selected[2].raised=true;
						helps++;
						needmore=0;
						repaint();
						return true;
						}
					}
		needmore=1;
		}
	if(cardlen==4 && more.inside(x,y)){
		for(j=0 ; j<3 ; j++)
			display[j][4]=new card(this,j,4,
			(cards>0?deck[--cards]:-1));
		cardlen++;
		valid=0;
		needmore=0;
		repaint();
		return true;
		}
	return false;
	}
}
class card extends Rectangle {
	set parent;
	int color,shade,shape,count;
	boolean raised;
	int i,j,myvalue;
	card(set parent1, int xoff, int yoff, int value){
		parent=parent1;
		int gap = parent.cardsize/6;
		width = parent.cardsize;
		height = parent.cardsize;
		myvalue=value;
		j=xoff;
		i=yoff;
		x = (xoff * (gap + width))+gap;
		y = (yoff * (gap + height))+gap;
		color = value % 3;
		value /= 3;
		shade = value % 3;
		value /= 3;
		shape = value % 3;
		count = (value / 3);
		raised=false;
		}
	void triangle(int x, int y, int xa[], int ya[], int objsize){
		xa[0]=x;
		ya[0]=y+objsize;
		xa[1]=x+objsize;
		ya[1]=y+objsize;
		xa[2]=x+(objsize/2);
		ya[2]=y;
		}
	public void paint(Graphics g){
		int objsize=width/4;
		int gap=objsize/4;
		int xa[] = new int[3];
		int ya[] = new int[3];
		Color mycolor;
		if(myvalue== -1) return;
		mycolor=parent.shades[shade];
		mycolor=(raised ? mycolor.brighter() : mycolor.darker());
		g.setColor(mycolor);
		g.fillRoundRect(x,y,width,height,5,5);
		if(raised){
			g.setColor(Color.black);
			g.drawString("s",x+5,y+10);
			}
		g.setColor(parent.colors[color]);
		if(count==1 || count==2){
			if(shape==0){
		g.fillRect(x+gap,y+(2*(objsize+gap))+gap,objsize,objsize);
		g.fillRect(x+(2*(objsize+gap))+gap,y,objsize,objsize);
				}
			if ( shape == 1){
		g.fillOval(x+gap,y+(2*(objsize+gap))+gap,objsize,objsize);
		g.fillOval(x+(2*(objsize+gap))+gap,y,objsize,objsize);
				}
			if ( shape == 2){
		triangle(x+gap,y+(2*(objsize+gap))+gap,xa,ya,objsize);
		g.fillPolygon(xa,ya,3);
		triangle(x+(2*(objsize+gap))+gap,y,xa,ya,objsize);
		g.fillPolygon(xa,ya,3);
				}
			}
		if(count==0 || count==2){
			if(shape==0)
		g.fillRect(x+(objsize+gap)+gap,y+(objsize+gap)+gap,objsize,objsize);
			if(shape==1)
		g.fillOval(x+(objsize+gap)+gap,y+(objsize+gap)+gap,objsize,objsize);
			if(shape==2){
		triangle(x+(objsize+gap)+gap,y+(objsize+gap)+gap,xa,ya,objsize);
		g.fillPolygon(xa,ya,3);
				}
			}
		}
	}
class mybutton extends Rectangle {
	mybutton(int x, int y, int w, int h){
		super(x,y,w,h);
		}
	}

