Skip to content

Commit 3808f73

Browse files
committed
Added client configuration object to replace individual constructor arguments.
1 parent 7651dc7 commit 3808f73

File tree

4 files changed

+1217
-1159
lines changed

4 files changed

+1217
-1159
lines changed

src/main/java/bwapi/BWClient.java

Lines changed: 16 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -7,20 +7,10 @@
77
*/
88
public class BWClient {
99
private final BWEventListener eventListener;
10-
private final boolean debugConnection;
1110
private EventHandler handler;
1211

1312
public BWClient(final BWEventListener eventListener) {
14-
this(eventListener, false);
15-
}
16-
17-
/**
18-
* @param debugConnection set to `true` for more explicit error messages (might spam the terminal).
19-
* `false` by default
20-
*/
21-
public BWClient(final BWEventListener eventListener, final boolean debugConnection) {
2213
Objects.requireNonNull(eventListener);
23-
this.debugConnection = debugConnection;
2414
this.eventListener = eventListener;
2515
}
2616

@@ -32,16 +22,29 @@ public Game getGame() {
3222
}
3323

3424
public void startGame() {
35-
startGame(false);
25+
BWClientConfiguration configuration = new BWClientConfiguration();
26+
startGame(configuration);
3627
}
3728

3829
/**
3930
* Start the game.
4031
*
4132
* @param autoContinue automatically continue playing the next game(s). false by default
4233
*/
34+
@Deprecated
4335
public void startGame(boolean autoContinue) {
44-
Client client = new Client(debugConnection);
36+
BWClientConfiguration configuration = new BWClientConfiguration();
37+
configuration.autoContinue = autoContinue;
38+
startGame(configuration);
39+
}
40+
41+
/**
42+
* Start the game.
43+
*
44+
* @param configuration Settings for playing games with this client.
45+
*/
46+
public void startGame(BWClientConfiguration configuration) {
47+
Client client = new Client(configuration);
4548
client.reconnect();
4649
handler = new EventHandler(eventListener, client);
4750

@@ -59,6 +62,6 @@ public void startGame(boolean autoContinue) {
5962
client.reconnect();
6063
}
6164
}
62-
} while (autoContinue); // lgtm [java/constant-loop-condition]
65+
} while (configuration.autoContinue); // lgtm [java/constant-loop-condition]
6366
}
6467
}
Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
package bwapi;
2+
3+
/**
4+
* Configuration for constructing a BWClient
5+
*/
6+
public class BWClientConfiguration {
7+
8+
/**
9+
* When true, restarts the client loop when a game ends, allowing the client to play multiple games without restarting.
10+
*/
11+
public boolean autoContinue = false;
12+
13+
/**
14+
* Runs the bot in asynchronous mode. Asynchronous mode helps attempt to ensure that the bot adheres to real-time performance constraints.
15+
*
16+
* Humans playing StarCraft (and some tournaments) expect bots to return commands within a certain period of time; ~42ms for humans ("fastesT" game speed),
17+
* and some tournaments enforce frame-wise time limits (at time of writing, 55ms for COG and AIIDE; 85ms for SSCAIT).
18+
*
19+
* Asynchronous mode invokes bot event handlers in a separate thread, and if all event handlers haven't returned by a specified period of time, sends an
20+
* returns control to StarCraft, allowing the game to proceed while the bot continues to run in the background. This increases the likelihood of meeting
21+
* real-time performance requirements, while not fully guaranteeing it (subject to the whims of the JVM thread scheduler), at a cost of the bot possibly
22+
* issuing commands later than intended, and a marginally larger memory footprint.
23+
*/
24+
public boolean async = false;
25+
26+
/**
27+
* If JBWAPI detects that this much time (in nanoseconds) has passed since a bot's event handlers began, returns control back to BWAPI.
28+
* Real-time human play typically uses the "fastest" game speed, which has 42.86ms (42,860ns) between frames.
29+
*/
30+
public int asyncFrameDurationNanosMax = 40000;
31+
32+
/**
33+
* How frequently (in nanoseconds) to poll for the bot's event handlers completing. Acts as a floor on the bot's frame duration.
34+
*/
35+
public int asyncFrameDurationNanosMin = 500;
36+
37+
/**
38+
* The maximum number of frames to buffer while waiting on a bot
39+
*/
40+
public int asyncFrameBufferSize = 10;
41+
42+
/**
43+
* Most bot tournaments allow bots to take an indefinite amount of time on frame #0 (the first frame of the game) to analyze the map and load data,
44+
* as the bot has no prior access to BWAPI or game information.
45+
*
46+
* This flag causes JBWAPI to wait for the bot's event handlers to return on the first frame of the game, even if operating in asynchronous mode,
47+
* respecting the time bots are typically allowed on frame 0.
48+
*/
49+
public boolean asyncWaitOnFrameZero = true;
50+
51+
/**
52+
* Set to `true` for more explicit error messages (which might spam the terminal).
53+
*/
54+
public boolean debugConnection;
55+
}

