/*
	Farkle.java - Cory J Goldfuss - September 25, 2000
	(paint method and draw die method previously written by John Estell 
	from RollDice5.java)
	Added a new GUI and a new way to handle the buttons using boolean array.
	------------------------------------------------------------------------------
	October 10, 2000 - Added scoring rules and highestScore() method to calculate the highest score
	possible and testGameOver() method to see if a high score was even possible.
        ------------------------------------------------------------------------------
        October 21, 2000 - Added ability to score only dice being held.  Program should now
        function according to set rules.....assuming that the user is not a dead gnat.
        ------------------------------------------------------------------------------
        November 3, 2000 - Finished game......now it should really work...assuming the user
        doesn't cheat....how do you cheat?.....well it involves you figuring it out because
        I'm not going to divulge that information. :)
 */

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


public class Farkle extends Applet implements ActionListener
{
    // define constants
    private boolean  buttons[];
    private int      die[];
    private int      scoredie[];
    private boolean  beenscored[]; //keep track of scored die
    private int      buttoncount = 0;
    public final int numDice = 6;
    private int      turnsleft = 3;
    private int      totalscore = 0;
    private int      currentscore = 0;
    public final int onespot = 100;
    public final int fivespot = 50;
    public final int each = 1500;
    public final int threeonespot = 1000;
    public final int threethreespot = 300;
    public final int threetwospot = 200;
    public final int threefourspot = 400;
    public final int threefivespot = 500;
    public final int threesixspot = 600;
    public final int threepairs = 500;
    /* Four of a kind */
    public final int onefourkind = 2 * threeonespot;
    public final int twofourkind = 2 * threetwospot;
    public final int threefourkind = 2 * threethreespot;
    public final int fourfourkind = 2 * threefourspot;
    public final int fivefourkind = 2 * threefivespot;
    public final int sixfourkind = 2 * threesixspot;
    /* Five of a kind */
    public final int onefivekind = 4 * threeonespot;
    public final int twofivekind = 4 * threetwospot;
    public final int threefivekind = 4 * threethreespot;
    public final int fourfivekind = 4 * threefourspot;
    public final int fivefivekind = 4 * threefivespot;
    public final int sixfivekind = 4 * threesixspot;
    /* Six of a kind */
    public final int onesixkind = 8 * threeonespot;
    public final int twosixkind = 8 * threetwospot;
    public final int threesixkind = 8 * threethreespot;
    public final int foursixkind = 8 * threefourspot;
    public final int fivesixkind = 8 * threefivespot;
    public final int sixsixkind = 8 * threesixspot;
      
