import java.applet.*;
import java.awt.*;
import java.awt.event.*;
import java.awt.image.*;
import java.util.*;
import java.text.*;
 
public class OhHell extends Applet implements MouseListener, KeyListener, Runnable
{
	// Screen constants	
	static final int BIDW = 30;
	static final int BIDH = 20;

	static final int SCOREW = 130;
	static final int SCOREH = 70;
	static final int SCOREX = 515;

	static final int TinyOFFSET = 5; 
	static final int SmOFFSET = 10; 
	static final int MedOFFSET = 15;
	static final int LgOFFSET = 20; 

	static final int MYHANDX = 235;

	static final int CARDOFFSET = 140; 
	static final int CARDW = 50; 
	static final int CARDH = 80; 

	Player players[] = new Player[4]; 
	int Leaders[] = {0, 1, 2, 3}; 
	static final String names[] = {"JILL", "JOE", "NICK", "YOU"};

	// the cards and the deal
	boolean Deck[] = new boolean[52]; 
	int HowMany = 14;
	int HowManyLeft = 0;
	int Direction = 0; // 0 = down
	int FirstTime = 0;
	int Trump = 4;
	int TrumpSwitch = 0;
	
	// bid variables
	int TtlBid = 0;
	int FirstToBid = 0;
	int CantBid = 10; 
	String Declare = "";
	
	// the play
	MediaTracker tracker = new MediaTracker(this);
 	int theLead;
	int LeadSuit;
	int TopCard;
	int TopPlayer;
	int IWent = 0;
	int StartPlay;
	int StopPlay = 3;
	int IGo = 0;

	Random rand = new Random();

	Thread trick = null;

	// Set up clicking areas
	Rectangle Deal = new Rectangle(540, 360, 80, 30);

      Font smallFont = new Font("SansSerif", Font.BOLD, 12);
      Font RegFont = new Font("SansSerif", Font.BOLD, 16);
	Font BigFont = new Font("SansSerif", Font.BOLD, 20);

    public void init() 
    {
	 setBackground(Color.pink);
	 addMouseListener(this);
	 addKeyListener(this);
	 for(int i = 0; i < 4; i++)
	    players[i] = new Player(names[i]);
    }

   public void update(Graphics g)
   {
	paint(g);
   }
	
   public void paint(Graphics g)
   {
	g.setFont(smallFont);
	g.clearRect(0, 0, 514, 400);

	// Add a Deal button
	g.setFont(RegFont);
	g.setColor(Color.lightGray);
	g.fill3DRect(540, 360, 80, 30, true);
	g.setColor(Color.black);
	g.drawRect(540 - 2, 360 - 2, 80, 30);
	g.drawString("DEAL", 540 + MedOFFSET, 360 + LgOFFSET); 

	// Add Trump display
	if(Trump < 4)
	{
	   String TrumpSuit = null;
	   g.setFont(RegFont);
	   g.setColor(Color.white);
	   g.fillRect(TinyOFFSET, 50, 110, 25);
	   g.setColor(Color.black);
	   g.drawString("Trump", 37, 48);
	   g.drawRect(TinyOFFSET, 50, 110, 25);
	   if((Trump == 1) || (Trump == 3))
		g.setColor(Color.red);
	   if(Trump == 0)
		TrumpSuit = "   Clubs";
	   if(Trump == 1)
		TrumpSuit = "Diamonds";
	   if(Trump == 2)
		TrumpSuit = "  Spades";
	   if(Trump == 3)
		TrumpSuit = "  Hearts";
	   g.setFont(BigFont);
	   g.drawString(TrumpSuit, MedOFFSET, 70); 
	}

	// Add the overbid/underbid display 
	if(Declare.length() > 0)
	   PaintBidDisplay(g);
 
	// Add the score
	g.setColor(Color.red);
	int ScoreY = 16;
      g.clearRect(SCOREX, 0, SCOREW, 15);
	g.fillRect(SCOREX, ScoreY, SCOREW, SCOREH);
	g.setColor(Color.black);
	g.drawString("Score", SCOREX + 40, 14);
	g.fillRect(SCOREX, ScoreY, SCOREW, 3);
	g.fillRect(SCOREX, ScoreY, 3, SCOREH);
	g.fillRect(SCOREX + SCOREW, ScoreY, 3, SCOREH);
	g.fillRect(SCOREX, ScoreY + SCOREH, SCOREW + 3, 3);
	g.setFont(smallFont);
	ScoreY += 20;
	for(int i = 0; i < 4; i++)
	{
	   g.setColor(Color.black);
	   int x = Leaders[i];
	   String Score = String.valueOf(players[x].Score); 		
	   g.drawString(players[x].Name, SCOREX + 5, ScoreY);
	   g.drawString(Score, 105 + SCOREX, ScoreY);
	   g.setColor(Color.white);
	   g.drawString(players[x].Name, SCOREX + 6, ScoreY + 1);
	   g.drawString(Score, 106 + SCOREX, ScoreY + 1);
	   ScoreY += 15;
	}  
	// Add bid / trick boxes
	PaintBoxes(g);
	if(FirstTime > 0)
	{
	   DisplayCards(g);
	   PaintMine(g); 
	}
   }

