mirror of
https://github.com/Card-Forge/forge.git
synced 2025-11-16 10:48:00 +00:00
Error handling and thread timeout added to simulated matches to allow large AI tournaments without infinite length games due to loops. AI tournaments should now always finish - if the matches take too long they are scored as a draw.
This commit is contained in:
@@ -3,9 +3,12 @@ package forge.view;
|
||||
import java.io.File;
|
||||
import java.io.FilenameFilter;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.TimeoutException;
|
||||
|
||||
import forge.LobbyPlayer;
|
||||
import forge.deck.DeckGroup;
|
||||
import forge.game.*;
|
||||
import forge.properties.ForgeConstants;
|
||||
import forge.tournament.system.*;
|
||||
import forge.util.TextUtil;
|
||||
@@ -15,12 +18,6 @@ import org.apache.commons.lang3.time.StopWatch;
|
||||
|
||||
import forge.deck.Deck;
|
||||
import forge.deck.io.DeckSerializer;
|
||||
import forge.game.Game;
|
||||
import forge.game.GameLogEntry;
|
||||
import forge.game.GameRules;
|
||||
import forge.game.GameType;
|
||||
import forge.game.GameLogEntryType;
|
||||
import forge.game.Match;
|
||||
import forge.game.player.RegisteredPlayer;
|
||||
import forge.model.FModel;
|
||||
import forge.player.GamePlayerUtil;
|
||||
@@ -161,14 +158,38 @@ public class SimulateMatch {
|
||||
System.out.println("\tq - Quiet flag. Output just the game result, not the entire game log.");
|
||||
}
|
||||
|
||||
|
||||
|
||||
private static void simulateSingleMatch(Match mc, int iGame, boolean outputGamelog) {
|
||||
StopWatch sw = new StopWatch();
|
||||
sw.start();
|
||||
|
||||
Game g1 = mc.createGame();
|
||||
// will run match in the same thread
|
||||
mc.startGame(g1);
|
||||
sw.stop();
|
||||
|
||||
long startTime = System.currentTimeMillis();
|
||||
try {
|
||||
TimeLimitedCodeBlock.runWithTimeout(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
mc.startGame(g1);
|
||||
sw.stop();
|
||||
}
|
||||
}, 120, TimeUnit.SECONDS);
|
||||
}
|
||||
catch (TimeoutException e) {
|
||||
System.out.println("Stopping slow match as draw");
|
||||
g1.setGameOver(GameEndReason.Draw);
|
||||
sw.stop();
|
||||
}catch (Exception e){
|
||||
e.printStackTrace();
|
||||
g1.setGameOver(GameEndReason.Draw);
|
||||
sw.stop();
|
||||
}catch(StackOverflowError e){
|
||||
g1.setGameOver(GameEndReason.Draw);
|
||||
sw.stop();
|
||||
}
|
||||
|
||||
|
||||
List<GameLogEntry> log;
|
||||
if (outputGamelog) {
|
||||
|
||||
@@ -0,0 +1,46 @@
|
||||
package forge.view;
|
||||
|
||||
import java.util.concurrent.*;
|
||||
|
||||
/**
|
||||
* Created by maustin on 08/02/2018.
|
||||
*/
|
||||
public class TimeLimitedCodeBlock {
|
||||
|
||||
public static void runWithTimeout(final Runnable runnable, long timeout, TimeUnit timeUnit) throws Exception {
|
||||
runWithTimeout(new Callable<Object>() {
|
||||
@Override
|
||||
public Object call() throws Exception {
|
||||
runnable.run();
|
||||
return null;
|
||||
}
|
||||
}, timeout, timeUnit);
|
||||
}
|
||||
|
||||
public static <T> T runWithTimeout(Callable<T> callable, long timeout, TimeUnit timeUnit) throws Exception {
|
||||
final ExecutorService executor = Executors.newSingleThreadExecutor();
|
||||
final Future<T> future = executor.submit(callable);
|
||||
executor.shutdown(); // This does not cancel the already-scheduled task.
|
||||
try {
|
||||
return future.get(timeout, timeUnit);
|
||||
}
|
||||
catch (TimeoutException e) {
|
||||
//remove this if you do not want to cancel the job in progress
|
||||
//or set the argument to 'false' if you do not want to interrupt the thread
|
||||
future.cancel(true);
|
||||
throw e;
|
||||
}
|
||||
catch (ExecutionException e) {
|
||||
//unwrap the root cause
|
||||
Throwable t = e.getCause();
|
||||
if (t instanceof Error) {
|
||||
throw (Error) t;
|
||||
} else if (t instanceof Exception) {
|
||||
throw (Exception) t;
|
||||
} else {
|
||||
throw new IllegalStateException(t);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user