	public void init()
	{
	    
	    	    
		// Take out this line if you don't use symantec.itools.net.RelativeURL or symantec.itools.awt.util.StatusScroller
		//symantec.itools.lang.Context.setApplet(this);
	
		// This code is automatically generated by Visual Cafe when you add
		// components to the visual environment. It instantiates and initializes
		// the components. To modify the code, only use code syntax that matches
		// what Visual Cafe can generate, or Visual Cafe may be unable to back
		// parse your Java file into its visual environment.
		//{{INIT_CONTROLS
		setLayout(null);
		setBackground(java.awt.Color.white);
		setSize(525,344);
		holdBtn0.setLabel("Hold");
		add(holdBtn0);
		holdBtn0.setBackground(java.awt.Color.orange);
		holdBtn0.setBounds(36,72,62,21);
		holdBtn1.setLabel("Hold");
		add(holdBtn1);
		holdBtn1.setBackground(java.awt.Color.orange);
		holdBtn1.setBounds(108,72,62,21);
		holdBtn2.setLabel("Hold");
		add(holdBtn2);
		holdBtn2.setBackground(java.awt.Color.orange);
		holdBtn2.setBounds(180,72,62,21);
		holdBtn3.setLabel("Hold");
		add(holdBtn3);
		holdBtn3.setBackground(java.awt.Color.orange);
		holdBtn3.setBounds(252,72,62,21);
		holdBtn4.setLabel("Hold");
		add(holdBtn4);
		holdBtn4.setBackground(java.awt.Color.orange);
		holdBtn4.setBounds(324,72,62,21);
		holdBtn5.setLabel("Hold");
		add(holdBtn5);
		holdBtn5.setBackground(java.awt.Color.orange);
		holdBtn5.setBounds(396,72,62,21);
		rollBtn.setLabel("Roll");
		add(rollBtn);
		rollBtn.setBackground(java.awt.Color.orange);
		rollBtn.setBounds(216,120,62,24);
		scoreplayBtn.setLabel("Score");
		add(scoreplayBtn);
		scoreplayBtn.setBackground(java.awt.Color.orange);
		scoreplayBtn.setBounds(216,156,62,24);
		totalscoreLbl.setText("Total Score");
		totalscoreLbl.setAlignment(java.awt.Label.CENTER);
		add(totalscoreLbl);
		totalscoreLbl.setBackground(java.awt.Color.orange);
		totalscoreLbl.setBounds(84,192,72,24);
		crntscoreLbl.setText("Current Score");
		crntscoreLbl.setAlignment(java.awt.Label.CENTER);
		add(crntscoreLbl);
		crntscoreLbl.setBackground(java.awt.Color.orange);
		crntscoreLbl.setBounds(360,192,84,24);
		turnLbl.setText("Turns Left");
		turnLbl.setAlignment(java.awt.Label.CENTER);
		add(turnLbl);
		turnLbl.setBackground(java.awt.Color.orange);
		turnLbl.setBounds(216,312,72,24);
		turntxtLbl.setText("3");
		turntxtLbl.setAlignment(java.awt.Label.CENTER);
		add(turntxtLbl);
		turntxtLbl.setFont(new Font("SansSerif", Font.PLAIN, 14));
		turntxtLbl.setBounds(216,288,72,24);
		totalscoretxtLbl.setText("0");
		totalscoretxtLbl.setAlignment(java.awt.Label.CENTER);
		add(totalscoretxtLbl);
		totalscoretxtLbl.setFont(new Font("SansSerif", Font.PLAIN, 14));
		totalscoretxtLbl.setBounds(84,216,72,24);
		crntscoretxtLbl.setText("0");
		crntscoretxtLbl.setAlignment(java.awt.Label.CENTER);
		add(crntscoretxtLbl);
		crntscoretxtLbl.setFont(new Font("SansSerif", Font.PLAIN, 14));
		crntscoretxtLbl.setBounds(360,216,72,24);
		newgameBtn.setLabel("New Game ?");
		add(newgameBtn);
		newgameBtn.setBackground(java.awt.Color.black);
		newgameBtn.setForeground(java.awt.Color.white);
		newgameBtn.setBounds(204,192,87,32);
		newgameBtn.setVisible(false);
		titleLbl.setText("Farkle 2000");
		titleLbl.setAlignment(java.awt.Label.CENTER);
		add(titleLbl);
		titleLbl.setFont(new Font("SansSerif", Font.BOLD, 36));
		titleLbl.setBounds(120,240,264,36);
		farkledleftLbl.setText("Farkle! Farkle!");
		farkledleftLbl.setAlignment(java.awt.Label.CENTER);
		add(farkledleftLbl);
		farkledleftLbl.setBackground(java.awt.Color.red);
		farkledleftLbl.setFont(new Font("SansSerif", Font.PLAIN, 24));
		farkledleftLbl.setBounds(48,120,168,60);
		farkledleftLbl.setVisible(false);
		farkledrightLbl.setText("Farkle! Farkle!");
		farkledrightLbl.setAlignment(java.awt.Label.CENTER);
		add(farkledrightLbl);
		farkledrightLbl.setBackground(java.awt.Color.red);
		farkledrightLbl.setFont(new Font("SansSerif", Font.PLAIN, 24));
		farkledrightLbl.setBounds(276,120,168,60);
		farkledrightLbl.setVisible(false);
		//}}
		rollBtn.addActionListener( this );
		holdBtn0.addActionListener( this );
		holdBtn1.addActionListener( this );
		holdBtn2.addActionListener( this );
		holdBtn3.addActionListener( this );
		holdBtn4.addActionListener( this );
		holdBtn5.addActionListener( this );
		scoreplayBtn.addActionListener( this );
		newgameBtn.addActionListener( this );
		die = new int[ numDice ];
		scoredie = new int [ numDice ];
		buttons = new boolean[ numDice ];
		beenscored = new boolean[ numDice ];
		
	}
	
