// // File: MClient.java Author: David Sinclair // Version: 1.1 Date: 09 Jan 2001 // // Client for Intelligent Game Theory Assignment - Game Matrix with side paymets // import java.io.*; import java.net.*; import java.util.*; // ClientGameMatrix Class // Builds and interrogates game matrix class ClientGameMatrix { int NumberOfPlayers, capacity; int dimensions []; int game[][]; int strategyIterator [] = null; // Constructor - generates a random game matrix based on the number of players // and the number of strategies specified by params. ClientGameMatrix (int params[]) { int i, j, size; NumberOfPlayers = params [0]; dimensions = new int [NumberOfPlayers]; for (i = 0; i < NumberOfPlayers; i++) { dimensions [i] = params [i+1]; } for (i = 0, size = 1; i < NumberOfPlayers; i++) { size = size * dimensions [i]; } capacity = size; game = new int [size][NumberOfPlayers]; } // getPayoffs // Return the payoffs for the specified strategy int [] getPayoffs (int strategy[]) { int i, index, multiplier = 1; index = strategy [0] - 1; for (i = 1; i < NumberOfPlayers; i++) { multiplier = multiplier * dimensions [i-1]; index = index + ((strategy [i] -1) * multiplier); } return (game [index]); } // setPayoffs // Assigns the specified payoffs to the specified strategy void setPayoffs (int strategy[], int payoff[]) { int i, index, multiplier = 1; index = strategy [0] - 1; for (i = 1; i < NumberOfPlayers; i++) { multiplier = multiplier * dimensions [i-1]; index = index + ((strategy [i] -1) * multiplier); } game [index] = payoff; return; } // getNumberOfStrategies // Return number of strategies for the specified player less one int getNumberOfStrategies (int i) { return (dimensions [i]); } // getCapacity // Return the capacity (max. size) of the game matrix int getCapacity () { return (capacity); } // initIterator // Creates and returns an iterator to iterate the possible strategies. int [] initIterator () { int i; // create the initial strategy strategyIterator = new int [NumberOfPlayers]; for (i = 0; i < NumberOfPlayers; i++) { strategyIterator [i] = 1; } return (strategyIterator); } // nextStrategy // Returns next strategy in from the iterator. If there are no more strategies // or the iterator has not been initialise return null. int [] nextStrategy () { int index; if (strategyIterator == null) return (null); else { // increment strategy for (index = 0; index < NumberOfPlayers; index++) { strategyIterator [index] = strategyIterator [index] + 1; if (strategyIterator [index] > dimensions [index]) { strategyIterator [index] = 1; } else { break; } } // check if we have run out of strategies if (index == NumberOfPlayers) { strategyIterator = null; // if so set iterator to null } return (strategyIterator); } } // findBest // A very simple algorithm that finds the strategy with the highest payoff for the specified player. // This is generally not the best choice of strategy. int [] findBest (int playerID) { int i, currentBestValue; int strategy[], payoff[], bestStrategy[]; bestStrategy = new int [NumberOfPlayers]; currentBestValue = Integer.MIN_VALUE; strategy = initIterator (); while (strategy != null) { payoff = getPayoffs (strategy); if (payoff [playerID - 1] > currentBestValue) { currentBestValue = payoff [playerID - 1]; for (i = 0; i < NumberOfPlayers; i++) { bestStrategy [i] = strategy [i]; } } strategy = nextStrategy (); } return (bestStrategy); } // display // Display the contents on the game matrix. void display () { int i, index = 0; int strategy[], payoff[]; System.out.println ("Number of Players = " + NumberOfPlayers); // create the initial strategy strategy = initIterator (); // iterate through all the strategies for each player. while (strategy != null) { payoff = getPayoffs (strategy); System.out.print ("Strategy "); for (i = 0; i < NumberOfPlayers; i++) { System.out.print (strategy [i] + " "); } System.out.print (" : "); for (i = 0; i < NumberOfPlayers; i++) { System.out.print (payoff [i] + " "); } System.out.println (); // increment strategy strategy = nextStrategy (); } return; } } // Application class MClient { public static void main (String args[]) throws IOException { int base_port = 4000; String ID = "12345678"; boolean offerNewContract; int i, j, k, m; int NumberOfPlayers = 0, playerID, size, myBest, side, player; int othersStrategy, bribe; int port_num = Integer.parseInt (args[0]) - 1; long balance; String message; ClientGameMatrix game = null; int params[], payoff[] = null, likelyPayoff[] = null, sidePayments[]; int strategy[], bestStrategy[], likelyStrategy[]; float offerRatio[]; Socket sock; playerID = port_num + 1; sock = new Socket ("localhost", base_port+port_num); PrintStream out = new PrintStream (sock.getOutputStream (), true); DataInputStream in = new DataInputStream (sock.getInputStream ()); message = in.readLine (); System.out.println ("Received: " + message); if (message.charAt(0) == 'W') { out.println (ID); out.flush (); } message = in.readLine (); System.out.println ("Received: " + message); if (message.charAt(0) == 'B') { balance = (long) Integer.parseInt (message.substring (1)); } message = in.readLine (); System.out.println ("Received: " + message); while (message.charAt(0) != 'E') { if (message.charAt(0) == 'M') { // build game matrix i = 2; NumberOfPlayers = Integer.parseInt (message.substring (i, endInt(message, i))); params = new int [NumberOfPlayers+1]; j = 0; while (i < message.length ()) { params [j++] = (Integer.parseInt (message.substring (i, endInt (message, i)))); // skip to next number if (message.charAt(i) == '-') i++; for (; (i < message.length ()) && (Character.isDigit(message.charAt(i))); i++); for (; (i < message.length ()) && (!Character.isDigit(message.charAt(i))) && (message.charAt(i) != '-'); i++); } game = new ClientGameMatrix (params); size = game.getCapacity (); strategy = game.initIterator (); // load game matrix for (j = 0; j < size; j++, strategy = game.nextStrategy ()) { message = in.readLine (); payoff = new int [NumberOfPlayers]; i = 0; k = 0; while (i < message.length ()) { payoff [k++] = (Integer.parseInt (message.substring (i, endInt (message, i)))); // skip to next number if (message.charAt (i) == '-') i++; for (; (i < message.length ()) && (Character.isDigit(message.charAt(i))); i++); for (; (i < message.length ()) && ((!Character.isDigit(message.charAt(i))) && (message.charAt(i) != '-')); i++); } game.setPayoffs (strategy, payoff); } game.display (); } message = in.readLine (); if (!message.equals ("R1")) { unexpectedMessage (message); } bestStrategy = game.findBest (playerID); myBest = bestStrategy [playerID-1]; // find strategy that will be played if everyone plays their best strategy likelyStrategy = new int [NumberOfPlayers]; for (i = 0; i < NumberOfPlayers; i++) { strategy = game.findBest (i+1); likelyStrategy [i] = strategy [i]; } // calculate initial side payments offerRatio = new float [NumberOfPlayers]; for (i = 0; i < NumberOfPlayers; i++) { offerRatio [i] = (float) 0.1; } sidePayments = new int [NumberOfPlayers]; for (i = 0; i < NumberOfPlayers; i++) { if (i != (playerID - 1)) { payoff = game.getPayoffs (bestStrategy); likelyPayoff = game.getPayoffs (likelyStrategy); System.out.println ("likely payoff for player " + (i+1) + " is " + likelyPayoff [i]); System.out.println ("best payoff for player " + (i+1) + " is " + payoff [i]); side = (int) (offerRatio [i] * (likelyPayoff [i] - payoff [i])); System.out.println ("Side payment to player " + (i+1) + " is " + side); if (side < 0) { side = 0; } } else { side = 0; } sidePayments [i] = side; } System.out.print ("Side Payments: "); for (i = 0; i < NumberOfPlayers; i++) { System.out.print (sidePayments [i] + " "); } System.out.println (); offerNewContract = true; for (i = 0; i < 3; i++) { for (j = 0; j < NumberOfPlayers; j++) { message = in.readLine (); player = Integer.parseInt (message.substring (1)); if ((message.charAt (0) == 'G') && (player != playerID)) { message = in.readLine (); // consume other player's offer m = 2; for (k = 0; k < NumberOfPlayers; k++) { // check if a player offered a side payment is being offering // a larger side payment by another player. othersStrategy = Integer.parseInt (message.substring (m, endInt (message, m))); for (; (m < message.length ()) && (Character.isDigit(message.charAt(m))); m++); for (; (m < message.length ()) && (!Character.isDigit(message.charAt(m))); m++); bribe = Integer.parseInt (message.substring (m, endInt (message, m))); for (; (m < message.length ()) && (Character.isDigit(message.charAt(m))); m++); for (; (m < message.length ()) && (!Character.isDigit(message.charAt(m))); m++); if ((othersStrategy != bestStrategy [k]) && (othersStrategy != 0) && (bribe > sidePayments [k])) { System.out.println ("I've been outbid by " + player + " on " + (k+1)); offerRatio [k] *= 2.0; side = (int) (offerRatio [k] * (likelyPayoff [k] - payoff [k])); if (side < 0) { side = 0; } sidePayments [k] = side; System.out.println ("Uping ratio to " + offerRatio [k]); System.out.println ("New side payment on " + (k+1) + " is " + sidePayments [k]); offerNewContract = true; } } } else { out.print ("C"); if (offerNewContract == true) { offerNewContract = false; for (k = 0; k < NumberOfPlayers; k++) { if ((k == (playerID-1)) || (sidePayments [k] == 0)) { out.print (" 0 0"); } else { out.print (" " + bestStrategy [k] + " " + sidePayments [k]); } } } else { for (k = 0; k < NumberOfPlayers; k++) { out.print (" 0 0"); } } out.println (); } } } message = in.readLine (); if (!message.equals ("R2")) { unexpectedMessage (message); } System.out.println ("Best Strategy = " + myBest); out.println ("S" + myBest); message = in.readLine (); System.out.println (message); if (message.charAt(0) == 'P') { for (i = 2, j = 0; j < (playerID - 1); j++) { // skip to next number if (message.charAt (i) == '-') i++; for (; (i < message.length ()) && (Character.isDigit(message.charAt(i))); i++); for (; (i < message.length ()) && (!Character.isDigit(message.charAt(i))) && (message.charAt(i) != '-'); i++); } System.out.println ("Won: " + Integer.parseInt (message.substring (i, endInt (message, i)))); } else { unexpectedMessage (message); } message = in.readLine (); } sock.close (); } // endInt // Returns an index just past the integer at the specified index in the specified string. static int endInt (String s, int index) { int i; if (s.charAt(index) == '-') i = index + 1; else i = index; // skip to end of number while ((i < s.length ()) && (Character.isDigit(s.charAt(i)))) { i++; } return (i); } // unexpectedMessage // Prints error message and exits. static void unexpectedMessage (String message) { System.out.println ("Unexpected message: " + message); System.exit (1); return; } }