Skip to content

Commit 653c403

Browse files
Merge branch 'master' into public-release
2 parents 0d84876 + f040dc9 commit 653c403

File tree

9 files changed

+91
-9
lines changed

9 files changed

+91
-9
lines changed

engine/src/main/battlecode/common/Clock.java

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,27 @@ public static int getBytecodeNum() {
4747
return RobotMonitor.getBytecodeNum();
4848
}
4949

50+
/**
51+
* Returns the total amount of execution time left this team has before they timeout
52+
*
53+
* @return the amount of execution time remaining, in nanoseconds
54+
* @battlecode.doc.costlymethod
55+
*/
56+
public static long getTimeLeft() {
57+
return RobotMonitor.getTimeLeft();
58+
}
59+
60+
/**
61+
* Returns the total amount of time that this team's robots have collectively spent executing
62+
* since the beginning of the match.
63+
*
64+
* @return the total execution time, in nanoseconds
65+
* @battlecode.doc.costlymethod
66+
*/
67+
public static long getTimeElapsed() {
68+
return RobotMonitor.getTimeElapsed();
69+
}
70+
5071
/**
5172
* Prevent construction.
5273
*/

engine/src/main/battlecode/common/GameConstants.java

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -85,8 +85,14 @@ public class GameConstants {
8585
/** The percent of the map which a team needs to paint to win. */
8686
public static final int PAINT_PERCENT_TO_WIN = 70;
8787

88-
/** The maximum number of towers that a team can have. */
89-
public static final int MAX_NUMBER_OF_TOWERS = 25;
88+
/** The maximum number of towers that a team can have. */
89+
public static final int MAX_NUMBER_OF_TOWERS = 25;
90+
91+
/**
92+
* The maximum execution time that can be spent on a team in one match. If the total time spent executing a team's bots
93+
* exceeds this limit, the team will immediately lose the game. Execution time is measured in ns.
94+
*/
95+
public static final long MAX_TEAM_EXECUTION_TIME = 1200000000000L;
9096

9197
// *********************************
9298
// ****** GAME MECHANICS ***********

engine/src/main/battlecode/instrumenter/SandboxedRobotPlayer.java

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
import battlecode.instrumenter.stream.RoboPrintStream;
77
import battlecode.instrumenter.stream.SilencedPrintStream;
88
import battlecode.server.ErrorReporter;
9+
import battlecode.world.control.PlayerControlProvider;
910
import battlecode.server.Config;
1011

1112
import java.io.OutputStream;
@@ -111,7 +112,8 @@ public SandboxedRobotPlayer(String teamName,
111112
int seed,
112113
TeamClassLoaderFactory.Loader loader,
113114
OutputStream robotOut,
114-
Profiler profiler)
115+
Profiler profiler,
116+
PlayerControlProvider provider)
115117
throws InstrumentationException {
116118
this.robotController = robotController;
117119
this.seed = seed;
@@ -135,7 +137,7 @@ public SandboxedRobotPlayer(String teamName,
135137
setBytecodeLimitMethod = monitor.getMethod("setBytecodeLimit", int.class);
136138
getBytecodeNumMethod = monitor.getMethod("getBytecodeNum");
137139
pauseMethod = monitor.getMethod("pause");
138-
initMethod = monitor.getMethod("init", Pauser.class, Killer.class, int.class, Profiler.class);
140+
initMethod = monitor.getMethod("init", Pauser.class, Killer.class, int.class, Profiler.class, PlayerControlProvider.class);
139141

140142
// Note: loading this here also keeps any initialization we do in System
141143
// from inflicting its bytecode cost on the player.
@@ -175,7 +177,7 @@ public SandboxedRobotPlayer(String teamName,
175177
mainThread = new Thread(() -> {
176178
try {
177179
// Init RobotMonitor
178-
initMethod.invoke(null, pauser, killer, this.seed, profiler);
180+
initMethod.invoke(null, pauser, killer, this.seed, profiler, provider);
179181
// Pause immediately
180182
pauseMethod.invoke(null);
181183
// Run the robot!

engine/src/main/battlecode/instrumenter/bytecode/resources/MethodCosts.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
battlecode/common/Clock/yield 0 true
22
battlecode/common/Clock/getBytecodesLeft 0 false
33
battlecode/common/Clock/getBytecodeNum 0 false
4+
battlecode/common/Clock/getTimeLeft 0 false
5+
battlecode/common/Clock/getTimeElapsed 0 false
46
battlecode/common/Direction/equals 1 false
57
battlecode/common/Direction/getDeltaX 1 false
68
battlecode/common/Direction/getDeltaY 1 false

engine/src/main/battlecode/instrumenter/inject/RobotMonitor.java

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
import battlecode.instrumenter.SandboxedRobotPlayer;
44
import battlecode.instrumenter.profiler.Profiler;
55
import battlecode.server.ErrorReporter;
6+
import battlecode.world.control.PlayerControlProvider;
67

78
import java.io.PrintStream;
89
import java.lang.Math;
@@ -33,6 +34,7 @@ public final class RobotMonitor {
3334
private static SandboxedRobotPlayer.Killer killer;
3435

3536
private static Profiler profiler;
37+
private static PlayerControlProvider provider;
3638

3739
// Methods called from SandboxedRobotPlayer
3840

@@ -46,12 +48,14 @@ public final class RobotMonitor {
4648
* @param theKiller killer to use to kill the thread
4749
* @param seed seed to use for new Random instances
4850
* @param theProfiler profiler to log bytecode usage per method to (profiling is disabled if null)
51+
* @param theProvider player control provider to query computation time remaining
4952
*/
5053
@SuppressWarnings("unused")
5154
public static void init(SandboxedRobotPlayer.Pauser thePauser,
5255
SandboxedRobotPlayer.Killer theKiller,
5356
int seed,
54-
Profiler theProfiler) {
57+
Profiler theProfiler,
58+
PlayerControlProvider theProvider) {
5559
shouldDie = false;
5660
bytecodesLeft = 0;
5761
debugLevel = 0;
@@ -61,6 +65,7 @@ public static void init(SandboxedRobotPlayer.Pauser thePauser,
6165
killer = theKiller;
6266

6367
profiler = theProfiler;
68+
provider = theProvider;
6469
}
6570

6671
/**
@@ -111,6 +116,23 @@ public static int getBytecodesLeft() {
111116
return bytecodesLeft;
112117
}
113118

119+
/**
120+
* @return the bytecode number that the active robot is currently on.
121+
* Note that this can be above bytecodeLimit in some cases.
122+
*/
123+
@SuppressWarnings("unused")
124+
public static long getTimeElapsed() {
125+
return provider.getTimeElapsed();
126+
}
127+
128+
/**
129+
* @return the bytecodes this robot has left to use.
130+
*/
131+
@SuppressWarnings("unused")
132+
public static long getTimeLeft() {
133+
return provider.getTimeLeft();
134+
}
135+
114136
// Methods called from RobotPlayer
115137

116138
/**

engine/src/main/battlecode/server/ErrorReporter.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,10 @@
33
// TODO: pass messages along to the client
44
public class ErrorReporter {
55

6+
public static void warn(String message) {
7+
Server.warn(message + "\n\n");
8+
}
9+
610
// reports the error, and tells the contestant to contact the devs
711
public static void report(Throwable e) {
812
report(e, true);

engine/src/main/battlecode/world/control/PlayerControlProvider.java

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
package battlecode.world.control;
22

3+
import battlecode.common.GameConstants;
34
import battlecode.common.Team;
45
import battlecode.instrumenter.InstrumentationException;
56
import battlecode.instrumenter.TeamClassLoaderFactory;
@@ -70,6 +71,11 @@ public class PlayerControlProvider implements RobotControlProvider {
7071
*/
7172
private int matchId = -1;
7273

74+
/**
75+
* The total time the player's bots have spent executing, measured in ns
76+
*/
77+
private long totalPlayerTime = 0;
78+
7379
/**
7480
* Create a new PlayerControlProvider.
7581
*
@@ -95,6 +101,14 @@ public PlayerControlProvider(Team team,
95101
}
96102
}
97103

104+
public long getTimeElapsed() {
105+
return totalPlayerTime;
106+
}
107+
108+
public long getTimeLeft() {
109+
return Math.max(GameConstants.MAX_TEAM_EXECUTION_TIME - totalPlayerTime, 0L);
110+
}
111+
98112
@Override
99113
public void matchStarted(GameWorld gameWorld) {
100114
this.gameWorld = gameWorld;
@@ -116,6 +130,7 @@ public void matchEnded() {
116130

117131
this.sandboxes.clear();
118132
this.gameWorld = null;
133+
this.totalPlayerTime = 0;
119134
}
120135

121136
@Override
@@ -132,7 +147,8 @@ public void robotSpawned(InternalRobot robot) {
132147
robot.getID(),
133148
factory.createLoader(profiler != null),
134149
robotOut,
135-
profiler
150+
profiler,
151+
this
136152
);
137153
this.sandboxes.put(robot.getID(), player);
138154
} catch (InstrumentationException e) {
@@ -173,7 +189,13 @@ public void runRobot(InternalRobot robot) {
173189

174190
if (player != null) {
175191
player.setBytecodeLimit(robot.getBytecodeLimit());
192+
long timeBefore = System.nanoTime();
176193
player.step();
194+
totalPlayerTime += (System.nanoTime() - timeBefore);
195+
if(totalPlayerTime > GameConstants.MAX_TEAM_EXECUTION_TIME) {
196+
ErrorReporter.warn("Team " + team + " has timed out!");
197+
robot.getController().resign();
198+
}
177199
}
178200
}
179201

engine/src/test/battlecode/instrumenter/LoaderTest.java

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
package battlecode.instrumenter;
22

33
import battlecode.instrumenter.profiler.Profiler;
4+
import battlecode.world.control.PlayerControlProvider;
5+
46
import org.junit.Before;
57
import org.junit.BeforeClass;
68
import org.junit.Test;
@@ -69,8 +71,9 @@ public TeamClassLoaderFactory.Loader setupLoader(TeamClassLoaderFactory cache) t
6971
SandboxedRobotPlayer.Pauser.class,
7072
SandboxedRobotPlayer.Killer.class,
7173
int.class,
72-
Profiler.class)
73-
.invoke(null, pauser, killer, 0, null);
74+
Profiler.class,
75+
PlayerControlProvider.class)
76+
.invoke(null, pauser, killer, 0, null, null);
7477
monitor1.getMethod("setBytecodeLimit", int.class)
7578
.invoke(null, Integer.MAX_VALUE);
7679

specs/specs.pdf

4.38 KB
Binary file not shown.

0 commit comments

Comments
 (0)