// This Class is (c)opyright 1999 by Geoff Knagge. It may be freely used
// for any non-commercial purpose on the following conditions:
//   1.	You indemnify the copyright holder of all possible liability
//  	resulting from its use.
//   2.	You provide a link back to the source of this file, that is
//	http://browse.to/gogogeoff
//
// Use of this class shows your agreement to the above.

import java.awt.*;
import java.awt.event.*;
import ColourPanel;

public class PNZColours extends Dialog implements ActionListener, WindowListener {

	Frame parentFrame;

	ColourPanel[] results;
	ColourPanel thisGuessPanel;
	int gameWidth;
	int gameHeight;
	int activeColours;
	boolean possibleHoles;
	boolean notUnique;
	boolean gameInProgress;	
	boolean limitMoves;

	Button guessNow;
	Button reset;
	TextField prompts;
	int movesToAllow;

	int[] thisGuess;
	int[] target;
	int numGuesses;
//////////////////////////////////////////////////////
	public void windowClosing (WindowEvent e) {
		setVisible(false);
	}

	public void windowActivated (WindowEvent e) {}
	public void windowClosed (WindowEvent e) {}
	public void windowDeactivated (WindowEvent e) {}
	public void windowDeiconified (WindowEvent e) {}
	public void windowIconified (WindowEvent e) {}
	public void windowOpened (WindowEvent e) {}
///////////////////////////////////////////////////////
	

	public void winner() {
		prompts.setText("Congratulations!! You got it in "+Integer.toString(numGuesses)+" guesses!");
		gameInProgress = false;
		guessNow.setEnabled(false);
	}

	public void loser() {
	  if (limitMoves) {
		prompts.setText("Game over. Ha Ha... You lost! :-P");
		gameInProgress = false;
		guessNow.setEnabled(false);
		PNZAnswer.showAnswers(parentFrame,this,target,"You Lost");
		}
	}

	public void giveUp() {
		if (gameInProgress) {
			prompts.setText("You gave up. New game started.");
			PNZAnswer.showAnswers(parentFrame,this,target,"You Gave Up");
			}
		gameInProgress=true;
		numGuesses=0;
		for (int cnt=0; cnt<gameWidth; cnt++)
			{
			thisGuess[cnt]=9;
			thisGuessPanel.setPanel(cnt,9);
			for (int cnt2=0; cnt2<gameHeight; cnt2++) {
				results[cnt2].setPanel(cnt,9);
				if (cnt==0)
					results[cnt2].showresults(0,0);
				}
			}
		guessNowEnabler();
		target = randomArray(gameWidth,activeColours,(! notUnique),possibleHoles);
		for (int cnt=0; cnt<gameHeight-1; cnt++) {
			results[cnt].prompt.setText(Integer.toString(1+cnt)+"   ");
			}

	}
////////////////////////////////////////////////////
	public void actionPerformed(ActionEvent e) {
		// Button pressed
		if (e.getSource() == guessNow) {
			int matches=0;
			int colours=0;
			int panelToFill=0;
			boolean linked = false;
			boolean[] linkedToAColour = new boolean[gameWidth];
			for (int cnt=0; cnt < gameWidth; cnt++)
				linkedToAColour[cnt] = false;
			if (numGuesses>=gameHeight) {
			 	// scroll up
				for (int cnt=0; cnt<gameHeight-1; cnt++) {
					for (int cnt2=0; cnt2<gameWidth; cnt2++) {
						results[cnt].setPanel(cnt2,results[cnt+1].numbers[cnt2]);
						}
					results[cnt].prompt.setText(Integer.toString(numGuesses-gameHeight+2+cnt)+"   ");
					results[cnt].showresults(results[cnt+1].numright,results[cnt+1].numwrong);
					}
				results[gameHeight-1].prompt.setText(Integer.toString(numGuesses+1)+"   ");
				panelToFill = gameHeight-1;
				}
			else
				panelToFill = numGuesses;
			for (int cnt=0; cnt < gameWidth; cnt++) {
				results[panelToFill].setPanel(cnt,thisGuess[cnt]);
				if (thisGuess[cnt]==target[cnt])
					matches++;
				linked = false;
				int cnt2=0;
				while ((! linked) && (cnt2<gameWidth)) {
					if ((thisGuess[cnt]==target[cnt2]) && (! linkedToAColour[cnt2])) {
						linkedToAColour[cnt2] = true;
						linked = true;
						colours++;
						}
					cnt2++;
					}
				thisGuessPanel.setPanel(cnt,9);
				thisGuess[cnt]=9;
				}
			results[panelToFill].showresults(colours,matches);
			numGuesses++;
			guessNowEnabler();
			if (matches == gameWidth)
				winner();
			else
			  if (numGuesses==movesToAllow)
				loser();
			}
		else
			giveUp();
	}

	public int[] randomArray(int size,int limit,boolean mustBeUnique,boolean allowHoles) {
		int tmp=0;
		boolean pass=false;
		int[] array = new int[size];
		for (int cnt=0; cnt< size; cnt++) {
			pass = false;
			while (pass==false) {
				if (allowHoles)
					tmp = (int) (Math.random() *(limit+1));
				else
					tmp = (int) (Math.random() *(limit));
				if (tmp == limit)
					tmp = 9;
				pass = true;
				if ((tmp !=9) && (mustBeUnique))
					for (int cnt2=0; cnt2<cnt; cnt2++)
						if (tmp==array[cnt2])
							pass = false;
				}
			//System.out.println(tmp);
			array[cnt]=tmp;
			}
		return array;
		}

