package player; import java.io.IOException; import java.net.ServerSocket; import java.net.Socket; import java.util.ArrayList; import java.util.List; import player.gamer.Gamer; import player.gamer.statemachine.reflex.random.RandomGamer; import player.event.PlayerDroppedPacketEvent; import player.event.PlayerReceivedMessageEvent; import player.event.PlayerSentMessageEvent; import player.request.factory.RequestFactory; import player.request.grammar.Request; import shef.strategies.uct.UCTNeuralStrategy; import shef.strategies.uct.UCTSimpleStrategy; import util.http.HttpReader; import util.http.HttpWriter; import util.logging.GamerLogger; import util.observer.Event; import util.observer.Observer; import util.observer.Subject; public final class GamePlayer extends Thread implements Subject { private final int port; private final Gamer gamer; private ServerSocket listener; private final List<Observer> observers; public GamePlayer(int port, Gamer gamer) throws IOException { observers = new ArrayList<Observer>(); listener = null; while (listener == null) { try { listener = new ServerSocket(port); } catch (IOException ex) { listener = null; port++; System.err.println("Failed to start gamer on port: " + (port - 1) + " trying port " + port); } } this.port = port; this.gamer = gamer; } public void addObserver(Observer observer) { observers.add(observer); } public void notifyObservers(Event event) { for (Observer observer : observers) { observer.observe(event); } } public final int getGamerPort() { return port; } public final Gamer getGamer() { return gamer; } @Override public void run() { while (!isInterrupted()) { try { Socket connection = listener.accept(); String in = HttpReader.readAsServer(connection); if (in.length() == 0) { throw new IOException("Empty message received."); } notifyObservers(new PlayerReceivedMessageEvent(in)); GamerLogger.log("GamePlayer", "[Received at " + System.currentTimeMillis() + "] " + in, GamerLogger.LOG_LEVEL_DATA_DUMP); Request request = new RequestFactory().create(gamer, in); String out = request.process(System.currentTimeMillis()); HttpWriter.writeAsServer(connection, out); connection.close(); notifyObservers(new PlayerSentMessageEvent(out)); GamerLogger.log("GamePlayer", "[Sent at " + System.currentTimeMillis() + "] " + out, GamerLogger.LOG_LEVEL_DATA_DUMP); } catch (Exception e) { notifyObservers(new PlayerDroppedPacketEvent()); } } } // Simple main function that starts a RandomGamer on a specified port. // It might make sense to factor this out into a separate app sometime, // so that the GamePlayer class doesn't have to import RandomGamer. public static void main(String[] args) { if (args.length != 2) { System.err.println("Usage: GamePlayer <port>"); System.exit(1); } try { Gamer strat = null; if (Integer.parseInt(args[1]) == 1) { strat = new UCTSimpleStrategy(); } else if (Integer.parseInt(args[1]) == 2){ strat = new UCTNeuralStrategy(); } GamePlayer player = new GamePlayer(Integer.valueOf(args[0]), strat); player.run(); } catch (NumberFormatException e) { System.err.println("Illegal port number: " + args[0]); e.printStackTrace(); System.exit(2); } catch (IOException e) { System.err.println("IO Exception: " + e); e.printStackTrace(); System.exit(3); } } }