src/main/java/bwapi/Client.java

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -60,10 +60,10 @@ public interface EventHandler {
6060
private ByteBuffer mapFileHandle = null;
6161
private ByteBuffer gameTableFileHandle = null;
6262

63-
private boolean debugConnection = false;
63+
private BWClientConfiguration configuration = new BWClientConfiguration();
6464

65-
Client(boolean debugConnection) {
66-
this.debugConnection = debugConnection;
65+
Client(BWClientConfiguration configuration) {
66+
this.configuration = configuration;
6767
}
6868

6969
/**
@@ -93,7 +93,7 @@ void reconnect(){
9393
}
9494

9595
void disconnect() {
96-
if (debugConnection) {
96+
if (configuration.debugConnection) {
9797
System.err.print("Disconnect called by: ");
9898
System.err.println(Thread.currentThread().getStackTrace()[2]);
9999
}
@@ -143,7 +143,7 @@ boolean connect() {
143143
}
144144
catch (Exception e) {
145145
System.err.println("Unable to map Game table.");
146-
if (debugConnection) {
146+
if (configuration.debugConnection) {
147147
e.printStackTrace();
148148
}
149149
return false;
@@ -177,7 +177,7 @@ boolean connect() {
177177
}
178178
catch (Exception e) {
179179
System.err.println("Unable to open communications pipe: " + communicationPipe);
180-
if (debugConnection) {
180+
if (configuration.debugConnection) {
181181
e.printStackTrace();
182182
}
183183
gameTableFileHandle = null;
@@ -192,7 +192,7 @@ boolean connect() {
192192
}
193193
catch (Exception e) {
194194
System.err.println("Unable to open shared memory mapping: " + sharedMemoryName);
195-
if (debugConnection) {
195+
if (configuration.debugConnection) {
196196
e.printStackTrace();
197197
}
198198
pipeObjectHandle = null;
@@ -205,7 +205,7 @@ boolean connect() {
205205
}
206206
catch (Exception e) {
207207
System.err.println("Unable to map game data.");
208-
if (debugConnection) {
208+
if (configuration.debugConnection) {
209209
e.printStackTrace();
210210
}
211211
return false;
@@ -226,7 +226,7 @@ boolean connect() {
226226
}
227227
catch (Exception e) {
228228
System.err.println("Unable to read pipe object.");
229-
if (debugConnection) {
229+
if (configuration.debugConnection) {
230230
e.printStackTrace();
231231
}
232232
disconnect();
@@ -246,7 +246,7 @@ void update(final EventHandler handler) {
246246
}
247247
catch (Exception e) {
248248
System.err.println("failed, disconnecting");
249-
if (debugConnection) {
249+
if (configuration.debugConnection) {
250250
e.printStackTrace();
251251
}
252252
disconnect();
@@ -258,7 +258,7 @@ void update(final EventHandler handler) {
258258
}
259259
catch (Exception e) {
260260
System.err.println("failed, disconnecting");
261-
if (debugConnection) {
261+
if (configuration.debugConnection) {
262262
e.printStackTrace();
263263
}
264264
disconnect();

0 commit comments

Comments
 (0)