	//{{DECLARE_CONTROLS
	java.awt.Button holdBtn0 = new java.awt.Button();
	java.awt.Button holdBtn1 = new java.awt.Button();
	java.awt.Button holdBtn2 = new java.awt.Button();
	java.awt.Button holdBtn3 = new java.awt.Button();
	java.awt.Button holdBtn4 = new java.awt.Button();
	java.awt.Button holdBtn5 = new java.awt.Button();
	java.awt.Button rollBtn = new java.awt.Button();
	java.awt.Button scoreplayBtn = new java.awt.Button();
	java.awt.Label totalscoreLbl = new java.awt.Label();
	java.awt.Label crntscoreLbl = new java.awt.Label();
	java.awt.Label turnLbl = new java.awt.Label();
	java.awt.Label turntxtLbl = new java.awt.Label();
	java.awt.Label totalscoretxtLbl = new java.awt.Label();
	java.awt.Label crntscoretxtLbl = new java.awt.Label();
	java.awt.Button newgameBtn = new java.awt.Button();
	java.awt.Label titleLbl = new java.awt.Label();
	java.awt.Label farkledleftLbl = new java.awt.Label();
	java.awt.Label farkledrightLbl = new java.awt.Label();
	//}}
	
	
	public void actionPerformed( ActionEvent e ){
    
    
    if (e.getSource() == rollBtn){
       holdBtn0.setEnabled(true);  //enable after rerolling
       holdBtn1.setEnabled(true);
       holdBtn2.setEnabled(true);
       holdBtn3.setEnabled(true);
       holdBtn4.setEnabled(true);
       holdBtn5.setEnabled(true);
       scoreplayBtn.setEnabled(true);
       /* Remove Farkled messages */
       farkledleftLbl.setVisible(false);
       farkledrightLbl.setVisible(false);
       
       
       if (buttoncount == 6){//made it through all die successfully
            holdBtn0.setLabel("Hold");
            holdBtn1.setLabel("Hold");
            holdBtn2.setLabel("Hold");
            holdBtn3.setLabel("Hold");
            holdBtn4.setLabel("Hold");
            holdBtn5.setLabel("Hold");
            holdBtn0.setVisible(true);
            holdBtn1.setVisible(true);
            holdBtn2.setVisible(true);
            holdBtn3.setVisible(true);
            holdBtn4.setVisible(true);
            holdBtn5.setVisible(true);
            totalscore += currentscore;
            buttoncount = 0;
            for (int i=0; i < numDice; i++){
                scoredie[i] = 0;
                
                buttons[i] = false;
                beenscored[i] = false;
            }
        }
      
       
        for (int i=0; i < numDice; i++){ // redraw unheld die
            if (buttons[i] == true){
                continue;
            }
            die[i] = 1 + (int) ( Math.random() * 6 );
            
        }
        
        
        for (int i=0; i < numDice; i++){
            if (buttons[i] == false) 
                continue;
            if (buttons[i] == true && beenscored[i] == false){
                scoredie[i] = die[i];//pass only dice that are to be scored
                beenscored[i] = true;
            }
        }
        
        if (testGameOver(die) == true){//Farkle
           turnsleft--;
           turntxtLbl.setText(String.valueOf(turnsleft));
           currentscore = 0;
           crntscoretxtLbl.setText(String.valueOf(currentscore));
           for (int i=0; i < numDice; i++){ // Reset arrays 
                buttons[i] = false;
                beenscored[i] = false;
                scoredie[i] = 0;
                }
           holdBtn0.setEnabled(false);  
           holdBtn1.setEnabled(false);
           holdBtn2.setEnabled(false);
           holdBtn3.setEnabled(false);
           holdBtn4.setEnabled(false);
           holdBtn5.setEnabled(false);
           scoreplayBtn.setEnabled(false);
           holdBtn0.setVisible(true);
           holdBtn1.setVisible(true);
           holdBtn2.setVisible(true);
           holdBtn3.setVisible(true);
           holdBtn4.setVisible(true);
           holdBtn5.setVisible(true);
           holdBtn0.setLabel("Hold");
           holdBtn1.setLabel("Hold");
           holdBtn2.setLabel("Hold");
           holdBtn3.setLabel("Hold");
           holdBtn4.setLabel("Hold");
           holdBtn5.setLabel("Hold"); 
           farkledleftLbl.setVisible(true);
           farkledrightLbl.setVisible(true);
        }
        
        // unless farkle.....then add score
        currentscore += highScore(scoredie);
        crntscoretxtLbl.setText(String.valueOf(currentscore));
        
        if (buttons[0] == true){
            die[0] = 0; //needed zero to test for farkle
            holdBtn0.setVisible(false);
            buttoncount++;
        }
        if (buttons[1] == true){
            holdBtn1.setVisible(false);
            die[1] = 0;
            buttoncount++;
        }
        if (buttons[2] == true){
            holdBtn2.setVisible(false);
            die[2] = 0;
            buttoncount++;
        }
        if (buttons[3] == true){
            holdBtn3.setVisible(false);
            die[3] = 0;
            buttoncount++;
        }
        if (buttons[4] == true){
            holdBtn4.setVisible(false);
            die[4] = 0;
            buttoncount++;
        }
        if (buttons[5] == true){
            holdBtn5.setVisible(false);
            die[5] = 0;
            buttoncount++;
        }
        
        for (int i=0; i < numDice; i++){ // reset before rerolling
            scoredie[i] = 0;
        }
        /* no more chances */
        if (turnsleft == 0){ 
            rollBtn.setEnabled(false);
            holdBtn0.setEnabled(false);
            holdBtn1.setEnabled(false);
            holdBtn2.setEnabled(false);
            holdBtn3.setEnabled(false);
            holdBtn4.setEnabled(false);
            holdBtn5.setEnabled(false);
            holdBtn0.setVisible(true);
            holdBtn1.setVisible(true);
            holdBtn2.setVisible(true);
            holdBtn3.setVisible(true);
            holdBtn4.setVisible(true);
            holdBtn5.setVisible(true);
            scoreplayBtn.setEnabled(false);
            newgameBtn.setVisible(true);
        }
        
    }
        
        
        
        
    
    
    if (e.getSource() == newgameBtn){
        gameReset();
    }
            
            
    if (e.getSource() == scoreplayBtn){
        for (int i=0; i < numDice; i++){ // Reset arrays 
            buttons[i] = false;
            beenscored[i] = false;
            scoredie[i] = 0;
        }
        holdBtn0.setVisible(true);
        holdBtn1.setVisible(true);
        holdBtn2.setVisible(true);
        holdBtn3.setVisible(true);
        holdBtn4.setVisible(true);
        holdBtn5.setVisible(true);
        holdBtn0.setLabel("Hold");
        holdBtn1.setLabel("Hold");
        holdBtn2.setLabel("Hold");
        holdBtn3.setLabel("Hold");
        holdBtn4.setLabel("Hold");
        holdBtn5.setLabel("Hold");
        scoreplayBtn.setEnabled(false);
        turnsleft--;
        turntxtLbl.setText(String.valueOf(turnsleft));
        totalscore += currentscore; // add current score to total
        currentscore = 0; // reset current to start again
        totalscoretxtLbl.setText(String.valueOf(totalscore));
             
    }
        
        
    
    if (e.getSource() == holdBtn0){
        if (buttons[0]== false){
            holdBtn0.setLabel("UnHold");
            buttons[0] = true;
           
        }
        else{
            holdBtn0.setLabel("Hold");
            buttons[0] = false;
            beenscored[0] = false;
        }
    }
    
    if (e.getSource() == holdBtn1){
        if (buttons[1] == false){
            holdBtn1.setLabel("UnHold");
            buttons[1] = true;
            
        }
        else{
            holdBtn1.setLabel("Hold");
            buttons[1] = false;
            beenscored[1] = false;
        }
    }
    
    if (e.getSource() == holdBtn2){
        if (buttons[2] == false){
            holdBtn2.setLabel("UnHold");
            buttons[2] = true;
           
        }
        else{
            holdBtn2.setLabel("Hold");
            buttons[2] = false;
            beenscored[2] = false;
        }
    }
    
    if (e.getSource() == holdBtn3){
        if (buttons[3] == false){
            holdBtn3.setLabel("UnHold");
            buttons[3] = true;
           
        }
        else{
            holdBtn3.setLabel("Hold");
            buttons[3] = false;
            beenscored[3] = false;
        }
    }
    
    if (e.getSource() == holdBtn4){
        if (buttons[4] == false){
            holdBtn4.setLabel("UnHold");
            buttons[4] = true;
            
        }
        else{
            holdBtn4.setLabel("Hold");
            buttons[4] = false;
            beenscored[4] = false;
        }
    }
    
    if (e.getSource() == holdBtn5){
        if (buttons[5] == false){
            holdBtn5.setLabel("UnHold");
            buttons[5] = true;
           
        }
        else{
            holdBtn5.setLabel("Hold");
            buttons[5] = false;
            beenscored[5] = false;
        }
    }
    
    repaint();
   }
    
    
    
        
    
    
    /* Reset Game */
   public void gameReset(){
        turnsleft = 3;
        totalscore = 0;
        currentscore = 0;
        buttoncount = 0;
        crntscoretxtLbl.setText("0");
        totalscoretxtLbl.setText("0");
        turntxtLbl.setText("3");
        newgameBtn.setVisible(false);
        rollBtn.setEnabled(true);
        
        
        for (int i=0; i < numDice; i++){ // Reset arrays 
            buttons[i] = false;
            beenscored[i] = false;
            scoredie[i] = 0;
        }
       holdBtn0.setLabel("Hold");
       holdBtn1.setLabel("Hold");
       holdBtn2.setLabel("Hold");
       holdBtn3.setLabel("Hold");
       holdBtn4.setLabel("Hold");
       holdBtn5.setLabel("Hold");
   }
     
    
   public void paint( Graphics g ) {
        int DIST = 72;
        for ( int i = 0; i < numDice; i++ ) {
            drawDie( g, die[i], 50 + DIST * i, 35 );
        }
    }
            