   private void PaintBidDisplay(Graphics g)
   {
	g.setFont(RegFont);
	g.setColor(Color.black);
	g.fillRect(TinyOFFSET, TinyOFFSET, 110, 25);
	g.setColor(Color.white);
	g.drawRect(TinyOFFSET, TinyOFFSET, 110, 25);
      g.drawString(Declare,TinyOFFSET+SmOFFSET,TinyOFFSET+LgOFFSET); 
   }	

   private void PaintBoxes(Graphics g)
   {
	g.setFont(smallFont);
	//do the top and bottom players
	int TempX = 220;
	int p = 3;
	int TempY = 95;
	for (int x = 0; x < 4; x++)
	{
         g.setColor(Color.lightGray);
	   g.fillRect(TempX, TempY, BIDW, BIDH);
	   g.setColor(Color.black);
	   if(x % 2 == 0)
	   	g.drawString("Bid", TempX + 5, TempY - 2);
	   else
	   	g.drawString("Tricks", TempX, TempY - 2);
	   g.fillRect(TempX, TempY, BIDW, p);
	   g.fillRect(TempX, TempY, p, BIDH);
	   g.fillRect(TempX + BIDW, TempY, p, BIDH);
	   g.fillRect(TempX, TempY + BIDH, BIDW + p, p);
	   TempX += 50;
	   if(x == 1)
	   {
		TempX = 220;
		TempY += 196;
	   }		
	}
	TempX = 220;
	TempY = 95;
	for (int x = 1; x < 4; x += 2)
	{
   	   g.setColor(Color.black);	
	   g.drawString(String.valueOf(players[x].Bid),TempX+15,TempY+15); 
	   g.drawString(String.valueOf(players[x].Tricks), TempX + 60, TempY + 15); 
	   g.fillRect(TempX - 55, TempY + 5, 35, 20);
	   g.setColor(Color.white);	
	   g.drawString(players[x].Name, TempX - 50, TempY + 20); 
	   TempY += 196;
	}

	//do the left and right players
	TempX = 100;
	TempY = 180;
	for (int x = 0; x < 4; x++)
	{
         g.setColor(Color.lightGray);
	   g.fillRect(TempX, TempY, BIDW, BIDH);
	   g.setColor(Color.black);
	   g.fillRect(TempX, TempY, BIDW, p);
	   g.fillRect(TempX, TempY, p, BIDH);
	   g.fillRect(TempX + BIDW, TempY, p, BIDH);
	   g.fillRect(TempX, TempY + BIDH, BIDW + p, p);
	   TempX += 280;
	   if(x == 1)
	   {
		TempX = 100;
		TempY += 40;
	   }		
	}
      TempX = 115;
	TempY = 195;
	for (int x = 0; x < 3; x += 2)
	{
	   g.setColor(Color.black);	
	   g.drawString("Bid", TempX - 10, TempY - 17);
	   g.drawString("Tricks", TempX - 15, TempY + 23);
	   g.drawString(String.valueOf(players[x].Bid), TempX, TempY); 
	   g.drawString(String.valueOf(players[x].Tricks),TempX,TempY+40); 
	   g.fillRect(TempX - 15, TempY + 60, 35, 20);
	   g.setColor(Color.white);	
	   g.drawString(players[x].Name, TempX - 10, TempY + 75); 
	   TempX += 280;
	}
   }

