//c2000 Hector Chang
import java.applet.*;
import java.awt.*;
import java.awt.event.*;
import java.awt.geom.*;

public class Big2AppletLocal extends Applet {
    private Button c, t, p;
    private int selected; //card index clicked on
    private byte playnum;  //number of cards selected
    private byte cardselected[] = new byte[13]; //array of 1-0 values
    private int trick;
    private Big2card deck[] = Big2card.randomDeck();
    private Big2card player[][] = new Big2card[4][52];
    private Big2card played[]; //hand played
    private Big2card newplay[]; //next play
    private byte firstplay; //1 in beginning, 0 for rest of time: checks play of 3$
    private byte goodfirstplay;
    private byte onplay;
    private byte passnum;
    private byte strength, newstrength;
    private Big2card leading[] = new Big2card[1];
    private Big2card newleading[] = new Big2card[1];
    private byte active;
    private int stackx, stacky;

    public void init() {
	super.init();
	this.setLayout(null);
	this.setBackground(new Color(255,255,204));
	System.out.println("Hector Chang's Java Big Two");
	System.out.println("This output is mainly for debugging purposes");
	System.out.println();
	firstplay=1;
	goodfirstplay=0;
	onplay=0;
	active=1;
	stackx=0;
	stacky=0;
	c = new Button("deselect all");
	t = new Button("play"); //throw
	p = new Button("    pass    ");
	Label x = new Label("Hector Chang's Java Big Two");
	c.addActionListener(new ActionListener() {
		public void actionPerformed(ActionEvent e) {
		    for(byte k=0; k<13; k++)
			cardselected[k]=0;
		    repaint(50, 190, 400, 210);
		    	
		}
	    }
			    );
	t.addActionListener(new ActionListener() {
		public void actionPerformed(ActionEvent e) {
		    Big2card evaluate[] = collectHand();
		    if(onplay==0 && active==1) {
		        strength = isValid(evaluate, leading);
			if(strength > 0) {
			    played = collectHand();
			    if(firstplay==1) {
				for(byte i=0; i<played.length; i++) {
				    if(played[i].value==3 && played[i].suit==1)
					goodfirstplay=1;
				}
			    }
			    if(goodfirstplay==1 && onplay==0) {
				passnum=0;
				firstplay=0;
				onplay=1;
				stackx+=3;
				stacky+=2;
				repaint(170+stackx, 20+stacky, 155, 62);
				discard();
				System.out.println("Player " + (trick%4+1) + ":");
				System.out.println("  Length of play: " + played.length);
				System.out.println("Strength of play: " + strength);
				System.out.println(" Leading card is: " + leading[0]);
				for(byte p=0; p<played.length; p++)
				    System.out.print(played[p]);
				System.out.println();
				System.out.println();
				trick++;
				repaint(50, 190, 400, 210);
				
			    }
			}
		    }
		    else if(onplay==1 && active==1) {
			newstrength = isValid(evaluate, newleading);
			if(newstrength > 0) {
			    passnum=0;
			    firstplay=0;
			    newplay = collectHand();
			    if(newplay.length==played.length) {  
				if((newstrength > strength) || (newstrength==strength && newleading[0].value > leading[0].value) || (newstrength==strength && newleading[0].value == leading[0].value && newleading[0].suit > leading[0].suit)) {
				    stackx+=3;
				    stacky+=2;
				    repaint(170+stackx, 20+stacky, 155, 62);
				    discard();
				    System.out.println("Player " + (trick%4+1) + ":");
				    System.out.println("  New length of play: " + newplay.length);
				    System.out.println("  Old length of play: " + played.length);
				    System.out.println("New strength of play: " + newstrength);
				    System.out.println("Old strength of play: " + strength);
				    System.out.println(" New leading card is: " + newleading[0]);
				    System.out.println(" Old leading card is: " + leading[0]);
				    for(byte p=0; p<newplay.length; p++)
					System.out.print(newplay[p]);
				    System.out.println();
				    System.out.println();
				    trick++;
				    repaint(50, 190, 400, 210);
				    
				    played = newplay;
				    leading[0] = newleading[0];
				}
			    }
			}
		    }
		}
	    }
			    );
	p.addActionListener(new ActionListener() {
		public void actionPerformed(ActionEvent e) {
		    if(onplay==1 && active==1) {
			System.out.println("Player " + (trick%4+1) + " passed");
			System.out.println();
			trick++;
			passnum++;
			for(byte i=0;i<13;i++)
			    cardselected[i]=0;
			if(passnum==3) {
			    played=emptyHand();
			    passnum=0;
			    onplay=0;
			    stackx=0;
			    stacky=0;
			    repaint();
			}
			repaint(50, 190, 400, 210);
		    }
		}
	    }
			    );
	c.setBounds(50, 270, 95, 30);
       	this.add(c);
	t.setBounds(155, 270, 185, 30);
	this.add(t);
	p.setBounds(350, 270, 95, 30);
	this.add(p);
       	x.setBounds(165, 3, 180, 16);
	this.add(x);
	for(byte k = 0; k < 13; k++)
	    cardselected[k] = 0;
	for(byte d = 0; d < deck.length; d++)
	    if (deck[d].value==3 && deck[d].suit==1)
		trick = d%4;
	for (byte s=0; s<13;s++) {
	    player[0][s]=Big2card.deal(deck); 
	    player[1][s]=Big2card.deal(deck);
	    player[2][s]=Big2card.deal(deck); 
	    player[3][s]=Big2card.deal(deck);
	}
	arrangeAll();
	addMouseListener(
			 new MouseAdapter() {
				 public void mouseClicked( MouseEvent e) {
				     byte max=0;
				     for(byte i=0; i<13; i++)
					 max+=cardselected[i];
				     if(e.getY() >= 192 && e.getY() <= 260) {
					 for(int j = 51; j <= 411; j+=30) {
					     if(e.getX() > j && e.getX() < (j + 30)) {
						 selected = (int)((j-50)/30);
						 if (cardselected[selected] == 1) 
						     cardselected[selected] = 0;
						 else if (cardselected[selected] == 0 && player[trick%4][selected].value != 16 && max < 5)
						     cardselected[selected] = 1;
			       			 repaint(selected*30+50,190,33,72);
					     }
					 }
				     }

				 }
			     }
			 );
    }