	public PNZColours(Frame f,int panels, int maxTurns, int colours, boolean holes, boolean doubleUps, boolean dieAtEnd, int maxMoves) {
		super(f,"Colour Guessing Game",true);
		activeColours = colours;
		notUnique = doubleUps;
		movesToAllow = maxMoves;
		limitMoves = dieAtEnd;
		setBackground(new Color(96,192,255));
		possibleHoles = holes;
		gameWidth= panels;
		gameHeight = maxTurns;
		thisGuess = new int[gameWidth];
		for (int cnt=0; cnt<gameWidth; cnt++)
			thisGuess[cnt]=9;
		setLayout(new GridLayout(2,1));
		addGuessPanel();
		addHistoryPanel();
		guessNowEnabler();
		target = randomArray(gameWidth,colours,(! notUnique),holes);
		gameInProgress = true;
		prompts.setEditable(false);
		addWindowListener(this);
		parentFrame = f;
		}

	public void addHistoryPanel() {
		Panel HistoryPanel = new Panel();
		add(HistoryPanel);
		HistoryPanel.setLayout(new GridLayout(gameHeight+1,1));
		HistoryPanel.add(new Label("Feedback is in the form : number of matches, number in correct position"));
		results = new ColourPanel[gameHeight];
		for (int cnt=0; cnt<gameHeight; cnt++) {
			results[cnt] = new ColourPanel(this,Integer.toString(cnt+1)+"    ",gameWidth,true,cnt);
			HistoryPanel.add(results[cnt]);
		}
	}

	public void guessNowEnabler() {
		boolean state = true;
		if (! possibleHoles)
			for (int cnt=0; cnt<gameWidth; cnt++)
				if (thisGuess[cnt]==9)
					{
					state = false;
					prompts.setText("You need to select colours for each slot");
					}
		if (state)
			prompts.setText("You may now test this combination");
		guessNow.setEnabled(state);
	}

	public void addSelectPanel(Panel guessPanel,int id,int width,int startfrom) {
		Panel selectPanel = new Panel();
		ColourPanel pickPanel;
		guessPanel.add(selectPanel);
		selectPanel.setLayout(new GridLayout(1,2+gameWidth));
		selectPanel.add(new Panel());

		for (int cnt=1; cnt<=gameWidth; cnt++) {
			pickPanel = new ColourPanel(this,width,false,cnt+id);
			for (int cnt2=0; cnt2< width; cnt2++)
				pickPanel.setPanel(cnt2, cnt2+startfrom);
			selectPanel.add(pickPanel);
			}

		selectPanel.add(new Panel());
	}

	public void addGuessPanel() {
		Panel guessPanel = new Panel();
		Label guessPrompt = new Label("Click on the colours below to make your guess :");
		Label thisGuess = new Label("Your Current selection is as follows :");
		add(guessPanel);
		guessPanel.setLayout(new GridLayout(9,1));
		guessPanel.add(guessPrompt);
		/////////////////////////////////////////////
		if (activeColours >8)
			{
			addSelectPanel(guessPanel,100,3,0);
			addSelectPanel(guessPanel,200,3,3);
			addSelectPanel(guessPanel,300,3,6);
			}
		else
		if (activeColours >6)
			{
			addSelectPanel(guessPanel,100,3,0);
			addSelectPanel(guessPanel,200,3,3);
			addSelectPanel(guessPanel,300,activeColours-6,6);
			}
		else
		if (activeColours >3)
			{
			addSelectPanel(guessPanel,100,3,0);
			addSelectPanel(guessPanel,200,activeColours-3,3);
			}
		else
			{
			addSelectPanel(guessPanel,100,activeColours,0);
			}
			addSelectPanel(guessPanel,400,1,9);

		/////////////////////////////////////////////
		guessPanel.add(thisGuess);
		thisGuessPanel = new ColourPanel(this,"", gameWidth, true);
		guessPanel.add(thisGuessPanel);

		Panel buttonPanel = new Panel();
		guessPanel.add(buttonPanel);
		buttonPanel.setLayout(new GridLayout(1,2));
		guessNow = new Button("Try this combination");
		reset = new Button("Restart");
		buttonPanel.add(reset);
		buttonPanel.add(guessNow);
		guessNow.addActionListener(this);
		reset.addActionListener(this);
		prompts = new TextField();
		prompts.setBackground(Color.cyan);
		guessPanel.add(prompts);
	}

	public boolean colourUnused(int cellToSkip, int colour) {
		for (int cnt =0; cnt< gameWidth; cnt++) {
		   if ((cnt != cellToSkip) && (colour == thisGuess[cnt]))
			return false;
		}
		return true;
	}

	public void panelClicked(int id, int subPanel) {
	   if (gameInProgress) {
		int column=id % 100 -1;
		int colour=(id / 100-1)*3+subPanel;
		if ((colour==9) || (notUnique) || (colourUnused(column,colour)))
			{
			thisGuess[column] = colour;
			thisGuessPanel.setPanel(column,colour);
			guessNowEnabler();
			}
		else
			prompts.setText("Each slot must have a unique colour!");
		}
	}

	public static void playGame(Frame f,int panels, int maxTurns, int colours, boolean holes, boolean doubleUps, int maxMoves) {
	        boolean dieAtEnd = (maxMoves != 0);
		PNZColours game = new PNZColours(f,panels,maxTurns,colours,holes,doubleUps,dieAtEnd,maxMoves) ;
		game.setSize(400,400);
		game.setVisible(true);
		game.dispose();
	}

	public static void main(String[] args) {
		playGame(new Frame(),4,10,6,false,false,10);
		System.exit(0);
	}
}

