public GameServer(Match match, List<String> hosts, List<Integer> ports) { this.match = match; this.hosts = hosts; this.ports = ports; playerGetsUnlimitedTime = new Boolean[hosts.size()]; Arrays.fill(playerGetsUnlimitedTime, Boolean.FALSE); playerPlaysRandomly = new Boolean[hosts.size()]; Arrays.fill(playerPlaysRandomly, Boolean.FALSE); stateMachine = new ProverStateMachine(); stateMachine.initialize(match.getGame().getRules()); currentState = stateMachine.getInitialState(); previousMoves = null; mostRecentErrors = new HashMap<Role, String>(); match.appendState(currentState.getContents()); observers = new ArrayList<Observer>(); spectatorServerURL = null; forceUsingEntireClock = false; }
private String getPlayerNameFromMatchForRequest(int i) { if (match.getPlayerNamesFromHost() != null) { return match.getPlayerNamesFromHost().get(i); } else { return ""; } }
public void abort() { try { match.markAborted(); sendAbortRequests(); notifyObservers(new ServerAbortedMatchEvent()); } catch (Exception e) { e.printStackTrace(); } }
@Test public void testTicTacToe() { SinglePlayer s = new SinglePlayer(); RandomGamer r = new RandomGamer(); Match m = new Match("", 10, 120, 120, GameRepository.getDefaultRepository().getGame("ticTacToe"), ""); s.setMatch(m); r.setMatch(m); s.setRoleName(GdlPool.getConstant("xplayer")); r.setRoleName(GdlPool.getConstant("oplayer")); assertTrue(s.getRoleName().toString() == "xplayer"); assertTrue(r.getRoleName().toString() == "oplayer"); while (!m.isCompleted()) {} if (m.isCompleted()) { assertTrue(s.bestValue >= 50); } else System.out.println("this should never print"); }
@Test public void testCoins() { try { SinglePlayer s = new SinglePlayer(); Match m = new Match("", -1, 1000, 1000, GameRepository.getDefaultRepository().getGame("coins"), ""); s.setMatch(m); s.setRoleName(GdlPool.getConstant("you")); s.metaGame(1000); assertEquals("SinglePlayer", s.getName()); assertTrue(s.selectMove(1000) != null); assertTrue(GdlPool.getConstant("you") == s.getRoleName()); if (m.isCompleted()) { assertTrue(s.bestValue == 100); } } catch (Exception e) { e.printStackTrace(); } }
// Should be called after each move, to collect all of the errors // caused by players and write them into the match description. private void appendErrorsToMatchDescription() { List<String> theErrors = new ArrayList<String>(); for (int i = 0; i < stateMachine.getRoles().size(); i++) { Role r = stateMachine.getRoles().get(i); if (mostRecentErrors.containsKey(r)) { theErrors.add(mostRecentErrors.get(r)); } else { theErrors.add(""); } } match.appendErrors(theErrors); mostRecentErrors.clear(); }
private void saveWhenNecessary() { if (saveToFilename == null) { return; } try { File file = new File(saveToFilename); if (!file.exists()) { file.createNewFile(); } FileWriter fw = new FileWriter(file); BufferedWriter bw = new BufferedWriter(fw); bw.write(match.toJSON().toString()); bw.close(); fw.close(); } catch (IOException ie) { ie.printStackTrace(); } }
@Override public void run() { try { if (match.getAnalysisClock() >= 0) { sendAnalyzeRequests(); } notifyObservers(new ServerNewMatchEvent(stateMachine.getRoles(), currentState)); notifyObservers(new ServerTimeEvent(match.getStartClock() * 1000)); sendStartRequests(); appendErrorsToMatchDescription(); while (!stateMachine.isTerminal(currentState)) { publishWhenNecessary(); saveWhenNecessary(); notifyObservers(new ServerNewGameStateEvent(currentState)); notifyObservers(new ServerTimeEvent(match.getPlayClock() * 1000)); notifyObservers(new ServerMatchUpdatedEvent(match, spectatorServerKey, saveToFilename)); previousMoves = sendPlayRequests(); notifyObservers(new ServerNewMovesEvent(previousMoves)); currentState = stateMachine.getNextState(currentState, previousMoves); match.appendMoves2(previousMoves); match.appendState(currentState.getContents()); appendErrorsToMatchDescription(); } match.markCompleted(stateMachine.getGoals(currentState)); publishWhenNecessary(); saveWhenNecessary(); notifyObservers(new ServerNewGameStateEvent(currentState)); notifyObservers(new ServerCompletedMatchEvent(getGoals())); notifyObservers(new ServerMatchUpdatedEvent(match, spectatorServerKey, saveToFilename)); sendStopRequests(previousMoves); } catch (InterruptedException ie) { if (match.isAborted()) { return; } else { ie.printStackTrace(); } } catch (Exception e) { e.printStackTrace(); } }
private synchronized List<Move> sendPlayRequests() throws InterruptedException, MoveDefinitionException { List<PlayRequestThread> threads = new ArrayList<PlayRequestThread>(hosts.size()); for (int i = 0; i < hosts.size(); i++) { List<Move> legalMoves = stateMachine.getLegalMoves(currentState, stateMachine.getRoles().get(i)); if (playerPlaysRandomly[i]) { threads.add(new RandomPlayRequestThread(match, legalMoves)); } else { threads.add( new PlayRequestThread( this, match, previousMoves, legalMoves, stateMachine.getRoles().get(i), hosts.get(i), ports.get(i), getPlayerNameFromMatchForRequest(i), playerGetsUnlimitedTime[i])); } } for (PlayRequestThread thread : threads) { thread.start(); } if (forceUsingEntireClock) { Thread.sleep(match.getPlayClock() * 1000); } List<Move> moves = new ArrayList<Move>(); for (PlayRequestThread thread : threads) { thread.join(); moves.add(thread.getMove()); } return moves; }
private synchronized void sendStartRequests() throws InterruptedException { List<StartRequestThread> threads = new ArrayList<StartRequestThread>(hosts.size()); for (int i = 0; i < hosts.size(); i++) { if (!playerPlaysRandomly[i]) { threads.add( new StartRequestThread( this, match, stateMachine.getRoles().get(i), hosts.get(i), ports.get(i), getPlayerNameFromMatchForRequest(i))); } } for (StartRequestThread thread : threads) { thread.start(); } if (forceUsingEntireClock) { Thread.sleep(match.getStartClock() * 1000); } for (StartRequestThread thread : threads) { thread.join(); } }
public static void main(String[] args) throws IOException, SymbolFormatException, GdlFormatException, InterruptedException, GoalDefinitionException { // Extract the desired configuration from the command line. String tourneyName = args[0]; String gameKey = args[1]; Game game = GameRepository.getDefaultRepository().getGame(gameKey); int startClock = Integer.valueOf(args[2]); int playClock = Integer.valueOf(args[3]); if ((args.length - 4) % 3 != 0) { throw new RuntimeException("Invalid number of player arguments of the form host/port/name."); } List<String> hostNames = new ArrayList<String>(); List<String> playerNames = new ArrayList<String>(); List<Integer> portNumbers = new ArrayList<Integer>(); String matchName = tourneyName + "." + gameKey + "." + System.currentTimeMillis(); for (int i = 4; i < args.length; i += 3) { String hostname = args[i]; Integer port = Integer.valueOf(args[i + 1]); String name = args[i + 2]; hostNames.add(hostname); portNumbers.add(port); playerNames.add(name); } int expectedRoles = Role.computeRoles(game.getRules()).size(); if (hostNames.size() != expectedRoles) { throw new RuntimeException( "Invalid number of players for game " + gameKey + ": " + hostNames.size() + " vs " + expectedRoles); } Match match = new Match(matchName, -1, startClock, playClock, game); match.setPlayerNamesFromHost(playerNames); // Actually run the match, using the desired configuration. GameServer server = new GameServer(match, hostNames, portNumbers); server.run(); server.join(); // Open up the directory for this tournament. // Create a "scores" file if none exists. File f = new File(tourneyName); if (!f.exists()) { f.mkdir(); f = new File(tourneyName + "/scores"); f.createNewFile(); } // Open up the XML file for this match, and save the match there. f = new File(tourneyName + "/" + matchName + ".xml"); if (f.exists()) f.delete(); BufferedWriter bw = new BufferedWriter(new FileWriter(f)); bw.write(match.toXML()); bw.flush(); bw.close(); // Open up the JSON file for this match, and save the match there. f = new File(tourneyName + "/" + matchName + ".json"); if (f.exists()) f.delete(); bw = new BufferedWriter(new FileWriter(f)); bw.write(match.toJSON()); bw.flush(); bw.close(); // Save the goals in the "/scores" file for the tournament. bw = new BufferedWriter(new FileWriter(tourneyName + "/scores", true)); List<Integer> goals = server.getGoals(); String goalStr = ""; String playerStr = ""; for (int i = 0; i < goals.size(); i++) { Integer goal = server.getGoals().get(i); goalStr += Integer.toString(goal); playerStr += playerNames.get(i); if (i != goals.size() - 1) { playerStr += ","; goalStr += ","; } } bw.write(playerStr + "=" + goalStr); bw.flush(); bw.close(); }