    public void paint(Graphics g) {
	g.setFont(new Font( "SansSerif", Font.PLAIN, 12));
	g.setColor(Color.black);
	byte win[] = checkVictory();
	for(byte p=0; p<4; p++)
	    if(win[p]==0) {
		g.drawString("Player " + (p+1) + " is the winner!", 60, 330);
		active=0;
		for(byte i = 0; i < played.length; i++)
		    drawCard(i*30+170+stackx, 20+stacky, played[i], g);
	    }
	if(active != 0) {
	    g.drawString("Player " + ((trick%4)+1), 60, 330);
	    byte howmany1 = 0;
	    for(byte i = 0; i < 13; i++)
		if (player[((trick+1)%4)][i].value != 16)
		    howmany1++;
	    byte howmany2 = 0;
	    for(byte i = 0; i < 13; i++)
		if (player[((trick+2)%4)][i].value != 16)
		    howmany2++;
	    byte howmany3 = 0;
	    for(byte i = 0; i < 13; i++)
		if (player[((trick+3)%4)][i].value != 16)
		    howmany3++;
	    if(firstplay==1)
		g.drawString("Play must include 3 of Diamonds", 60, 345);
	    g.drawString("Player " + (((trick+1)%4)+1), 60, 393);
	    g.drawString("Player " + (((trick+2)%4)+1), 200, 393);
	    g.drawString("Player " + (((trick+3)%4)+1), 340, 393);
	    for(byte i = 0; i < howmany1; i++) {
		g.setColor(new Color(200, 200, 160));
		g.fillRoundRect(60+i*8, 358, 10, 20, 5, 5);
		g.setColor(Color.black);
		g.drawRoundRect(60+i*8, 358, 10, 20, 5, 5);
	    }
	    for(byte i = 0; i < howmany2; i++) {
		g.setColor(new Color(200, 200, 160));
		g.fillRoundRect(200+i*8, 358, 10, 20, 5, 5);
		g.setColor(Color.black);
		g.drawRoundRect(200+i*8, 358, 10, 20, 5, 5);
	    }
	    for(byte i = 0; i < howmany3; i++) {
		g.setColor(new Color(200, 200, 160));
		g.fillRoundRect(340+i*8, 358, 10, 20, 5, 5);
		g.setColor(Color.black);
		g.drawRoundRect(340+i*8, 358, 10, 20, 5, 5);
	    }
	    if(firstplay==0 && onplay==1)
		if(played.length==1)
		    g.drawString("Play " + played.length + " card", 60, 345);
		else
		    g.drawString("Play " + played.length + " cards", 60, 345);
	    for(byte i = 0; i < 13; i++) {
		if(player[trick%4][i].value != 16 )
		    drawCard(i*30+50, 200-cardselected[i]*10, player[trick%4][i], g);
	    }
	    if(firstplay != 1)
		for(byte i = 0; i < played.length; i++)
		    drawCard(i*30+170+stackx, 20+stacky, played[i], g);
	}
    }