   private void DisplayCards(Graphics g)
   {
	int TempX = MYHANDX - (6 * HowManyLeft);
	int TempY = 0;
	for(int i = 0; i < HowManyLeft; i++)
	{
	   g.setColor(Color.blue);	
	   g.fillRoundRect(TempX, TempY, CARDW, CARDH, 10, 10);
	   g.setColor(Color.white);	
	   g.fillRoundRect(TempX + 2, TempY +2, CARDW-4, CARDH-4, 10, 10);
	   g.setColor(Color.blue);	
	   g.fillRoundRect(TempX + 3, TempY +3, CARDW-6, CARDH-6, 10, 10);
	   g.setColor(Color.black);	
	   g.drawRoundRect(TempX, TempY, CARDW, CARDH, 10, 10);
	   TempX += 15;
	}

	TempY = 180 - (6 * HowManyLeft);
	TempX = 5;
	for(int i = 0; i < HowManyLeft; i++)
	{
	   g.setColor(Color.blue);	
	   g.fillRoundRect(TempX, TempY, CARDH, CARDW, 10, 10);
	   g.fillRoundRect(TempX + 420, TempY, CARDH, CARDW, 10, 10);
	   g.setColor(Color.white);	
	   g.fillRoundRect(TempX + 2, TempY +2, CARDH-4, CARDW-4, 10, 10);
	   g.fillRoundRect(TempX +422, TempY+2, CARDH-4, CARDW-4, 10, 10);
	   g.setColor(Color.blue);	
	   g.fillRoundRect(TempX +3, TempY +3, CARDH-6, CARDW-6, 10, 10);
	   g.fillRoundRect(TempX +423, TempY+3, CARDH-6, CARDW-6, 10, 10);
	   g.setColor(Color.black);	
	   g.drawRoundRect(TempX, TempY, CARDH, CARDW, 10, 10);
	   g.drawRoundRect(TempX + 420, TempY, CARDH, CARDW, 10, 10);
	   TempY += 15;
	}
   }

   private void DealCards()
   {
	int cards;
	// reset the deck
	for(int i = 0; i < 52; i++)
	   Deck[i] = false;
	// for each of the 4 players ...
	for(int x = 0; x < 4; x++)
	{ 
	   // reset the bid / trick	
	   players[x].Bid = 0;
         players[x].Tricks = 0;
	   // Deal the appropriate amount of cards
	   for(int i = 0; i < HowMany; i++)
	   {
	      while(true)
	      {
		   cards = (int)(Math.random() * 52);
		   if(Deck[cards] == false)
		      break;
	      }
	      players[x].Hand[i] = new Card(cards);
		if(x == 3)
		   tracker.addImage(players[x].Hand[i].pic, 0);
		else 
		   tracker.addImage(players[x].Hand[i].pic, 1);
	      Deck[cards] = true; //take that card out of circulation
	   }
	} 
	// Pick a Trump suit
	if(HowMany != 13)
	   Trump = (int)(Math.random() * 4);
	if(HowMany > 2)
	   players[3].SortHand(HowMany);
	repaint(); 
   }	

   private void GetBid()
   {
	int whoGoes = FirstToBid;
	boolean last = false;
	for(int x = 0; x < 4; x++)
	{
	   if(whoGoes == 3)
	   {
		GetMyBid(x);
		break;
	   }
	   else 
		EnterBid(whoGoes, last);
	   whoGoes += 1;
	}
   }
	
   private void FinishBid(int left)
   {
      boolean last;
	for(int x = 0; x < left; x++)
	{
	   last = (x == left -1) ? true : false;
	   EnterBid(x, last);
	}
   }

