Network.java
Home Up BelotConstants.java Network.java Network.html

 

 

import java.awt.*;
import java.net.*;
import java.awt.event.*; 
import java.applet.*;   
import java.io.*;      
public class Network extends Applet 
	implements ActionListener,          // Button
	           ItemListener,            // Choice
		   MouseListener,           // Mouse
		   BelotConstants
{
	public void init ()
	{
		MediaTracker tracker = new MediaTracker(this);
		int trackerID = 1;
		URL url = getCodeBase();
		String imageName;
		Image image;
		String suits [] = {"c", "d", "h", "s"};
		String ranks [] = {"8", "9", "t", "j", "q", "k", "a"};
		Font f = new Font("SansSerif", Font.BOLD, 14);
		cardImageIndices = new int [CARDS_IN_HAND];       
		trump = "Unknown";
		caller = "Unknown";
		dealerName = "Unknown";
		cardsToDisplay = 0;  		      
		myRawPoints = 0;
		yourRawPoints = 0;
		myGamePoints = 0;
		yourGamePoints = 0;
		myRawPoints = 0;
		yourRawPoints = 0;      
		setMessages("Welcome", "to Belot!");      
		setBackground(new Color(0, 220, 220));    // light blue      
		setLayout(null);
		setForeground(Color.black);
		fm = getGraphics().getFontMetrics(f);
		height = getSize().height;
		width = getSize().width;      
		cardImages = new Image [CARDS_IN_DECK + 1];       
		for (int s = 0; s < suits.length; s++)
		{
			for (int r = 0; r < ranks.length; r++)
			{
				imageName = ranks[r] + suits[s] + ".gif";
				image = getImage (url, imageName);
				cardImages[s*ranks.length + r] = image; 
				tracker.addImage (image, trackerID);
				trackerID++;
			}
		}      
		imageName = "cardback.gif";
		cardBackImage = getImage(url, imageName);
		cardImages[28] = cardBackImage;       
		tracker.addImage(cardBackImage, trackerID);      
		try { tracker.waitForAll(); }
		catch (InterruptedException e) {}      
		addMouseListener(this);      
		joinButton = makeButton("Join", 2, 4);
		joinButton.setVisible(true);
		rulesButton = makeButton("Rules", 2, 5);
		rulesButton.setVisible(true);
		againButton = makeButton("Again", 2, 4);
		quitButton = makeButton("Quit", 2, 5);
		sendButton = makeButton("Send", 2, 0);
		sendButton.setVisible(true);      
		outgoingField = new TextField("Outgoing Message");
		add(outgoingField);
		placeComponent(outgoingField, 2, 1, 1);
		outgoingField.setVisible(true);      
		incomingField = new TextField("Incoming Message");
		add(incomingField);
		placeComponent(incomingField, 2, 1, 2);
		incomingField.setVisible(true);      
		acceptTrumpChoice = new Choice();
		acceptTrumpChoice.add ("Accept Trump");
		acceptTrumpChoice.add ("Dont Accept");
		add (acceptTrumpChoice);
		placeComponent(acceptTrumpChoice, 2, 4);
		acceptTrumpChoice.setVisible(false);
		acceptTrumpChoice.addItemListener(this);      
		callTrumpChoice = new Choice();
		callTrumpChoice.add("Clubs");
		callTrumpChoice.add("Diamonds");
		callTrumpChoice.add("Hearts");
		callTrumpChoice.add("Spades");
		callTrumpChoice.add("Nothing");
		callTrumpChoice.add("Everything");
		callTrumpChoice.add("Pass");
		add (callTrumpChoice);
		placeComponent(callTrumpChoice, 2, 4);
		callTrumpChoice.setVisible(false);
		callTrumpChoice.addItemListener(this);      
		cardOne = cardImages[CARDS_IN_DECK]; 
		cardTwo = cardImages[CARDS_IN_DECK];
		cardThree = cardImages[CARDS_IN_DECK];      
	}      
	private Button makeButton(String name, int row, int col)
	{
		Button tempButton = new Button(name);
		add (tempButton);
		placeComponent (tempButton, row, col);
		tempButton.setVisible(false);
		tempButton.addActionListener(this);
		return tempButton;
	}      
	public void paint (Graphics g)
	{
		for (int i = 1; i < NUMBER_ROWS; i++)
			g.drawLine(0, i * height / NUMBER_ROWS, width, 
							i * height / NUMBER_ROWS);
		for (int i = 1; i < NUMBER_COLUMNS; i++)
			g.drawLine(i * width / NUMBER_COLUMNS, 0, 
							i * width / NUMBER_COLUMNS, height);      
		displayStrings(0, 0, "Your", "Play");
		displayStrings(0, 3, "Opponent's", "Play");
		displayStrings(0, 5, "Flipped", "Card");      
		setForeground(Color.red);
		displayStrings(0, 8, "Trump:", "Caller:", "Dealer:");
		setForeground(Color.black);      
		displayStrings(0, 9, trump, caller, dealerName);
		displayStrings(1, 0, "Your", "Hand");      
		displayStrings(2, 6, "You:", "Opponent:");
		displayStringsTop(2, 7, "Raw", "Score");
		displayStringsTop(2, 8, "Game", "Points");
		displayStringsTop(2, 9, "Total", "Points");      
		displayStrings(2, 3, message1, message2);
		displayStrings(2, 7, Integer.toString(myRawPoints), Integer.toString(yourRawPoints));
		displayStrings(2, 8, Integer.toString(myGamePoints), Integer.toString(yourGamePoints));
		displayStrings(2, 9, Integer.toString(myTotalPoints), Integer.toString(yourTotalPoints));      
		for (int i = 0; i < cardsToDisplay; i++) 
		{		displayCard(cardImages[cardImageIndices[i]], 1, i + 1);
		}      
		displayCard(cardOne, 0, 1);
		displayCard(cardTwo, 0, 2);
		displayCard(cardThree, 0, 6);
	}		      
	private boolean inImage (int x, int y, int imageNumber)
	{
		int cellWidth = width / NUMBER_COLUMNS;
		int cellHeight = height / NUMBER_ROWS;
		int upperLeftX = (imageNumber + 1) * cellWidth;
		int upperLeftY = cellHeight;      
		upperLeftX += (int) (.1 * cellWidth);
		upperLeftY += (int) (.1 * cellHeight);
		cellWidth = (int) (.8 * cellWidth);
		cellHeight = (int) (.8 * cellHeight);      
		return ((x >= upperLeftX) && (x <= upperLeftX + cellWidth) &&
			    (y >= upperLeftY) && (y <= upperLeftY + cellHeight));      
	}      
	private boolean legalPlay (int whichCard)
	{
		int cardsPerSuit = CARDS_IN_DECK / 4;      
		if (trickLeader == me)
		{
			return true;
		}
		else if ( (cardImageIndices[whichCard] / cardsPerSuit) == (cardTwoIndex / cardsPerSuit) )
		{
			return true;
		}
		else
		{
			for (int i = 0; i < cardsToDisplay; i++)
			{
				if ((cardImageIndices[i] / cardsPerSuit) == (cardTwoIndex / cardsPerSuit))
					return false;
			}
			return true;
		}
	}      
	public void mousePressed (MouseEvent evt)
	{
		int x = evt.getX();
		int y = evt.getY();      
		for (int i = 0; i < cardsToDisplay; i++)
		{
			if (clickableImages && inImage(x, y, i) && legalPlay(i))
			{
				cardOne = cardImages[cardImageIndices[i]];	
				if (trickLeader == me)
				{					
					cardTwo = cardBackImage;
					client.sendMessage("#CARD1#" + cardImageIndices[i] + "#");
				}
				else
				{
					client.sendMessage("#CARD2#" + cardImageIndices[i] + "#");
				}
				for (int j = i; j < cardsToDisplay - 1; j++)
				{
					cardImageIndices[j] = cardImageIndices[j+1];
				}
				setMessages("Wait", "");
				cardsToDisplay--;
				clickableImages = false;
				repaint();
			}
		}
	}      
	public void mouseClicked (MouseEvent evt) {}
	public void mouseReleased (MouseEvent evt) {}
	public void mouseEntered (MouseEvent evt) {}
	public void mouseExited (MouseEvent evt) {}      
	public void itemStateChanged (ItemEvent evt)
	{
		if (evt.getStateChange() == ItemEvent.SELECTED)
		{
			String arg = (String) evt.getItem();
			if (arg.equals ("Accept Trump"))
			{		
				acceptTrumpChoice.setVisible(false);
				client.sendMessage("#BID1#" + "Accept" + "#");    
				caller = "You";
				setMessages("Wait for", "Final Deal");
			}
			else if (arg.equals ("Dont Accept"))
			{
				acceptTrumpChoice.setVisible(false);
					client.sendMessage("#BID1#Pass#");  
					setMessages("Wait for", "Other Bid");
			}
			else if ((arg.equals("Clubs")) || (arg.equals("Diamonds")) ||
				     (arg.equals("Hearts")) || (arg.equals("Spades")) ||
					 (arg.equals("Nothing")) || (arg.equals("Everything")))
			{
				callTrumpChoice.setVisible(false);
				client.sendMessage("#BID2#" + arg + "#");
				caller = "You";
				trump = arg;
				setMessages("Wait", "");
			}
			else if (arg.equals("Pass"))
			{
				callTrumpChoice.setVisible(false);
				client.sendMessage("#BID2#Pass#");
				if (dealerName.equals("Opponent"))
				{
					setMessages("Wait for", "Other Bid");
				}
				else
				{
					setMessages("Passed Out", "Redeal");
					client.sendMessage("#PASSOUT#");
				}
			}
		}
		repaint();
	}      
	public void actionPerformed(ActionEvent evt)
	{
		String arg = evt.getActionCommand();
		      
		if (arg.equals("Join"))
		{							
			client = new ClientListener(this);
		        client.start();
                        rulesButton.setVisible(false);
			joinButton.setVisible(false);
			setMessages("Wait for", "Opponent");
		}
		else if (arg.equals("Rules"))
		{
			URL url = null;
			try 
			{
				url = new URL("http://cs.montana.edu/~paxton/tutorial/belot.htm");
			}
			catch (MalformedURLException e) {}
			getAppletContext().showDocument(url);
		}
		else if ((arg.equals("Again")) || (arg.equals("Quit")))
		{
			againButton.setVisible(false);
			quitButton.setVisible(false);
			client.sendMessage("#" + arg.toUpperCase() + "#");
			setMessages("Wait", "");
		}
		else if (arg.equals("Send"))
		{
			String message = outgoingField.getText();
			outgoingField.setText("");
			client.sendMessage("#MESSAGE#" + message + "#");
		}
		repaint();
	}      
	public void setMessages(String m1, String m2)
	{
		message1 = m1;
		message2 = m2;
	}      
	public void placeComponent (TextField field, int row, int column, int where)
	{
		int x = column * width / NUMBER_COLUMNS;
		int y = row * height / NUMBER_ROWS;      
		y = y + where * (height / NUMBER_ROWS / 3 );      
		field.setBounds(x + 10, y, 2 * width / NUMBER_COLUMNS - 20, 20);
	}      
	public void placeComponent (Component component, int row, int column)
	{
		int x = column * width / NUMBER_COLUMNS;
		int y = row * height / NUMBER_ROWS;
		component.setBounds(x + 10, y + 10, width/NUMBER_COLUMNS - 20, 
								height/NUMBER_ROWS - 20);
	}      
	void displayString(int row, int column, String text)
	{
		Graphics g = getGraphics();      
		int x = column * width / NUMBER_COLUMNS + 10;
		int y = row * height / NUMBER_ROWS + 70;      
		g.drawString(text, x, y);
	}      
	void displayString(int row, int column, int whichOne,
		               int howMany, String text)
	{
		Graphics g = getGraphics();      
		int x = column * width / NUMBER_COLUMNS;
		int y = row * height / NUMBER_ROWS;
		int yGap = ((height / NUMBER_ROWS) - (fm.getHeight() * howMany) - 
			           (howMany - 1)*(height/NUMBER_ROWS/20)) / 2;      
		x += (width/NUMBER_COLUMNS - fm.stringWidth(text)) / 2;   // center horizontally
		y += yGap + fm.getHeight()*whichOne + (height/NUMBER_ROWS/20*(whichOne - 1));      
		g.drawString(text, x, y);
	}      
	void displayStringTop(int row, int column, int whichOne, String text)
	{
		Graphics g = getGraphics();      
		int x = column * width / NUMBER_COLUMNS;
		x += (width/NUMBER_COLUMNS - fm.stringWidth(text)) / 2;      
		int y = row * height / NUMBER_ROWS + whichOne * fm.getHeight();      
		g.drawString(text, x, y);
	}      
	void displayStrings (int row, int column, String text1, String text2)
	{
		displayString(row, column, 1, 2, text1);
		displayString(row, column, 2, 2, text2);
	}      
	void displayStrings (int row, int column, String text1, 
							String text2, String text3)
	{
		displayString(row, column, 1, 3, text1);
		displayString(row, column, 2, 3, text2);
		displayString(row, column, 3, 3, text3);
	}      
	void displayStringsTop (int row, int column, String text1, String text2)
	{
		displayStringTop(row, column, 1, text1);
		displayStringTop(row, column, 2, text2);
	}      
	void displayCard (Image card, int row, int column)
	{
		int cellWidth = width / NUMBER_COLUMNS;
		int cellHeight = height / NUMBER_ROWS;
		int x = column * cellWidth;
		int y = row * cellHeight;      
		x = x + (int) (.1 * cellWidth) ;
		y = y + (int) (.1 * cellHeight);
		cellWidth = (int) (.8 * cellWidth);
		cellHeight = (int) (.8 * cellHeight);      
		getGraphics().drawImage(card, x, y, cellWidth, cellHeight, this);
	}      
	private Button joinButton;
	private Button rulesButton;
	private Button sendButton;
	protected Button againButton;
	protected Button quitButton;
	protected Choice acceptTrumpChoice;
	protected Choice callTrumpChoice;
	protected TextField outgoingField;
	protected TextField incomingField;      
	protected Image cardOne;
	protected Image cardTwo;
	protected Image cardThree;
	protected int cardTwoIndex;      
	protected Image cardBackImage;
	      
	protected boolean clickableImages;      
	protected int dealer;
	protected int trickLeader;
	private int height;   // height of applet
	private int width;    // width of applet      
	private String message1;
	private String message2;
	private FontMetrics fm;       
	protected Image cardImages[];
	protected int cardImageIndices[];
	protected int cardsToDisplay;      
	protected String trump;
	protected String caller;
	protected String dealerName;      
	protected int myRawPoints;
	protected int yourRawPoints;
	protected int myGamePoints;
	protected int yourGamePoints;
	protected int myTotalPoints;
	protected int yourTotalPoints;      
	protected int me;
	protected int you;      
	private ClientListener client;      
}      
class ClientListener extends Thread implements BelotConstants
{
	ClientListener (Network network)
	{
		parent = network;
	    
		if ( !connectToServer() )
		{
			parent.setBackground(Color.yellow);
		}      
		try
		{
			clientInput = new DataInputStream 
				(new BufferedInputStream (clientSocket.getInputStream()));
			clientOutput = new DataOutputStream 
				(new BufferedOutputStream (clientSocket.getOutputStream()));
		}
		catch (Exception e)
		{
			parent.setMessages("Stream", "Error");
		}
	}      
	private boolean connectToServer()
	{	
		try
		{
			clientSocket = new Socket("cs.montana.edu", 41962);
			return true;
		}
		catch (Exception e)
		{
			parent.setMessages("Connect", "Error");
			return false;
		}      
	}      
	public void sendMessage (String message)
	{
		try
		{
			clientOutput.writeUTF(message);
			clientOutput.flush();
		}
		catch (Exception e)
		{
                        parent.setMessages("Write", "Error");
			parent.setBackground(Color.white);
			parent.repaint();
		}
	}      
	public void run ()
	{
		String message;
		String command = "";
		int whichPosition;
		int whichCard;
		String whichSuit;      
		int pointsMe;
		int pointsYou;
		int who;      
		while (!command.equals("QUIT"))
		{
			try
			{
				message = clientInput.readUTF();
				command = determineCommand ( message);
				message = shortenCommand(message, command);
								      
				if (command.equals("CARD"))
				{		
					command = determineCommand(message);
					whichPosition = Integer.parseInt(command);
					message = shortenCommand (message, command);      
					whichCard = Integer.parseInt(determineCommand(message));      
					if (whichPosition < CARDS_IN_HAND)
					{
						parent.cardImageIndices[whichPosition] = whichCard;
					}
					else if (whichPosition == CARDS_IN_HAND)
					{
						parent.cardOne = parent.cardImages[whichCard];
					}
					else if (whichPosition == CARDS_IN_HAND + 1)
					{
						parent.cardTwo = parent.cardImages[whichCard];
						parent.cardTwoIndex = whichCard;
					}
					else if (whichPosition == CARDS_IN_HAND + 2)
					{
						parent.cardThree = parent.cardImages[whichCard];
					}
				}
				else if (command.equals("CARDSTODISPLAY"))
				{
					parent.cardsToDisplay = Integer.parseInt(determineCommand(message));
				}
				else if (command.equals("DEALER"))
				{
					who = Integer.parseInt(determineCommand(message));
					parent.caller = "Unknown";
					parent.trump = "Unknown";
					if (parent.me == who)
					{
						parent.dealerName = "You";
					}
					else
					{
						parent.dealerName = "Opponent";
					}
				}
				else if (command.equals("FIRSTBID"))
				{
					whichSuit = determineCommand(message);
					if (!whichSuit.equals("Pass"))
					{
						parent.caller = "Opponent";
						parent.trump = whichSuit;
						parent.setMessages("Wait", "");
					}
					else if (parent.dealerName.equals("You"))
					{
						parent.acceptTrumpChoice.setVisible(true);
						parent.setMessages("Make a", "Bid");
					}
					else
					{
						parent.callTrumpChoice.setVisible(true);
						parent.setMessages("Make a", "Bid");
					}
				}
				else if (command.equals("FOLLOWCARD"))
				{					
					whichCard = Integer.parseInt(determineCommand(message));						
					parent.cardTwo = parent.cardImages[whichCard];
					parent.cardTwoIndex = whichCard;
					parent.setMessages("Play a", "Card");
					parent.clickableImages = true;
					parent.trickLeader = parent.you;
					parent.cardOne = parent.cardBackImage;
				}
				else if (command.equals("GAMEPOINTS"))
				{					
					command = determineCommand(message);
					pointsMe = Integer.parseInt(command);
					message = shortenCommand(message, command);
					command = determineCommand(message);
					pointsYou = Integer.parseInt(command);
					parent.myGamePoints = pointsMe;
					parent.yourGamePoints = pointsYou;
				}
				else if (command.equals("MESSAGE"))
				{
					parent.incomingField.setText(determineCommand(message));
					parent.repaint();
				}
				else if (command.equals("PAINT"))
				{
					parent.repaint();
				}
				else if (command.equals("PLAYCARD"))
				{
					parent.setMessages("Play a", "Card");
					parent.clickableImages = true;
					parent.trickLeader = parent.me;
				}
				else if (command.equals("QUIT"))
				{
					parent.setMessages("Player", "Quit");
					sendMessage("#QUIT#");
					parent.repaint();
				}
				else if (command.equals("RAWPOINTS"))
				{
					command = determineCommand(message);
					pointsMe = Integer.parseInt(command);
					message = shortenCommand(message, command);
					command = determineCommand(message);
					pointsYou = Integer.parseInt(command);
					parent.myRawPoints = pointsMe;
					parent.yourRawPoints = pointsYou;
				}
				else if (command.equals("SECONDBID"))
				{
					whichSuit = determineCommand(message);
					if (!whichSuit.equals("Pass"))
					{
						parent.caller = "Opponent";
						parent.trump = whichSuit;
						parent.setMessages("Wait", "");
					}
					else if (parent.dealerName.equals("You"))
					{
						parent.callTrumpChoice.setVisible(true);
						parent.setMessages("Make a", "Bid");
					}
					else
					{
						parent.setMessages("Passed", "Out");
					}
				}
				else if (command.equals("SLEEP"))
				{
					sleep(5000);
				}
				else if (command.equals("STARTBIDDING"))
				{
					if (parent.dealerName.equals("Opponent"))
					{
						parent.setMessages("Make", "a Bid");
						parent.acceptTrumpChoice.setVisible(true);
					}
					else
					{
						parent.setMessages("Wait for", "Opponent Bid");
					}
				}
				else if (command.equals("TOTALPOINTS"))
				{
					command = determineCommand(message);
					pointsMe = Integer.parseInt(command);
					message = shortenCommand(message, command);
					command = determineCommand(message);
					pointsYou = Integer.parseInt(command);
					parent.myTotalPoints = pointsMe;
					parent.yourTotalPoints = pointsYou;
					if ((pointsYou > POINTS_TO_WIN) && (pointsYou > pointsMe))
					{
						parent.setMessages("You", "Lose");
						parent.againButton.setVisible(true);
						parent.quitButton.setVisible(true);
					}
					else if ((pointsMe > POINTS_TO_WIN) && (pointsMe > pointsYou))
					{
						parent.setMessages("You", "Win");
						parent.againButton.setVisible(true);
						parent.quitButton.setVisible(true);
					}
				}
				else if (command.equals("TRUMP"))
				{
					whichSuit = determineCommand(message);
					parent.trump = whichSuit;
				}
				else if (command.equals("YOURNUMBER"))
				{
					parent.me = Integer.parseInt(determineCommand(message));
					parent.you = 1 - parent.me;
				}
			}
			catch (Exception e)
			{
                                parent.setMessages("Command", "Error");
				parent.setBackground(Color.green);
			}
		}
		parent.repaint();
	}      
	private String determineCommand (String message)
	{
		int secondHash = message.indexOf("#", 1);      
		return message.substring(1, secondHash);
	}      
	private String shortenCommand (String message, String argument)
	{
		return message.substring(1 + argument.length());
	}      
	private Socket clientSocket;
	private DataInputStream clientInput;
	private DataOutputStream clientOutput;      
	private Network parent;
}