    public void makeSuit (int x, int y, int suit, Graphics g) {
	switch (suit) {
      case 1: //diam:  x, 18; y, 24
        int xpts4[] = {x+11,  x+20, x+11, x+2};
        int ypts4[] = {y,     y+12, y+24, y+12};
	g.fillPolygon(xpts4, ypts4, xpts4.length);
        break;
      case 2: //club:  x, 22; y, 24
	  //        int xpts2[] = {x+11, x+13, x+16, x+16, x+13, x+18, x+22, x+21, x+18, x+13, x+15, x+7,  x+9,  x+4,  x+1,  x,    x+4, x+9,  x+6, x+6, x+9};
        int xpts2[] = {x+11, x+13, x+16, x+16, x+13, x+18, x+22, x+21, x+18, x+13, x+15, x+7,  x+9,  x+4,  x+1,  x+1,    x+4, x+9,  x+6, x+6, x+9};
        int ypts2[] = {y+1,  y+1,  y+4,  y+6,  y+11, y+7,  y+10, y+16, y+18, y+15, y+24, y+24, y+15, y+18, y+16, y+10, y+7, y+11, y+6, y+4, y+1};
	g.fillPolygon(xpts2, ypts2, xpts2.length);
        break;
      case 3: //heart: x, 18; y, 24
        int xpts3[] = {x+11, x+15, x+18, x+20, x+18, x+11,  x+4,  x+2, x+4, x+7};
        int ypts3[] = {y+6,  y,    y+2,  y+8,  y+14, y+24,  y+14, y+8, y+2, y};
	g.fillPolygon(xpts3, ypts3, xpts3.length);
        break;
      case 4: //spade: x. 18; y, 24
        int xpts[] = {x+11,  x+19, x+20, x+18, x+16, x+13,  x+15, x+7,   x+9,  x+6,  x+4,  x+2,  x+3};
        int ypts[] = {y,     y+12, y+16, y+20, y+20, y+16,  y+24, y+24,  y+16, y+20, y+20, y+16, y+12};
	g.fillPolygon(xpts, ypts, xpts.length);
        break;
        }
    }