   private void GetMyBid(int x)
   {
	int MyBidY = 120;
	Graphics g = getGraphics();
	g.setFont(smallFont);
	if(x < 3)
	   CantBid = HowMany - TtlBid;
	g.setColor(Color.white);
	g.fillRect(SCOREX, MyBidY, SCOREW, SCOREH);
	g.setColor(Color.black);
	g.fillRect(SCOREX, MyBidY, SCOREW, 3);
	g.fillRect(SCOREX, MyBidY, 3, SCOREH);
	g.fillRect(SCOREX + SCOREW, MyBidY, 3, SCOREH);
	g.fillRect(SCOREX, MyBidY + SCOREH, SCOREW + 3, 3);
	g.drawString("The bidding is at " + String.valueOf(TtlBid), SCOREX + 5, MyBidY + 20);
	if((x == 3)&&(TtlBid < HowMany + 1))
	{
	   CantBid = HowMany - TtlBid;
	   g.drawString("You may Not bid " + String.valueOf(CantBid), SCOREX + 5, MyBidY + 45);
	}
	g.drawString("Type in your bid Now", SCOREX + 5, MyBidY + 60);
   }	
	
   private void EnterBid(int whoGoes, boolean last)
   {
	float Strength = players[whoGoes].EvaluateHand(HowMany, Trump);
	int theBid = 0;
      if(last) 
	{
	   //player is last to bid and may not bid anything
	   if(Strength > (HowMany - TtlBid))    	   	    	
      	theBid = (int)Math.ceil(Strength);
	   else
		theBid = (int)Math.floor(Strength);
	}
	else
	{
	   //player is not last to bid and may bid anything
	   theBid = (int)Math.round(Strength);
	}
	players[whoGoes].Bid = theBid;
	TtlBid += theBid;
   }	

   private void PaintMine(Graphics g)
   {		
      // make sure images are loaded - eliminate flickering
	try
	{
	   tracker.waitForID(0);
	}	
      catch(InterruptedException e){}
	int TempX = MYHANDX - (6 * HowManyLeft);
	int TempY = 320;
	g.clearRect(155, TempY - 1, 270, 83); 
	for(int i = 0; i < HowMany; i++)
	{
	   if(players[3].Hand[i].Display == true) 
	   {
	      g.drawImage(players[3].Hand[i].pic, TempX, TempY, TempX + 80, TempY + 80, 0, 0, 100, 100, this);
	   }
         TempX += 15;
	}
	g.clearRect(TempX + 45, TempY - 1, 25, 83); 
   }
	
   public void run()
   {
	Graphics g = getGraphics();
	IGo = 0;
	try
	{
	   tracker.waitForID(1);
	}	
      catch(InterruptedException e){}
	for(int x = StartPlay; x < StopPlay; x++)
	{
	   try
	   {
	      trick.sleep(1500);
	   }
	   catch(InterruptedException e){}
	   PlayCard(g, x);
	}	
      if(IWent == 1) 
	{
	   try
	   {
	      trick.sleep(2000);
	   }
	   catch(InterruptedException e){}
	   DetermineWinner(g);	
	}
	IGo = 1;
   }
	
   public void stop()
   {
      trick = null;
   }	
   
   private void ILead()
   {
	Graphics g = getGraphics();
	g.setFont(RegFont);
      g.setColor(Color.black);
	g.fillRect(SCOREX, 200, 110, 25);
	g.setColor(Color.white);
	g.drawRect(SCOREX, 200, 110, 25);
      g.drawString("You Lead!", SCOREX + SmOFFSET, 200 + LgOFFSET);
	IGo = 1;
	theLead = 3;
   }
		
   private void WhoLeads()
   {
	trick = null;
	// figure out who leads and start a playing thread 
	if(FirstToBid == 2) // I lead
	   ILead();
	else if (FirstToBid == 3)
	   theLead = 0;
	else
   	   theLead = FirstToBid + 1;
      StartPlay = theLead;
      StopPlay = 3;
	if (theLead != 3)
	{
	   trick = new Thread(this);
	   trick.start();
	}
   }
	
