import java.util.*;
import java.io.*;
import randnum;
import policy;
import yatzee;
import holddata;

//******************************************************
// CLASS: Game
//******************************************************
// Simulation of yatzee game for 1 person
// 
//******************************************************
class game extends Thread{
	state dice_state;
		// previous state in turn
	state dice_action;
		// previous action
	state new_dice;
		// new throw of dice
	boolean category[][];
		// if yathzee categories are filled 
	int turn;
		// 1 to 3 turn
	int num_of_players;
		// always one player
	int player;
	int num_of_categories;
		// one or four categories.
	randnum r;
		// make rundom dice number
	policy learn_policy;
		// the SARSA algorithm
	int round_count[];
		// for statistics
	int score_count[];
		// for statistics		
	boolean one_game_end;
	//holddata _data;

	public game()
		{
			//_data = data;
			r = new randnum();
			num_of_players = 1;
			num_of_categories = 4;
			learn_policy = new policy((int)5,(float)1,(float)0.4);
			category = new boolean[num_of_players][num_of_categories];
			round_count = new int[num_of_players];			
			score_count = new int[num_of_players];
		}// of game
		

	public void run()
   {
      play();                                      
   }// of run

	public void play() 
		{
			PrintWriter output;  
			learn_policy.load();
			try 
			{
				output = new PrintWriter( new FileOutputStream("summery.log") );
				for ( int j=0;j<=100;j++)
				{		
						int k = 0;
						// do trial games
						for ( k=0; k<1000; k++)
						{
							System.out.println("Game: play..");						
							for(int i=0;i<num_of_players;i++)
								one_game(i);
						}
						// print statisrtics to file
						for(int i=0;i<num_of_players;i++)
						{	
								String line = new String("turn ");
								line += j;
								line += ": round[";
								line += (round_count[i]/k);
								line += "], score[";
								line += (score_count[i]/k);
								line += "].";
								output.println(line);
								output.flush();
								round_count[i] = 0;
								score_count[i] = 0;
						}
						learn_policy.save();
				}
			}
			catch  ( IOException e )
		  {
				System.err.println( "File exception\n" + e.toString() );
			}	
	}// of play

		
	private void one_game( int who_plays ) 
		// play till all categories scored
		{
			// initialize values
			player = who_plays;
			System.out.println("Game:one game..");
			one_game_end = false;			
			for ( int j=0; j< category[player].length; j++ ) 
						category[player][j] = false;
					
			while (true) 
				{
					int i;
					if ( ! one_game_end ) 
						{
							dice_action = new state();
							dice_state = new state();
							round(player);	
							round_count[player]++;
						}		
					else
						break;				
				}
		}// of one game
	
	
	private void round(int who_plays) 
		// play one round
		{
			dice_state = new state();
			for (turn=0;turn<3;turn++) 
				{
					sleep 2 seconds
					try {
						Thread.currentThread().sleep(2000);
						}
					catch ( InterruptedException e) {}
					
					int new_dice_num = 5-dice_state.numOfDie()-dice_action.numOfDie();
					if ( new_dice_num == 0 )
						break;
					new_dice = rundom_dice(new_dice_num,true);
					learn_policy.iteartion(this);
				}
			new_dice = new state();
			learn_policy.iteartion(this);

		}// of round
	
	
		
	public state rundom_dice(int dice_num,boolean all)
		// create set of random dices
		{
			System.out.print("random dice:");
			int rund_dice_num;
			if ( ! all )
				rund_dice_num = r.dM(dice_num);
			else
				rund_dice_num = dice_num;
			int new_die[] = new int[rund_dice_num];
			for (int j=0,index =0;j<rund_dice_num;j++) 
				{
					new_die[j] = r.d6();
					System.out.print("-"+new_die[j]);
				}
			System.out.println();
			state rund_dice = new state(new_die);
			return rund_dice;
		}// of state random dice
		
	public int immidiate_val() 
		// take immidiate values & update categories 
		// also check if end of game
		{
			state s  = new state ();
			s.merge(dice_state);
			s.merge(dice_action);
			if ( s.numOfDie() < 5 )
				return 0;
			int val = -10;
			int value[] = new int[1];
			int num = s.countTheSame(value);
			System.out.println("Immidiate_val: there are "+num+" with the same value");
			switch (num) 
				{
					 case 1: 
						if ( s.countByValue(1) > 0 ) 
							{
								if ( !category[player][3] ) 
									{
										category[player][3] = true;
										System.out.println("Immidiate_val: small yatzee!" );
										val = 25;
									}
							}
						else if ( s.countByValue(6) > 0)
							{ 
								if ( !category[player][2] ) 
									{
										category[player][2] = true;
										System.out.println("Immidiate_val: big yatzee!" );
										val = 35;
									}
							}
							break;
					
					case 3:
							if ( !category[player][0]) 
								{
									category[player][0] = true;
									System.out.println("Immidiate_val: 3 "+value[0]+"'s in a raw!");
									score_count[player] += 3*value[0];
									val = 3*value[0];
							 }
							 break;
						
					case 4:	
							if ( !category[player][1]) 
									{
										category[player][1] = true;
										System.out.println("Immidiate_val: 4 "+value[0]+"'s in a raw!");
										val = 4*value[0];
									}	
							break;
									
					default:
							System.out.println("Immidiate_val: defualt "+val+" for bad round");
							return val;							
				}	
				// check if one game ended
				int i;
				for (i=0; i<category[player].length; i++)
						{
							if ( ! category[player][i])	
								break;
						}
				if ( i == category[player].length ) 
							one_game_end = true;
				return val;
		}// of imiddiate val
}
		