    public void drawCard(int x, int y, Big2card card, Graphics g) {
	g.setColor(Color.white);
	g.fillRoundRect(x, y, 32, 60, 10, 10);
	g.setColor(Color.black);
	g.drawRoundRect(x, y, 32, 60, 10, 10);
	g.setColor(Color.red);
	if (card.suit % 2 == 0)
	    g.setColor(Color.black);
	makeSuit(x+5, y+5, card.suit, g);
	g.setFont(new Font( "SansSerif", Font.PLAIN, 26));
	String tag = new String();
	switch (card.value) {
	case 10:
	    tag = "I0";
	    break;
	case 11:
	    tag = "J";
	    break;
	case 12:
	    tag = "Q";
	    break;
	case 13:
	    tag = "K";
	    break;
	case 14:
	    tag = "A";
	    break;
	case 15:
	    tag = "2";
	    break;
	default:
	    tag = Integer.toString(card.value);
	}
	g.drawString(tag, x+6, y+55);
    }

    public byte isValid(Big2card hand[], Big2card lead[]){
	byte strength = 0;
	playnum = 0;
	for(byte i=0; i<13; i++)
	    playnum += cardselected[i];
	if(playnum == 0 || playnum == 4 || playnum > 5)
	    strength = 0;
	if(playnum == 1) { 
	    strength += 1;
	    lead[0] = hand[0];
	}
	if(playnum == 2) {
	    if(hand[0].value == hand[1].value)
	        strength += 2;
	    lead[0] = hand[1];
	}
	if(playnum == 3) {
	    if(hand[0].value == hand[1].value && hand[1].value == hand[2].value)
		strength += 3;
	    lead[0] = hand[2];
	}
	if(playnum == 5) {
	    if(hand[0].value == hand[1].value && hand[1].value == hand[2].value && hand[2].value == hand[3].value) {
		strength += 7;
		lead[0] = hand[3];
	    }
	    if(hand[1].value == hand[2].value && hand[2].value == hand[3].value && hand[3].value == hand[4].value) {
		strength += 7;
		lead[0] = hand[4];
	    }
	    if(hand[0].value == hand[1].value && hand[1].value == hand[2].value && hand[3].value == hand[4].value) {
		strength += 6;
		lead[0] = hand[2];
	    }
	    if(hand[0].value == hand[1].value && hand[2].value == hand[3].value && hand[3].value == hand[4].value) {
		strength += 6;
		lead[0] = hand[4];
	    }
	    if(hand[0].suit==hand[1].suit && hand[1].suit==hand[2].suit && hand[2].suit==hand[3].suit && hand[3].suit==hand[4].suit) {
		strength += 5;
		lead[0] = hand[4];
	    }
	    int firstvalue = hand[0].value;
	    if(hand[1].value==firstvalue+1 && hand[2].value==firstvalue+2 && hand[3].value==firstvalue+3 && hand[4].value==firstvalue+4) {
		strength += 4;
		lead[0] = hand[4];
	    }
	}
	return strength;
    }

    public void arrangeAll() {
	Big2card.arrangeHand(player, 0);
	Big2card.arrangeHand(player, 1);
	Big2card.arrangeHand(player, 2);
	Big2card.arrangeHand(player, 3);
    }    

    public Big2card[] collectHand() {
	playnum = 0;
	for(byte i=0; i<13; i++)
	    playnum += cardselected[i];
        Big2card hand[] = new Big2card[playnum];
	byte counter = 0;
        for(byte i=0; i<13; i++) {
	    if(cardselected[i]==1) {
		hand[counter] = player[trick%4][i];
		counter++;
	    }
	}
	return hand;
    }

    public Big2card[] emptyHand() {
	Big2card hand[] = new Big2card[0];
	return hand;
    }

    public void discard() {
	for(byte i=0; i<13; i++) {
	    if(cardselected[i]==1) {
		cardselected[i]=0;
		player[trick%4][i]=new Big2card(16,1);
	    }
	}
	arrangeAll();
	repaint(50, 190, 400, 210);			
    }

    public byte[] checkVictory() {
	byte score[] = new byte[4];
	for(byte p=0; p<4; p++) {
	    for(byte i=0; i<13; i++) {
		if(player[p][i].value != 16)
		    score[p]++;
	    }
	}
	return score;
    }
}