   private synchronized void PlayCard(Graphics g, int x)
   {
	boolean haveSuit = false;
	boolean wantTrick = false;
	int theCard = 0;
	// Does the player want to win this trick
	if(players[x].Bid > players[x].Tricks)
	   wantTrick = true;

	// Select a card from player
	if(theLead == x)
	{
   	   int PlaySw = 0;
	   for(theCard = 0; theCard < HowMany; theCard++)
	   {
	      int Value = players[x].Hand[theCard].Value;
   	      int Suit = players[x].Hand[theCard].Suit;
            if(players[x].Hand[theCard].Display) 
		{
		   if((wantTrick)&&(Value > 9))
		   {
			PlaySw = 1;
	            break;
		   }	
	 	   else if((!wantTrick)&&(Value < 6))
		   {
			PlaySw = 1;
	            break;
		   }	
		}
	   }
	   if(PlaySw == 0)
	   {
		for(theCard = 0; theCard < HowMany; theCard++)
      	{
    	         if(players[x].Hand[theCard].Display) 
		      break;
	      }
	   }	
	   LeadSuit = players[x].Hand[theCard].Suit;
	   SetTop(players[x].Hand[theCard].Value, x);
	}
	else if(theLead != x)
	{ 
	   // check that they have one of the suit lead
	   for(int i = 0; i < HowMany; i++)
	   {	
		if((players[x].Hand[i].Suit == LeadSuit)&&	
	 	   (players[x].Hand[i].Display)) 
      	   haveSuit = true;
	   }	
	   // if they do - select one from that suit
	   if(haveSuit)
	   { 
		int PlaySw = 0;
		for(theCard = 0; theCard < HowMany; theCard++)
	   	{ 
		   int Value = players[x].Hand[theCard].Value;
		   int Suit = players[x].Hand[theCard].Suit;
		   if((Suit==LeadSuit)&&(players[x].Hand[theCard].Display))
  		   { 
			if(wantTrick)
			{ 
			   // no one has trumped the trick so play high	
			   if((TrumpSwitch == 0)&&(Value > TopCard))
			   {
			      PlaySw = 1;
	                  break;
			   }	
			   // some one has trumped the trick so play low	
			   else if((TrumpSwitch == 1)&&(Value < 8))
			   {
			      PlaySw = 1;
	                  break;
			   }
			} 
			else if(!wantTrick)
			{ 
			   if((TrumpSwitch == 0)&&(Value < TopCard))
			   {
			      PlaySw = 1;
	                  break;
			   }	
			   // some one has trumped the trick so play high	
			   else if((TrumpSwitch == 1)&&(Value > 9))
			   {
			      PlaySw = 1;
	                  break;
			   }
			} 
		   } 
		} 
		// if they didn't play a card select one randomly
		if(PlaySw == 0)
		{
		   for(theCard = 0; theCard < HowMany; theCard++)
	   	   {
			if((players[x].Hand[theCard].Display)&&(players[x].Hand[theCard].Suit == LeadSuit))
	               break;
		   }	
	      }
	   } 
	   // if they don't have lead suit select a card		
	   if(!haveSuit)
	   {  
		int PlaySw = 0;
		for(theCard = 0; theCard < HowMany; theCard++)
	   	{  
		   int Value = players[x].Hand[theCard].Value;
		   int Suit = players[x].Hand[theCard].Suit;
		   if(players[x].Hand[theCard].Display) 
		   { 
			if(wantTrick)
			{ 
			   // Can't trump so dump a low card	
			   if((Trump == LeadSuit)&&(Value < 8))
			   {
		   	   	PlaySw = 1;
	                  break;
			   }
			   // someone already trumped so over trump	
			   else if(TrumpSwitch == 1)
			   {
				if((Value > TopCard)&&(Suit == Trump))
    	            	{
		   	   	   PlaySw = 1;
	                     break;
		      	}
			   }
			   // noone has trumped so trump
			   else if((TrumpSwitch == 0)&&(Suit == Trump))
    	               {
		   	      PlaySw = 1;
	                  break;
			   }
			}
		      else if(!wantTrick)
			{ 
			   // Trump is led so dump a high card 	
			   if((Trump == LeadSuit)&&(Value > 9))
			   { 
			      PlaySw = 1;
	                  break;
			   }	
			   // some one has trumped the trick so play high	
			   else if(TrumpSwitch == 1)
			   {
				 if(((Suit != Trump)&&(Value > 9))||((Suit == Trump)&&(Value < TopCard)))
				 {
			          PlaySw = 1;
	                      break;
				 }
			   }
			   // No one has trumped so under play
			   else if((TrumpSwitch==0)&&(Suit !=Trump)&&(Value < TopCard))
			   {	 
			      PlaySw = 1;
	                  break;
			   }	
			} 
	         }
	      } 
		if(PlaySw == 0)
	      {
	         for(theCard = 0; theCard < HowMany; theCard++)
               {
    	            if(players[x].Hand[theCard].Display) 
		         break;
	         }
		}	
	   } 
	   // evaluate top card
	  int Value = players[x].Hand[theCard].Value;
	  int Suit = players[x].Hand[theCard].Suit;
	  // if some else trumped already
	  if(TrumpSwitch == 1) 
	  {
            if((Suit == Trump)&&(Value > TopCard))
		   SetTop(Value, x);
	  }
	  else if(TrumpSwitch == 0) 
	  {	
	     // if this player just trumped
	     if((Suit == Trump)&&(LeadSuit != Trump))
		{
		   TrumpSwitch = 1;
		   SetTop(Value, x);
	      }
		else if((Value > TopCard)&&(Suit == LeadSuit))
		   SetTop(Value, x);
	   }	
	} 
	int TempX;
	int TempY;
	if(x == 0) 
	{
	   TempX = 160;
	   TempY = 160;
	}
	else if(x == 1) 
	{
	   TempX = MYHANDX;
	   TempY = 120;
	}
	else
	{
	   TempX = 300;
	   TempY = 160;
	}
	g.drawImage(players[x].Hand[theCard].pic, TempX, TempY, TempX + CARDH, TempY + CARDH, 0, 0, 100, 100, this);
	players[x].Hand[theCard].Display = false;
   }

