/* Muk-Chi-Ba
 *
 * Korean for "Rock-Scissors-Paper", Muk-Chi-Ba is a simple guessing game.
 * Two players each guess one of those three choices.  Certain choices
 * "beat" certain other choices, so one player can beat the other, or
 * the game can result in a tie if both players choose the same.
 *
 * This game is posted as an example of how to create a simple event-driven
 * game that uses Model-View-Controller separation.  The program demonstrates
 * the use of layout management, action listeners, and painting panels using
 * Graphics2D and the Java 2D API.
 *
 * @author Martin Stepp
 * @version 2001/6/11
 */

import java.awt.*;
import java.awt.event.*;
import java.awt.geom.*;
import java.util.*;
import javax.swing.*;

/** Runs the game. */
public class MukChiBa {
	public static void main(String[] args) {
		new MukChiBaFrame().show();
	}
}


/** A window frame for the game.
  *
  * Represents the Controller of the game because it acts as
  * a listener to its play button.
  */
class MukChiBaFrame extends JFrame implements ActionListener {
	private MukChiBaGame  myGame;
	private MukChiBaPanel myPanel;


	/** Constructs a new frame. */
	public MukChiBaFrame() {
		// set attributes of the frame
		super("Muk-Chi-Ba!");
		setDefaultCloseOperation(EXIT_ON_CLOSE);

		// construct objects and GUI components
		myGame = new MukChiBaGame();
		myPanel = new MukChiBaPanel(myGame);
		JButton playButton = new JButton("Play!");

		// set up event listening
		playButton.addActionListener(this);

		// layout
		JPanel southPanel = new JPanel();
		southPanel.add(playButton);

		Container contentPane = getContentPane();
		contentPane.add(southPanel, BorderLayout.SOUTH);
		contentPane.add(myPanel, BorderLayout.CENTER);
		pack();
	}


	/** Responds to button presses in this frame. */
	public void actionPerformed(ActionEvent event) {
		myGame.play();
		myPanel.repaint();
	}
}


/** A panel on which the rock-paper-scissors are drawn.
  *
  * Represents the View of the game.
  */
class MukChiBaPanel extends JPanel {
	private MukChiBaGame myGame;

	/** Constructs a new panel to show the given game. */
	public MukChiBaPanel(MukChiBaGame game) {
		myGame = game;
		setPreferredSize(new Dimension(150, 110));
	}


	/** Paints this panel on the screen. */
	public void paintComponent(Graphics g) {
		super.paintComponent(g);

		Graphics2D g2 = (Graphics2D)g;

		// set line width
		g2.setStroke(new BasicStroke(2));

		// draw players' symbols
		String player1 = myGame.getPlayer1();
		drawPlayer(g2, player1, 10, 10);

		String player2 = myGame.getPlayer2();
		drawPlayer(g2, player2, 90, 10);

		// write names below
		g2.setFont(new Font("SansSerif", Font.PLAIN, 11));
		g2.setPaint(Color.black);
		g2.drawString(player1, 10, 75);
		g2.drawString(player2, 90, 75);

		// write who won
		g2.setPaint(Color.red);
		g2.setFont(new Font("SansSerif", Font.BOLD, 16));

		int winner = myGame.getWinner();
		if (winner > 0)
			g2.drawString("Player " + winner + " wins!", 10, 100);
		else
			g2.drawString("Tie!", 10, 100);
	}


	/** A helper method to draw one player's game symbol. */
	private void drawPlayer(Graphics2D g2, String player, int x, int y) {
		if (player == MukChiBaGame.MUK) {
			// draw rock
			g2.setPaint(Color.darkGray);
			g2.fill(new Ellipse2D.Double(x, y, 40, 40));
		}

		else if (player == MukChiBaGame.CHI) {
			// draw scissors
			g2.setPaint(Color.blue.darker());

			// circles for handle
			g2.draw(new Ellipse2D.Double(x, y, 20, 20));
			g2.draw(new Ellipse2D.Double(x + 20, y, 20, 20));

			// blades
			g2.draw(new Line2D.Double(x + 10, y + 20, x + 20, y + 25));
			g2.draw(new Line2D.Double(x + 30, y + 20, x + 20, y + 25));
			g2.draw(new Line2D.Double(x + 20, y + 25, x + 15, y + 50));
			g2.draw(new Line2D.Double(x + 20, y + 25, x + 25, y + 50));
		}

		else if (player == MukChiBaGame.BA) {
			// draw paper
			g2.setPaint(Color.white);

			int[] xPoints = {x + 5, x + 30, x + 30, x,      x    };
			int[] yPoints = {y,     y,      y + 40, y + 40, y + 5};

			g2.fill(new Polygon(xPoints, yPoints, xPoints.length));

			// black outline
			g2.setPaint(Color.black);
			g2.draw(new Polygon(xPoints, yPoints, xPoints.length));

			// folded corner
			int[] xPoints2 = {x + 5, x + 5, x    };
			int[] yPoints2 = {y,     y + 5, y + 5};
			g2.draw(new Polygon(xPoints2, yPoints2, xPoints2.length));
		}
	}
}


/** The game state of a game of Muk-Chi-Ba, or Rock-Paper-Scissors.
  *
  * Represents the Model of this game because it contains
  * only data about the game state, not about any graphics or control.
  */
class MukChiBaGame {
	// constants
	public static final String MUK = "Muk";  // rock
	public static final String CHI = "Chi";  // scissors
	public static final String BA  = "Ba";   // paper
	private static final String[] CHOICES = {MUK, CHI, BA};

	// instance variables
	private String myPlayer1;
	private String myPlayer2;


	/** Constructs a new game. */
	public MukChiBaGame() {
		play();
	}


	/** Plays a game, randomly choosing from the three choices for each player. */
	public void play() {
		// pick random rock/paper/scissors for each player
		Random rand = new Random();
		int randomIndex1 = rand.nextInt(3);
		int randomIndex2 = rand.nextInt(3);

		myPlayer1 = CHOICES[randomIndex1];
		myPlayer2 = CHOICES[randomIndex2];
	}


	/** Returns player 1's symbol. */
	public String getPlayer1() {
		return myPlayer1;
	}


	/** Returns player 2's symbol. */
	public String getPlayer2() {
		return myPlayer2;
	}

	/** Returns the number of the player who won; -1 for a tie. */
	public int getWinner() {
		// rock (muk) beats scissors (chi),
		// scissors beats paper (ba),
		// paper beats rock

		if ( (myPlayer1 == MUK  &&  myPlayer2 == CHI)  ||
		     (myPlayer1 == CHI  &&  myPlayer2 == BA)   ||
		     (myPlayer1 == BA   &&  myPlayer2 == MUK))
			return 1;

		else if ( (myPlayer2 == MUK  &&  myPlayer1 == CHI)  ||
		          (myPlayer2 == CHI  &&  myPlayer1 == BA)   ||
		          (myPlayer2 == BA   &&  myPlayer1 == MUK))
			return 2;

		else
			return -1;
	}
}