    // drawDie - draws a die face with the provided value showing
    //           at the specified upper-left X-Y coordinate
    public void drawDie( Graphics gr, int die, int x1, int y1 ) {
        int x = x1 + 4, y = y1 + 4;  // internal offset into die face
        int DIA = 7;                 // diameter of die "point" circles
        int HALF = 9, FULL = 18;     // offsets for positioning die points

        gr.drawRoundRect( x1, y1, 33, 33, 5, 5 );  // draw border
        switch (die) {
            case 1:
                    gr.fillOval( x + HALF, y + HALF, DIA, DIA);
                    break;
            case 2:
                    gr.fillOval( x, y, DIA, DIA);
                    gr.fillOval( x + FULL, y + FULL, DIA, DIA);
                    break;
            case 3:
                    gr.fillOval( x, y, DIA, DIA);
                    gr.fillOval( x + HALF, y + HALF, DIA, DIA);
                    gr.fillOval( x + FULL, y + FULL, DIA, DIA);
                    break;
            case 4:
                    gr.fillOval( x, y, DIA, DIA);
                    gr.fillOval( x, y + FULL, DIA, DIA);
                    gr.fillOval( x + FULL, y, DIA, DIA);
                    gr.fillOval( x + FULL, y + FULL, DIA, DIA);
                    break;
            case 5:
                    gr.fillOval( x, y, DIA, DIA);
                    gr.fillOval( x, y + FULL, DIA, DIA);
                    gr.fillOval( x + FULL, y, DIA, DIA);
                    gr.fillOval( x + HALF, y + HALF, DIA, DIA);
                    gr.fillOval( x + FULL, y + FULL, DIA, DIA);
                    break;
            case 6:
                    gr.fillOval( x, y, DIA, DIA);
                    gr.fillOval( x, y + HALF, DIA, DIA);
                    gr.fillOval( x, y + FULL, DIA, DIA);
                    gr.fillOval( x + FULL, y, DIA, DIA);
                    gr.fillOval( x + FULL, y + HALF, DIA, DIA);
                    gr.fillOval( x + FULL, y + FULL, DIA, DIA);
                    break;
        } // end switch
    }     // end method
    
    
   /* Method for scoring dice after roll */
   