   private synchronized void SetTop(int Value, int Who)
   {
	 TopCard = Value;
	 TopPlayer = Who; 
   }			

   private synchronized void DetermineWinner(Graphics g)
   {
      theLead = TopPlayer;
	HowManyLeft -= 1; 
	TrumpSwitch = 0;
	IWent = 0;
	StartPlay = theLead;
      StopPlay = 3;
	// add to tricks
	players[TopPlayer].Tricks += 1;

	// repaint
	repaint();

	// track who leads next and start the play thread
	if(HowManyLeft > 0)
	{
	   if(theLead == 3)
		ILead();
         else if(theLead != 3)
	   {	
	      trick = new Thread(this);
	      trick.start();
	   }
	}
	else if(HowManyLeft == 0)
	{
	   // End of the hand - Calculate the score
	   for(int i = 0; i < 4; i++)
	   {
	      if(players[i].Bid == players[i].Tricks)
		{
		   players[i].Score += (players[i].Bid + 5);
		}
		else
		{
		   players[i].Score -= Math.abs(players[i].Bid-players[i].Tricks);
		}
	   }
	   SortLeader();		
	}
   }

   private synchronized void SortLeader()
   {
	int HoldWho = 10;
	int Who = 10;
	int LastOne = 1000;
	int HoldHigh = -100;
	for(int x = 0; x < 4; x++)
	{
	   for(int i = 0; i < 4; i++)
	   {
		int Score = players[i].Score; 
		if((Score > HoldHigh)&&(Score <= LastOne)&&(i != HoldWho))
		{
		   HoldHigh = Score;
		   Who = i;
		}
	   }
	   LastOne = HoldHigh;
	   Leaders[x] = Who;
	   HoldHigh = -100;
	   HoldWho = Who;
	}
  }
			 	
// The user has clicked the applet. Figure out where and what they want.
   public void mouseReleased(MouseEvent e)
   {	
	int MEx = e.getX();
	int MEy = e.getY();
	boolean haveSuit = false;
	Graphics g = getGraphics();

	if((Deal.contains(MEx, MEy))&&(HowManyLeft == 0))
	{
     	   Trump = 4;
     	   TrumpSwitch = 0;
	   IWent = 0;
	   FirstTime = 1;
	   Declare = "";
	   CantBid = 10;	
   	   TtlBid = 0;
	   FirstToBid = (FirstToBid == 3) ? 0 : FirstToBid += 1;
	   if(HowMany == 14)
	   {
		Direction = 0;
	      HowMany = 13;
	   }
	   else if(HowMany == 1)
	   {
		Direction = 1; // going back up
	      HowMany = 2;
	   }
	   else
	   {
	      HowMany = (Direction == 0)? HowMany -= 1 : HowMany += 1;
 	   }
	   HowManyLeft = HowMany;
	   DealCards();
	   if(FirstToBid == 3)
 		GetMyBid(0);
	   else
 		GetBid();
	}

	// check if I have the suit lead
	for(int j = 0; j < HowMany; j++)
	{	
	   if((players[3].Hand[j].Suit == LeadSuit)&&	
	      (players[3].Hand[j].Display == true)) 
            haveSuit = true;
	}
	int TempX = MYHANDX - (6 * HowManyLeft);
	int TempY = 320;
	for(int i = 0; i < HowMany; i++)
	{
	   if((MEx > TempX) && (MEx < TempX + 15) && (MEy > TempY) && (MEy < TempY + CARDH)&&(players[3].Hand[i].Display)&&(IGo == 1))
	   {
		int Suit = players[3].Hand[i].Suit;
		int Value = players[3].Hand[i].Value;
	      if(theLead == 3)
		{
	   	   g.clearRect(SCOREX, 200, 112, 27);
		   LeadSuit = Suit;
               SetTop(Value, 3);
		}
		else if(theLead != 3)
		{
	         if(haveSuit)
	         {
			// if no trump has been played or trump is lead suit
			if((TrumpSwitch == 0)&&(Suit == LeadSuit))
		      {
		         // if I played lead suit see if its higher
		         if(Value > TopCard) 
              	      SetTop(Value, 3);
			}
			// I have the lead suit but didn't play it-PROBLEM
			else if(Suit != LeadSuit)
			{
			   break;		
			}
		   }
              // if I played trump suit 
	         else if((!haveSuit)&&(Suit == Trump))
		   {
   		      // and so did someone else see if mine is higher
			if((TrumpSwitch == 1)&&(Value > TopCard))
              	   SetTop(Value, 3);
			// and no one else did mine is higher
			else if(TrumpSwitch == 0)
			{
			   TrumpSwitch = 1;
              	   SetTop(Value, 3);
			}
   		   }	
		}
		g.drawImage(players[3].Hand[i].pic, MYHANDX, 200, MYHANDX + CARDH, 280, 0, 0, 100, 100, this);
		players[3].Hand[i].Display = false;
		PaintMine(g);
	      StartPlay = 0;
            StopPlay = theLead;
		IWent = 1;
		trick = new Thread(this);
	      trick.start();
		break;
	   }
	   TempX += 15;
	}
   }

   public void mousePressed(MouseEvent e) {}

   public void mouseClicked(MouseEvent e) {}

   public void mouseEntered(MouseEvent e){}

   public void mouseExited(MouseEvent e) {}

   public void keyPressed(KeyEvent e)
   {
	Graphics g = getGraphics();
	int key = e.getKeyCode();
	int theBid; 
	// the user has pressed 0 - 9 
	if((key > 47)&&(key < 58))
	{
	   theBid = key - 48;
	   int MyBidY = 120;
	   if((theBid != CantBid)&&(theBid < HowMany + 1))
	   {
	   	players[3].Bid = theBid;
	      TtlBid += theBid;
		g.clearRect(SCOREX, MyBidY, SCOREW + 3, SCOREH + 3);
	      PaintBoxes(g);
		FinishBid(FirstToBid);
	      PaintBoxes(g);
	      Declare = (TtlBid > HowMany)? "OverBid" : "UnderBid";	
            PaintBidDisplay(g);
      	WhoLeads();
	   }
	}			
   }

   public void keyReleased(KeyEvent e) {}

   public void keyTyped(KeyEvent e) {}

   public void destroy()
   {
      removeMouseListener(this);
      removeKeyListener(this);
   }
   
   public String getAppletInfo() 
   {
	return "Oh Hell by Jay Lipp";
   }