   private int highScore( int dice[] ){
      int totalscore = 0;
      
      
    /* Array to hold quantity of a certain spotted die */
      int spots[];
      spots = new int [6];
      for (int i = 0; i < 6; i++){  // Init to zero
        spots[i] = 0;
      }
      
                 
      for (int i = 0; i < numDice; i++){ // Count up quantity of die
        
        if (dice[i] == 1){
            spots[0] += 1;
        }
        if (dice[i] == 2){
            spots[1] += 1;
        }
        if (dice[i] == 3){
            spots[2] += 1;
        }
        if (dice[i] == 4){
            spots[3] += 1;
        }
        if (dice[i] == 5){
            spots[4] += 1;
        }
        if (dice[i] == 6){
            spots[5] += 1;
        }
      }
      /* Scoring  Note: spots array starts at zero which is acutally the number of
      one spots....and so on....spots[4] holds the number of five spots...etc*/
      int pairs = 0;
      
      if (spots[0] == 1 ){ // one of one
        totalscore += onespot;
      }
      if (spots[0] == 2){// two ones
        totalscore += 2 * onespot;
        pairs++;
      }
      if (spots[1] == 2){ // pair of twos
        pairs++;
      }
      if (spots[2] == 2){ // pair of threes
        pairs++;
      }
      if (spots[3] == 2){ // pair of fours
        pairs++;
      }
      if (spots[5] == 2){ // pair of sixes
        pairs++;
      }
      if (spots[0] == 3){ // three of one
        totalscore += threeonespot;
      }
      if (spots[4] == 1){ // one of five
        totalscore += fivespot;
      }
      if (spots[4] == 2){ // two fives
        totalscore += 2 * fivespot;
        pairs++;
      }
      if (spots[1] == 3){ // three of two
        totalscore += threetwospot;
      }
      if (spots[2] == 3){ // three of three
        totalscore += threethreespot;
      }
      if (spots[3] == 3){ // three of four
        totalscore += threefourspot;
      }
      if (spots[4] == 3){ // three of five
        totalscore += threefivespot;
      }
      if (spots[5] == 3){ //three of six
        totalscore += threesixspot;
      }
      if (spots[0] == 1 && spots[1] == 1 && spots[2] == 1 && spots[3] == 1 && spots[4] == 1 && spots[5] == 1){ // one of each
        totalscore += each;
      }
      if (pairs == 3){ // 3 pairs
        totalscore += threepairs;
      }
      
      if (spots[0] == 4){ //four of one
        totalscore += onefourkind;
      }
      if (spots[1] == 4){ //four of two
        totalscore += twofourkind;
      }
      if (spots[2] == 4){ //four of three
        totalscore += threefourkind;
      }
      if (spots[3] == 4){ //four of four
        totalscore += fourfourkind;
      }
      if (spots[4] == 4){ //four of five 
        totalscore += fivefourkind;
      }
      if (spots[5] == 4){ //four of six
        totalscore += sixfourkind;
      }
      
      if (spots[0] == 5){ //five of one
        totalscore += onefivekind;
      }
      if (spots[1] == 5){ //five of two
        totalscore += twofivekind;
      }
      if (spots[2] == 5){ //five of three
        totalscore += threefivekind;
      }
      if (spots[3] == 5){ //five of four
        totalscore += fourfivekind;
      }
      if (spots[4] == 5){ //five of five
        totalscore += fivefivekind;
      }
      if (spots[5] == 5){ //five of six
        totalscore += sixfivekind;
      }
      if (spots[0] == 6){ //six of one
        totalscore += onesixkind;
      }
      if (spots[1] == 6){ //six of two
        totalscore += twosixkind;
      }
      if (spots[2] == 6){ //six of three
        totalscore += threesixkind;
      }
      if (spots[3] == 6){ //six of four
        totalscore += foursixkind;
      }
      if (spots[4] == 6){ //six of five
        totalscore += fivesixkind;
      }
      if (spots[5] == 6){ //six of six
        totalscore += sixsixkind;
      }
      
    return totalscore;
   }    
     
   

      
  /* Test for game over */
  private boolean testGameOver( int die[] ){
    
    int score = highScore(die);
    
    if (score == 0){
        return true;
    }
    else {
        return false;
    }
  }
    
}// applet