   class Card
   {
      // 0=Clubs, 1=Diamonds, 3=Hearts, 2=Spades
	// 11=Jack, 12=Queen, 13=King 14=Ace

	public int Value;
	public int TtlValue;
	public int Suit;
	public String Name;
	public Image pic; 
	public boolean Display;
	private String theSuit;

	public Card(int x)
	{
	   Display = true;
	   Suit = x % 4;
	   if(Suit == 0)	
	   	theSuit = "C";
	   else if(Suit == 1)	
	   	theSuit = "D";
	   else if(Suit == 2)	
	   	theSuit = "S";
	   else
	   	theSuit = "H";
	   Value = x % 13;
 	   if(Value == 0)
		Value = 13;
 	   if(Value == 1)
		Value = 14;
	   TtlValue = (Suit * 13) + Value;
 	   Name = String.valueOf(Value) + theSuit;
	   pic = getImage(getCodeBase(),"Images/" + Name + ".gif"); 
	  // pic = pic.getScaledInstance(50, 80, Image.SCALE_FAST);
	}
   } 	

   class Player
   {
	public int Bid;
	public int Tricks;
	public int Score;
	public String Name;
	public Card Hand[] = new Card[13]; 

	public Player(String name)
	{
	   Bid = 0;
	   Tricks = 0;
	   Score = 0;
	   Name = new String(name);			
	}

	public void SortHand(int Amount)
	{
	   Card Temp;
	   for(int x = 0; x < Amount; x++)
	   {
		int min = x;
		for(int i = x; i < Amount; i++)	
		{
		   if(Hand[i].TtlValue < Hand[min].TtlValue)
			min = i;
		}
		Temp = Hand[x];
		Hand[x] = Hand[min];
		Hand[min] = Temp;
	   } 	
	} 

	public float EvaluateHand(int Amount, int Trump)
	{
	   float Strength = 0;
	   int Club = 0;
	   int Heart = 0;
	   int Spade = 0;
	   int Diamond = 0;	
	   for(int x = 0; x < Amount; x++)
	   {
	      // evaluate card strength	
	      if(Hand[x].Value == 0)
		   Strength += 1;
		if(Hand[x].Value == 13)
		   Strength += 0.9; 
		if(Hand[x].Value == 12)
		   Strength += 0.8;
		if(Hand[x].Value == 11)
		   Strength += 0.7;
	      // evaluate suit strength	
  	      if(Hand[x].Suit == 0)
		   Club += 1;
		if(Hand[x].Suit == 1)
		   Diamond += 1;
		if(Hand[x].Suit == 2)
		   Spade += 1;
		if(Hand[x].Suit == 3)
		   Heart += 1;
	   }
	   // give 1/2 point for each suit over average distribution
	   float temp = (float)Amount;
	   float benchmark = temp / 4;
	   if(Trump == 4)
	   {			
	      if(Club > benchmark)
		   Strength += (Club - benchmark) * 0.5;
	      if(Diamond > benchmark)
		   Strength += (Diamond - benchmark) * 0.5;
	      if(Spade > benchmark)
		   Strength += (Spade - benchmark) * 0.5;
	      if(Heart > benchmark)
		   Strength += (Heart - benchmark) * 0.5;
	   }
	   else if(Trump < 4)
	   {
	      if((Trump == 0)&&(Club > benchmark))
		   Strength += (Club - benchmark) * 1.5;
	      if((Trump == 1)&&(Diamond > benchmark))
		   Strength += (Diamond - benchmark) * 1.5;
	      if((Trump == 2)&&(Heart > benchmark))
		   Strength += (Heart - benchmark) * 1.5;
	      if((Trump == 3)&&(Spade > benchmark))
		   Strength += (Spade - benchmark) * 1.5;
	   }
	   return Strength;
	}  	
   } 			
}
