package bwapi;
import bwapi.ClientData.GameData;
import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.IntStream;
import static bwapi.CommandType.*;
import static bwapi.Point.TILE_WALK_FACTOR;
import static bwapi.Race.Zerg;
import static bwapi.UnitType.*;
/**
* The {@link Game} class is implemented by BWAPI and is the primary means of obtaining all
* game state information from Starcraft Broodwar. Game state information includes all units,
* resources, players, forces, bullets, terrain, fog of war, regions, etc.
*/
public final class Game {
private static final int[][] damageRatio = {
// Ind, Sml, Med, Lrg, Non, Unk
{0, 0, 0, 0, 0, 0}, // Independent
{0, 128, 192, 256, 0, 0}, // Explosive
{0, 256, 128, 64, 0, 0}, // Concussive
{0, 256, 256, 256, 0, 0}, // Normal
{0, 256, 256, 256, 0, 0}, // Ignore_Armor
{0, 0, 0, 0, 0, 0}, // None
{0, 0, 0, 0, 0, 0} // Unknown
};
private static final boolean[][] bPsiFieldMask = {
{false, false, false, false, false, true, true, true, true, true, true, false, false, false, false, false},
{false, false, true, true, true, true, true, true, true, true, true, true, true, true, false, false},
{false, true, true, true, true, true, true, true, true, true, true, true, true, true, true, false},
{true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true},
{true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true},
{true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true},
{true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true},
{false, true, true, true, true, true, true, true, true, true, true, true, true, true, true, false},
{false, false, true, true, true, true, true, true, true, true, true, true, true, true, false, false},
{false, false, false, false, false, true, true, true, true, true, true, false, false, false, false, false}
};
private static final int REGION_DATA_SIZE = 5000;
private final Set
* Units that are inside refineries are not included in this set.
*
* @return List
* This set includes resources that have been mined out or are inaccessible.
*
* @return List
* This set includes resources that are inaccessible.
*
* @return List
* This set includes units that are inaccessible.
*
* @return List
* Nuke dots are the red dots painted by a @Ghost when using the nuclear strike ability.
*
* @return Set of Positions giving the coordinates of nuke locations.
*/
public List
* Flags may only be enabled at the start of the match during the {@link BWEventListener#onStart}
* callback.
*
* @param flag The {@link Flag} entry describing the flag's effects on BWAPI.
* @return true if the given flag is enabled, false if the flag is disabled.
* @see Flag
*/
final public boolean isFlagEnabled(final Flag flag) {
return gameData().getFlags(flag.id);
}
/**
* Enables the state of a given flag.
*
* Flags may only be enabled at the start of the match during the {@link BWEventListener#onStart}
* callback.
*
* @param flag The {@link Flag} entry describing the flag's effects on BWAPI.
* @see Flag
*/
public void enableFlag(final Flag flag) {
addCommand(EnableFlag, flag.id, 1);
}
public List
* Campaign maps will return a hash of their internal map chunk components(.chk), while
* standard maps will return a hash of their entire map archive (.scm,.scx).
*/
public String mapHash() {
return mapHash;
}
/**
* Checks if the given mini-tile position is walkable.
*
* This function only checks if the static terrain is walkable. Its current occupied
* state is excluded from this check. To see if the space is currently occupied or not, then
* see {@link #getUnitsInRectangle}.
*
* @param walkX The x coordinate of the mini-tile, in mini-tile units (8 pixels).
* @param walkY The y coordinate of the mini-tile, in mini-tile units (8 pixels).
* @return true if the mini-tile is walkable and false if it is impassable for ground units.
*/
final public boolean isWalkable(final int walkX, final int walkY) {
return isWalkable(new WalkPosition(walkX, walkY));
}
final public boolean isWalkable(final WalkPosition position) {
return position.isValid(this) && walkable[position.x][position.y];
}
/**
* Returns the ground height at the given tile position.
*
* @param tileX X position to query, in tiles
* @param tileY Y position to query, in tiles
* @return The tile height as an integer. Possible values are:
* - 0: Low ground
* - 1: Low ground doodad
* - 2: High ground
* - 3: High ground doodad
* - 4: Very high ground
* - 5: Very high ground doodad
* .
*/
final public int getGroundHeight(final int tileX, final int tileY) {
return isValidTile(tileX, tileY) ? groundHeight[tileX][tileY] : 0;
}
final public int getGroundHeight(final TilePosition position) {
return getGroundHeight(position.x, position.y);
}
final public boolean isBuildable(final int tileX, final int tileY) {
return isBuildable(tileX, tileY, false);
}
/**
* Checks if a given tile position is buildable. This means that, if all
* other requirements are met, a structure can be placed on this tile. This function uses
* static map data.
*
* @param tileX The x value of the tile to check.
* @param tileY The y value of the tile to check.
* @param includeBuildings If this is true, then this function will also check if any visible structures are occupying the space. If this value is false, then it only checks the static map data for tile buildability. This value is false by default.
* @return boolean identifying if the given tile position is buildable (true) or not (false).
* If includeBuildings was provided, then it will return false if a structure is currently
* occupying the tile.
*/
final public boolean isBuildable(final int tileX, final int tileY, final boolean includeBuildings) {
return isValidTile(tileX, tileY) && buildable[tileX][tileY] && (!includeBuildings || !gameData().isOccupied(tileX, tileY));
}
final public boolean isBuildable(final TilePosition position) {
return isBuildable(position, false);
}
boolean isValidPosition(final int x, final int y) {
return x >= 0 && y >= 0 && x < mapPixelWidth && y < mapPixelHeight;
}
boolean isValidTile(final int x, final int y) {
return x >= 0 && y >= 0 && x < mapWidth && y < mapHeight;
}
final public boolean isBuildable(final TilePosition position, final boolean includeBuildings) {
return isBuildable(position.x, position.y, includeBuildings);
}
/**
* Checks if a given tile position is visible to the current player.
*
* @param tileX The x value of the tile to check.
* @param tileY The y value of the tile to check.
* @return boolean identifying the visibility of the tile. If the given tile is visible, then
* the value is true. If the given tile is concealed by the fog of war, then this value will
* be false.
*/
final public boolean isVisible(final int tileX, final int tileY) {
return isValidTile(tileX, tileY) && gameData().isVisible(tileX, tileY);
}
final public boolean isVisible(final TilePosition position) {
return isVisible(position.x, position.y);
}
/**
* Checks if a given tile position has been explored by the player. An
* explored tile position indicates that the player has seen the location at some point in the
* match, partially revealing the fog of war for the remainder of the match.
*
* @param tileX The x tile coordinate to check.
* @param tileY The y tile coordinate to check.
* @return true if the player has explored the given tile position (partially revealed fog), false if the tile position was never explored (completely black fog).
* @see #isVisible
*/
final public boolean isExplored(final int tileX, final int tileY) {
return isValidTile(tileX, tileY) && gameData().isExplored(tileX, tileY);
}
final public boolean isExplored(final TilePosition position) {
return isExplored(position.x, position.y);
}
/**
* Checks if the given tile position has @Zerg creep on it.
*
* @param tileX The x tile coordinate to check.
* @param tileY The y tile coordinate to check.
* @return true if the given tile has creep on it, false if the given tile does not have creep, or if it is concealed by the fog of war.
*/
final public boolean hasCreep(final int tileX, final int tileY) {
return isValidTile(tileX, tileY) && gameData().getHasCreep(tileX, tileY);
}
final public boolean hasCreep(final TilePosition position) {
return hasCreep(position.x, position.y);
}
final public boolean hasPowerPrecise(final int x, final int y) {
return hasPowerPrecise(new Position(x, y));
}
/**
* Checks if the given pixel position is powered by an owned @Protoss_Pylon for an
* optional unit type.
*
* @param x The x pixel coordinate to check.
* @param y The y pixel coordinate to check.
* @param unitType Checks if the given {@link UnitType} requires power or not. If ommitted, then it will assume that the position requires power for any unit type.
* @return true if the type at the given position will have power, false if the type at the given position will be unpowered.
*/
final public boolean hasPowerPrecise(final int x, final int y, final UnitType unitType) {
return isValidPosition(x, y) && hasPower(x, y, unitType, self().getUnits().stream().filter(u -> u.getType() == Protoss_Pylon).collect(Collectors.toList()));
}
final public boolean hasPowerPrecise(final Position position) {
return hasPowerPrecise(position.x, position.y, UnitType.None);
}
final public boolean hasPowerPrecise(final Position position, final UnitType unitType) {
return hasPowerPrecise(position.x, position.y, unitType);
}
final public boolean hasPower(final TilePosition position) {
return hasPower(position.x, position.y);
}
final public boolean hasPower(final int tileX, final int tileY) {
return hasPower(tileX, tileY, UnitType.None);
}
final public boolean hasPower(final TilePosition position, final UnitType unitType) {
return hasPower(position.x, position.y, unitType);
}
final public boolean hasPower(final int tileX, final int tileY, final UnitType unitType) {
if (unitType.id >= 0 && unitType.id < UnitType.None.id) {
return hasPowerPrecise(tileX * 32 + unitType.tileWidth() * 16, tileY * 32 + unitType.tileHeight() * 16, unitType);
}
return hasPowerPrecise(tileY * 32, tileY * 32, UnitType.None);
}
final public boolean hasPower(final int tileX, final int tileY, final int tileWidth, final int tileHeight) {
return hasPower(tileX, tileY, tileWidth, tileHeight, UnitType.Unknown);
}
/**
* Checks if the given tile position if powered by an owned @Protoss_Pylon for an
* optional unit type.
*
* @param tileX The x tile coordinate to check.
* @param tileY The y tile coordinate to check.
* @param unitType Checks if the given UnitType will be powered if placed at the given tile position. If omitted, then only the immediate tile position is checked for power, and the function will assume that the location requires power for any unit type.
* @return true if the type at the given tile position will receive power, false if the type will be unpowered at the given tile position.
*/
final public boolean hasPower(final int tileX, final int tileY, final int tileWidth, final int tileHeight, final UnitType unitType) {
return hasPowerPrecise(tileX * 32 + tileWidth * 16, tileY * 32 + tileHeight * 16, unitType);
}
final public boolean hasPower(final TilePosition position, final int tileWidth, final int tileHeight) {
return hasPower(position.x, position.y, tileWidth, tileHeight);
}
final public boolean hasPower(final TilePosition position, final int tileWidth, final int tileHeight, final UnitType unitType) {
return hasPower(position.x, position.y, tileWidth, tileHeight, unitType);
}
final public boolean canBuildHere(final TilePosition position, final UnitType type, final Unit builder) {
return canBuildHere(position, type, builder, false);
}
final public boolean canBuildHere(final TilePosition position, final UnitType type) {
return canBuildHere(position, type, null);
}
/**
* Checks if the given unit type can be built at the given build tile position.
* This function checks for creep, power, and resource distance requirements in addition to
* the tiles' buildability and possible units obstructing the build location.
*
* If the type is an addon and a builer is provided, then the location of the addon will
* be placed 4 tiles to the right and 1 tile down from the given position. If the builder
* is not given, then the check for the addon will be conducted at position.
*
* If type is UnitType.Special_Start_Location, then the area for a resource depot
* (@Command_Center, @Hatchery, @Nexus) is checked as normal, but any potential obstructions
* (existing structures, creep, units, etc.) are ignored.
*
* @param position Indicates the tile position that the top left corner of the structure is intended to go.
* @param type The UnitType to check for.
* @param builder The intended unit that will build the structure. If specified, then this function will also check if there is a path to the build site and exclude the builder from the set of units that may be blocking the build site.
* @param checkExplored If this parameter is true, it will also check if the target position has been explored by the current player. This value is false by default, ignoring the explored state of the build site.
* @return true indicating that the structure can be placed at the given tile position, and
* false if something may be obstructing the build location.
*/
final public boolean canBuildHere(final TilePosition position, final UnitType type, final Unit builder, final boolean checkExplored) {
// lt = left top, rb = right bottom
final TilePosition lt = builder != null && type.isAddon() ?
position.add(new TilePosition(4, 1)) : // addon build offset
position;
final TilePosition rb = lt.add(type.tileSize());
// Map limit check
if (!lt.isValid(this) || !(rb.toPosition().subtract(new Position(1, 1)).isValid(this))) {
return false;
}
//if the getUnit is a refinery, we just need to check the set of geysers to see if the position
//matches one of them (and the type is still vespene geyser)
if (type.isRefinery()) {
for (final Unit g : getGeysers()) {
if (g.getTilePosition().equals(lt)) {
return !g.isVisible() || g.getType() == Resource_Vespene_Geyser;
}
}
return false;
}
// Tile buildability check
for (int x = lt.x; x < rb.x; ++x) {
for (int y = lt.y; y < rb.y; ++y) {
// Check if tile is buildable/unoccupied and explored.
if (!isBuildable(x, y) || (checkExplored && !isExplored(x, y))) {
return false;
}
}
}
// Check if builder is capable of reaching the building site
if (builder != null) {
if (!builder.getType().isBuilding()) {
if (!builder.hasPath(lt.toPosition().add(type.tileSize().toPosition().divide(2)))) {
return false;
}
} else if (!builder.getType().isFlyingBuilding() && type != Zerg_Nydus_Canal && !type.isFlagBeacon()) {
return false;
}
}
// Ground getUnit dimension check
if (type != Special_Start_Location) {
final Position targPos = lt.toPosition().add(type.tileSize().toPosition().divide(2));
final List
* That text printed through this function is not seen by other players or in replays.
*
* @param string String to print.
*/
public void printf(final String string, final Text... colors) {
final String formatted = formatString(string, colors);
addCommand(Printf, formatted, 0);
}
/**
* Sends a text message to all other players in the game.
*
* In a single player game this function can be used to execute cheat codes.
*
* @param string String to send.
* @see #sendTextEx
*/
public void sendText(final String string, final Text... colors) {
sendTextEx(false, string, colors);
}
/**
* An extended version of {@link #sendText} which allows messages to be forwarded to
* allies.
*
* @param toAllies If this parameter is set to true, then the message is only sent to allied players, otherwise it will be sent to all players.
* @param string String to send.
* @see #sendText
*/
public void sendTextEx(final boolean toAllies, final String string, final Text... colors) {
final String formatted = formatString(string, colors);
addCommand(SendText, formatted, toAllies ? 1 : 0);
}
/**
* Checks if the current client is inside a game.
*
* @return true if the client is in a game, and false if it is not.
*/
final public boolean isInGame() {
return gameData().isInGame();
}
/**
* Checks if the current client is inside a multiplayer game.
*
* @return true if the client is in a multiplayer game, and false if it is a single player
* game, a replay, or some other state.
*/
final public boolean isMultiplayer() {
return multiplayer;
}
/**
* Checks if the client is in a game that was created through the Battle.net
* multiplayer gaming service.
*
* @return true if the client is in a multiplayer Battle.net game and false if it is not.
*/
final public boolean isBattleNet() {
return battleNet;
}
/**
* Checks if the current game is paused. While paused, {@link BWEventListener#onFrame}
* will still be called.
*
* @return true if the game is paused and false otherwise
* @see #pauseGame
* @see #resumeGame
*/
final public boolean isPaused() {
return gameData().isPaused();
}
/**
* Checks if the client is watching a replay.
*
* @return true if the client is watching a replay and false otherwise
*/
final public boolean isReplay() {
return replay;
}
/**
* Pauses the game. While paused, {@link BWEventListener#onFrame} will still be called.
*
* @see #resumeGame
*/
public void pauseGame() {
addCommand(PauseGame, 0, 0);
}
/**
* Resumes the game from a paused state.
*
* @see #pauseGame
*/
public void resumeGame() {
addCommand(ResumeGame, 0, 0);
}
/**
* Leaves the current game by surrendering and enters the post-game statistics/score
* screen.
*/
public void leaveGame() {
addCommand(LeaveGame, 0, 0);
}
/**
* Restarts the match. Works the same as if the match was restarted from
* the in-game menu (F10). This option is only available in single player games.
*/
public void restartGame() {
addCommand(RestartGame, 0, 0);
}
/**
* Sets the number of milliseconds Broodwar spends in each frame. The
* default values are as follows:
* - Fastest: 42ms/frame
* - Faster: 48ms/frame
* - Fast: 56ms/frame
* - Normal: 67ms/frame
* - Slow: 83ms/frame
* - Slower: 111ms/frame
* - Slowest: 167ms/frame
*
* Specifying a value of 0 will not guarantee that logical frames are executed as fast
* as possible. If that is the intention, use this in combination with #setFrameSkip.
*
* Changing this value will cause the execution of @UMS scenario triggers to glitch.
* This will only happen in campaign maps and custom scenarios (non-melee).
*
* @param speed The time spent per frame, in milliseconds. A value of 0 indicates that frames are executed immediately with no delay. Negative values will restore the default value as listed above.
* @see #setFrameSkip
* @see #getFPS
*/
public void setLocalSpeed(final int speed) {
addCommand(SetLocalSpeed, speed, 0);
}
/**
* Issues a given command to a set of units. This function automatically
* splits the set into groups of 12 and issues the same command to each of them. If a unit
* is not capable of executing the command, then it is simply ignored.
*
* @param units A List
* Example:
* `drawTextMap(50, 50, "%cHello %cWorld", Text.Red, Text.Blue)`
* will draw the text `Hello` in Red and `World` in Blue at offset (50, 50) from the TopLeft of the Map.
*/
public void drawTextMap(final int x, final int y, final String string, final Text... colors) {
drawText(CoordinateType.Map, x, y, string, colors);
}
/**
* Draw formatted text on the Map. (0, 0) coordinate is TopLeft of the Map.
* Use the %c delimiter to change the color of the following text to given `colors` until the next %c
*
* Example:
* `drawTextMap(new Position(50, 50), "%cHello %cWorld", Text.Red, Text.Blue)`
* will draw the text `Hello` in Red and `World` in Blue at offset (50, 50) from the TopLeft of the Map.
*/
public void drawTextMap(final Position p, final String string, final Text... colors) {
drawTextMap(p.x, p.y, string, colors);
}
/**
* Draw formatted text relative to the Mouse location. (0, 0) is the Mouse location.
* Use the %c delimiter to change the color of the following text to given `colors` until the next %c
*
* Example:
* `drawTextMouse(50, 50, "%cHello %cWorld", Text.Red, Text.Blue)`
* will draw the text `Hello` in Red and `World` in Blue at offset (50, 50) from the Mouse location.
*/
public void drawTextMouse(final int x, final int y, final String string, final Text... colors) {
drawText(CoordinateType.Mouse, x, y, string, colors);
}
/**
* Draw formatted text relative to the Mouse location. (0, 0) is the Mouse location.
* Use the %c delimiter to change the color of the following text to given `colors` until the next %c
*
* Example:
* `drawTextMouse(new Position(50, 50), "%cHello %cWorld", Text.Red, Text.Blue)`
* will draw the text `Hello` in Red and `World` in Blue at offset (50, 50) from the Mouse location.
*/
public void drawTextMouse(final Position p, final String string, final Text... colors) {
drawTextMouse(p.x, p.y, string, colors);
}
/**
* Draw formatted text relative to the Screen location. (0, 0) is TopLeft of the Screen.
* Use the %c delimiter to change the color of the following text to given `colors` until the next %c
*
* Example:
* `drawTextScreen(50, 50, "%cHello %cWorld", Text.Red, Text.Blue)`
* will draw the text `Hello` in Red and `World` in Blue at offset (50, 50) from the TopLeft of the Screen.
*/
public void drawTextScreen(final int x, final int y, final String string, final Text... colors) {
drawText(CoordinateType.Screen, x, y, string, colors);
}
/**
* Draw formatted text relative to the Screen location. (0, 0) is TopLeft of the Screen.
* Use the %c delimiter to change the color of the following text to given `colors` until the next %c
*
* Example:
* `drawTextScreen(new Position(50, 50), "%cHello %cWorld", Text.Red, Text.Blue)`
* will draw the text `Hello` in Red and `World` in Blue at offset (50, 50) from the TopLeft of the Screen.
*/
public void drawTextScreen(final Position p, final String string, final Text... colors) {
drawTextScreen(p.x, p.y, string, colors);
}
public void drawBox(final CoordinateType ctype, final int left, final int top, final int right, final int bottom, final Color color) {
drawBox(ctype, left, top, right, bottom, color, false);
}
/**
* Draws a rectangle on the screen with the given color.
*
* @param ctype The coordinate type. Indicates the relative position to draw the shape.
* @param left The x coordinate, in pixels, relative to ctype, of the left edge of the rectangle.
* @param top The y coordinate, in pixels, relative to ctype, of the top edge of the rectangle.
* @param right The x coordinate, in pixels, relative to ctype, of the right edge of the rectangle.
* @param bottom The y coordinate, in pixels, relative to ctype, of the bottom edge of the rectangle.
* @param color The color of the rectangle.
* @param isSolid If true, then the shape will be filled and drawn as a solid, otherwise it will be drawn as an outline. If omitted, this value will default to false.
*/
public void drawBox(final CoordinateType ctype, final int left, final int top, final int right, final int bottom, final Color color, final boolean isSolid) {
addShape(ShapeType.Box, ctype, left, top, right, bottom, 0, 0, color.id, isSolid);
}
public void drawBoxMap(int left, int top, int right, int bottom, Color color) {
drawBox(CoordinateType.Map, left, top, right, bottom, color);
}
public void drawBoxMap(int left, int top, int right, int bottom, Color color, boolean isSolid) {
drawBox(CoordinateType.Map, left, top, right, bottom, color, isSolid);
}
public void drawBoxMap(Position leftTop, Position rightBottom, Color color) {
drawBox(CoordinateType.Map, leftTop.x, leftTop.y, rightBottom.x, rightBottom.y, color);
}
public void drawBoxMap(Position leftTop, Position rightBottom, Color color, boolean isSolid) {
drawBox(CoordinateType.Map, leftTop.x, leftTop.y, rightBottom.x, rightBottom.y, color, isSolid);
}
public void drawBoxMouse(int left, int top, int right, int bottom, Color color) {
drawBox(CoordinateType.Mouse, left, top, right, bottom, color);
}
public void drawBoxMouse(int left, int top, int right, int bottom, Color color, boolean isSolid) {
drawBox(CoordinateType.Mouse, left, top, right, bottom, color, isSolid);
}
public void drawBoxMouse(Position leftTop, Position rightBottom, Color color) {
drawBox(CoordinateType.Mouse, leftTop.x, leftTop.y, rightBottom.x, rightBottom.y, color);
}
public void drawBoxMouse(Position leftTop, Position rightBottom, Color color, boolean isSolid) {
drawBox(CoordinateType.Mouse, leftTop.x, leftTop.y, rightBottom.x, rightBottom.y, color, isSolid);
}
public void drawBoxScreen(int left, int top, int right, int bottom, Color color) {
drawBox(CoordinateType.Screen, left, top, right, bottom, color);
}
public void drawBoxScreen(int left, int top, int right, int bottom, Color color, boolean isSolid) {
drawBox(CoordinateType.Screen, left, top, right, bottom, color, isSolid);
}
public void drawBoxScreen(Position leftTop, Position rightBottom, Color color) {
drawBox(CoordinateType.Screen, leftTop.x, leftTop.y, rightBottom.x, rightBottom.y, color);
}
public void drawBoxScreen(Position leftTop, Position rightBottom, Color color, boolean isSolid) {
drawBox(CoordinateType.Screen, leftTop.x, leftTop.y, rightBottom.x, rightBottom.y, color, isSolid);
}
public void drawTriangle(CoordinateType ctype, int ax, int ay, int bx, int by, int cx, int cy, Color color) {
drawTriangle(ctype, ax, ay, bx, by, cx, cy, color, false);
}
/**
* Draws a triangle on the screen with the given color.
*
* @param ctype The coordinate type. Indicates the relative position to draw the shape.
* @param ax The x coordinate, in pixels, relative to ctype, of the first point.
* @param ay The y coordinate, in pixels, relative to ctype, of the first point.
* @param bx The x coordinate, in pixels, relative to ctype, of the second point.
* @param by The y coordinate, in pixels, relative to ctype, of the second point.
* @param cx The x coordinate, in pixels, relative to ctype, of the third point.
* @param cy The y coordinate, in pixels, relative to ctype, of the third point.
* @param color The color of the triangle.
* @param isSolid If true, then the shape will be filled and drawn as a solid, otherwise it will be drawn as an outline. If omitted, this value will default to false.
*/
public void drawTriangle(CoordinateType ctype, int ax, int ay, int bx, int by, int cx, int cy, Color color, boolean isSolid) {
addShape(ShapeType.Triangle, ctype, ax, ay, bx, by, cx, cy, color.id, isSolid);
}
public void drawTriangleMap(int ax, int ay, int bx, int by, int cx, int cy, Color color) {
drawTriangle(CoordinateType.Map, ax, ay, bx, by, cx, cy, color);
}
public void drawTriangleMap(int ax, int ay, int bx, int by, int cx, int cy, Color color, boolean isSolid) {
drawTriangle(CoordinateType.Map, ax, ay, bx, by, cx, cy, color, isSolid);
}
public void drawTriangleMap(Position a, Position b, Position c, Color color) {
drawTriangle(CoordinateType.Map, a.x, a.y, b.x, b.y, c.x, c.y, color);
}
public void drawTriangleMap(Position a, Position b, Position c, Color color, boolean isSolid) {
drawTriangle(CoordinateType.Map, a.x, a.y, b.x, b.y, c.x, c.y, color, isSolid);
}
public void drawTriangleMouse(int ax, int ay, int bx, int by, int cx, int cy, Color color) {
drawTriangle(CoordinateType.Mouse, ax, ay, bx, by, cx, cy, color);
}
public void drawTriangleMouse(int ax, int ay, int bx, int by, int cx, int cy, Color color, boolean isSolid) {
drawTriangle(CoordinateType.Mouse, ax, ay, bx, by, cx, cy, color, isSolid);
}
public void drawTriangleMouse(Position a, Position b, Position c, Color color) {
drawTriangle(CoordinateType.Mouse, a.x, a.y, b.x, b.y, c.x, c.y, color);
}
public void drawTriangleMouse(Position a, Position b, Position c, Color color, boolean isSolid) {
drawTriangle(CoordinateType.Mouse, a.x, a.y, b.x, b.y, c.x, c.y, color, isSolid);
}
public void drawTriangleScreen(int ax, int ay, int bx, int by, int cx, int cy, Color color) {
drawTriangle(CoordinateType.Screen, ax, ay, bx, by, cx, cy, color);
}
public void drawTriangleScreen(int ax, int ay, int bx, int by, int cx, int cy, Color color, boolean isSolid) {
drawTriangle(CoordinateType.Screen, ax, ay, bx, by, cx, cy, color, isSolid);
}
public void drawTriangleScreen(Position a, Position b, Position c, Color color) {
drawTriangle(CoordinateType.Screen, a.x, a.y, b.x, b.y, c.x, c.y, color);
}
public void drawTriangleScreen(Position a, Position b, Position c, Color color, boolean isSolid) {
drawTriangle(CoordinateType.Screen, a.x, a.y, b.x, b.y, c.x, c.y, color, isSolid);
}
public void drawCircle(CoordinateType ctype, int x, int y, int radius, Color color) {
drawCircle(ctype, x, y, radius, color, false);
}
/**
* Draws a circle on the screen with the given color.
*
* @param ctype The coordinate type. Indicates the relative position to draw the shape.
* @param x The x coordinate, in pixels, relative to ctype.
* @param y The y coordinate, in pixels, relative to ctype.
* @param radius The radius of the circle, in pixels.
* @param color The color of the circle.
* @param isSolid If true, then the shape will be filled and drawn as a solid, otherwise it will be drawn as an outline. If omitted, this value will default to false.
*/
public void drawCircle(CoordinateType ctype, int x, int y, int radius, Color color, boolean isSolid) {
addShape(ShapeType.Circle, ctype, x, y, 0, 0, radius, 0, color.id, isSolid);
}
public void drawCircleMap(int x, int y, int radius, Color color) {
drawCircle(CoordinateType.Map, x, y, radius, color);
}
public void drawCircleMap(int x, int y, int radius, Color color, boolean isSolid) {
drawCircle(CoordinateType.Map, x, y, radius, color, isSolid);
}
public void drawCircleMap(Position p, int radius, Color color) {
drawCircle(CoordinateType.Map, p.x, p.y, radius, color);
}
public void drawCircleMap(Position p, int radius, Color color, boolean isSolid) {
drawCircle(CoordinateType.Map, p.x, p.y, radius, color, isSolid);
}
public void drawCircleMouse(int x, int y, int radius, Color color) {
drawCircle(CoordinateType.Mouse, x, y, radius, color);
}
public void drawCircleMouse(int x, int y, int radius, Color color, boolean isSolid) {
drawCircle(CoordinateType.Mouse, x, y, radius, color, isSolid);
}
public void drawCircleMouse(Position p, int radius, Color color) {
drawCircle(CoordinateType.Mouse, p.x, p.y, radius, color);
}
public void drawCircleMouse(Position p, int radius, Color color, boolean isSolid) {
drawCircle(CoordinateType.Mouse, p.x, p.y, radius, color, isSolid);
}
public void drawCircleScreen(int x, int y, int radius, Color color) {
drawCircle(CoordinateType.Screen, x, y, radius, color);
}
public void drawCircleScreen(int x, int y, int radius, Color color, boolean isSolid) {
drawCircle(CoordinateType.Screen, x, y, radius, color, isSolid);
}
public void drawCircleScreen(Position p, int radius, Color color) {
drawCircle(CoordinateType.Screen, p.x, p.y, radius, color);
}
public void drawCircleScreen(Position p, int radius, Color color, boolean isSolid) {
drawCircle(CoordinateType.Screen, p.x, p.y, radius, color, isSolid);
}
public void drawEllipse(CoordinateType ctype, int x, int y, int xrad, int yrad, Color color) {
drawEllipse(ctype, x, y, xrad, yrad, color, false);
}
/**
* Draws an ellipse on the screen with the given color.
*
* @param ctype The coordinate type. Indicates the relative position to draw the shape.
* @param x The x coordinate, in pixels, relative to ctype.
* @param y The y coordinate, in pixels, relative to ctype.
* @param xrad The x radius of the ellipse, in pixels.
* @param yrad The y radius of the ellipse, in pixels.
* @param color The color of the ellipse.
* @param isSolid If true, then the shape will be filled and drawn as a solid, otherwise it will be drawn as an outline. If omitted, this value will default to false.
*/
public void drawEllipse(CoordinateType ctype, int x, int y, int xrad, int yrad, Color color, boolean isSolid) {
addShape(ShapeType.Ellipse, ctype, x, y, 0, 0, xrad, yrad, color.id, isSolid);
}
public void drawEllipseMap(int x, int y, int xrad, int yrad, Color color) {
drawEllipse(CoordinateType.Map, x, y, xrad, yrad, color);
}
public void drawEllipseMap(int x, int y, int xrad, int yrad, Color color, boolean isSolid) {
drawEllipse(CoordinateType.Map, x, y, xrad, yrad, color, isSolid);
}
public void drawEllipseMap(Position p, int xrad, int yrad, Color color) {
drawEllipse(CoordinateType.Map, p.x, p.y, xrad, yrad, color);
}
public void drawEllipseMap(Position p, int xrad, int yrad, Color color, boolean isSolid) {
drawEllipse(CoordinateType.Map, p.x, p.y, xrad, yrad, color, isSolid);
}
public void drawEllipseMouse(int x, int y, int xrad, int yrad, Color color) {
drawEllipse(CoordinateType.Mouse, x, y, xrad, yrad, color);
}
public void drawEllipseMouse(int x, int y, int xrad, int yrad, Color color, boolean isSolid) {
drawEllipse(CoordinateType.Mouse, x, y, xrad, yrad, color, isSolid);
}
public void drawEllipseMouse(Position p, int xrad, int yrad, Color color) {
drawEllipse(CoordinateType.Mouse, p.x, p.y, xrad, yrad, color);
}
public void drawEllipseMouse(Position p, int xrad, int yrad, Color color, boolean isSolid) {
drawEllipse(CoordinateType.Mouse, p.x, p.y, xrad, yrad, color, isSolid);
}
public void drawEllipseScreen(int x, int y, int xrad, int yrad, Color color) {
drawEllipse(CoordinateType.Screen, x, y, xrad, yrad, color);
}
public void drawEllipseScreen(int x, int y, int xrad, int yrad, Color color, boolean isSolid) {
drawEllipse(CoordinateType.Mouse, x, y, xrad, yrad, color, isSolid);
}
public void drawEllipseScreen(Position p, int xrad, int yrad, Color color) {
drawEllipse(CoordinateType.Mouse, p.x, p.y, xrad, yrad, color);
}
public void drawEllipseScreen(Position p, int xrad, int yrad, Color color, boolean isSolid) {
drawEllipse(CoordinateType.Mouse, p.x, p.y, xrad, yrad, color, isSolid);
}
/**
* Draws a dot on the map or screen with a given color.
*
* @param ctype The coordinate type. Indicates the relative position to draw the shape.
* @param x The x coordinate, in pixels, relative to ctype.
* @param y The y coordinate, in pixels, relative to ctype.
* @param color The color of the dot.
*/
public void drawDot(CoordinateType ctype, int x, int y, Color color) {
addShape(ShapeType.Dot, ctype, x, y, 0, 0, 0, 0, color.id, false);
}
public void drawDotMap(int x, int y, Color color) {
drawDot(CoordinateType.Map, x, y, color);
}
public void drawDotMap(Position p, Color color) {
drawDot(CoordinateType.Map, p.x, p.y, color);
}
public void drawDotMouse(int x, int y, Color color) {
drawDot(CoordinateType.Mouse, x, y, color);
}
public void drawDotMouse(Position p, Color color) {
drawDot(CoordinateType.Mouse, p.x, p.y, color);
}
public void drawDotScreen(int x, int y, Color color) {
drawDot(CoordinateType.Screen, x, y, color);
}
public void drawDotScreen(Position p, Color color) {
drawDot(CoordinateType.Screen, p.x, p.y, color);
}
/**
* Draws a line on the map or screen with a given color.
*
* @param ctype The coordinate type. Indicates the relative position to draw the shape.
* @param x1 The starting x coordinate, in pixels, relative to ctype.
* @param y1 The starting y coordinate, in pixels, relative to ctype.
* @param x2 The ending x coordinate, in pixels, relative to ctype.
* @param y2 The ending y coordinate, in pixels, relative to ctype.
* @param color The color of the line.
*/
public void drawLine(CoordinateType ctype, int x1, int y1, int x2, int y2, Color color) {
addShape(ShapeType.Line, ctype, x1, y1, x2, y2, 0, 0, color.id, false);
}
public void drawLineMap(int x1, int y1, int x2, int y2, Color color) {
drawLine(CoordinateType.Map, x1, y1, x2, y2, color);
}
public void drawLineMap(Position a, Position b, Color color) {
drawLine(CoordinateType.Map, a.x, a.y, b.x, b.y, color);
}
public void drawLineMouse(int x1, int y1, int x2, int y2, Color color) {
drawLine(CoordinateType.Mouse, x1, y1, x2, y2, color);
}
public void drawLineMouse(Position a, Position b, Color color) {
drawLine(CoordinateType.Mouse, a.x, a.y, b.x, b.y, color);
}
public void drawLineScreen(int x1, int y1, int x2, int y2, Color color) {
drawLine(CoordinateType.Screen, x1, y1, x2, y2, color);
}
public void drawLineScreen(Position a, Position b, Color color) {
drawLine(CoordinateType.Screen, a.x, a.y, b.x, b.y, color);
}
/**
* Retrieves the maximum delay, in number of frames, between a command being issued
* and the command being executed by Broodwar.
*
* In Broodwar, latency is used to keep the game synchronized between players without
* introducing lag.
*
* @return Difference in frames between commands being sent and executed.
* @see #getLatencyTime
* @see #getRemainingLatencyFrames
*/
public int getLatencyFrames() {
return gameData().getLatencyFrames();
}
/**
* Retrieves the maximum delay, in milliseconds, between a command being issued and
* the command being executed by Broodwar.
*
* @return Difference in milliseconds between commands being sent and executed.
* @see #getLatencyFrames
* @see #getRemainingLatencyTime
*/
public int getLatencyTime() {
return gameData().getLatencyTime();
}
/**
* Retrieves the number of frames it will take before a command sent in the current
* frame will be executed by the game.
*
* @return Number of frames until a command is executed if it were sent in the current
* frame.
* @see #getRemainingLatencyTime
* @see #getLatencyFrames
*/
public int getRemainingLatencyFrames() {
return gameData().getRemainingLatencyFrames();
}
/**
* Retrieves the number of milliseconds it will take before a command sent in the
* current frame will be executed by Broodwar.
*
* @return Amount of time, in milliseconds, until a command is executed if it were sent in
* the current frame.
* @see #getRemainingLatencyFrames
* @see #getLatencyTime
*/
public int getRemainingLatencyTime() {
return gameData().getRemainingLatencyTime();
}
/**
* Retrieves the current revision of BWAPI.
*
* @return The revision number of the current BWAPI interface.
*/
public int getRevision() {
return revision;
}
/**
* Retrieves the debug state of the BWAPI build.
*
* @return true if the BWAPI module is a DEBUG build, and false if it is a RELEASE build.
*/
final public boolean isDebug() {
return debug;
}
/**
* Checks the state of latency compensation.
*
* @return true if latency compensation is enabled, false if it is disabled.
* @see #setLatCom
*/
final public boolean isLatComEnabled() {
return latcom;
}
/**
* Changes the state of latency compensation. Latency compensation
* modifies the state of BWAPI's representation of units to reflect the implications of
* issuing a command immediately after the command was performed, instead of waiting
* consecutive frames for the results. Latency compensation is enabled by default.
*
* @param isEnabled Set whether the latency compensation feature will be enabled (true) or disabled (false).
* @see #isLatComEnabled
*/
public void setLatCom(final boolean isEnabled) {
if (isEnabled && configuration.getAsync()) {
throw new IllegalStateException("Latency compensation is not compatible with JBWAPI asynchronous mode.");
}
//update shared memory
gameData().setHasLatCom(isEnabled);
//update internal memory
latcom = isEnabled;
//update server
addCommand(SetLatCom, isEnabled ? 1 : 0, 0);
}
/**
* Retrieves the Starcraft instance number recorded by BWAPI to identify which
* Starcraft instance an AI module belongs to. The very first instance should
* return 0.
*
* @return An integer value representing the instance number.
*/
public int getInstanceNumber() {
return gameData().getInstanceID();
}
public int getAPM() {
return getAPM(false);
}
/**
* Retrieves the Actions Per Minute (APM) that the bot is producing.
*
* @param includeSelects If true, the return value will include selections as individual commands, otherwise it will exclude selections. This value is false by default.
* @return The number of actions that the bot has executed per minute, on average.
*/
public int getAPM(final boolean includeSelects) {
return includeSelects ? gameData().getBotAPM_selects() : gameData().getBotAPM_noselects();
}
/**
* Sets the number of graphical frames for every logical frame. This
* allows the game to step more logical frames per graphical frame, increasing the speed at
* which the game runs.
*
* @param frameSkip Number of graphical frames per logical frame. If this value is 0 or less, then it will default to 1.
* @see #setLocalSpeed
*/
public void setFrameSkip(int frameSkip) {
addCommand(SetFrameSkip, Math.max(frameSkip, 1), 0);
}
/**
* Sets the alliance state of the current player with the target player.
*
* @param player The target player to set alliance with.
* @param allied If true, the current player will ally the target player. If false, the current player
* will make the target player an enemy. This value is true by default.
* @param alliedVictory Sets the state of "allied victory". If true, the game will end in a victory if all
* allied players have eliminated their opponents. Otherwise, the game will only end if
* no other players are remaining in the game. This value is true by default.
*/
final public boolean setAlliance(Player player, boolean allied, boolean alliedVictory) {
if (self() == null || isReplay() || player == null || player.equals(self())) {
return false;
}
addCommand(CommandType.SetAllies, player.getID(), allied ? (alliedVictory ? 2 : 1) : 0);
return true;
}
final public boolean setAlliance(Player player, boolean allied) {
return setAlliance(player, allied, true);
}
final public boolean setAlliance(Player player) {
return setAlliance(player, true);
}
/**
* In a game, this function sets the vision of the current BWAPI player with the
* target player.
*
* In a replay, this function toggles the visibility of the target player.
*
* @param player The target player to toggle vision.
* @param enabled The vision state. If true, and in a game, the current player will enable shared vision
* with the target player, otherwise it will unshare vision. If in a replay, the vision
* of the target player will be shown, otherwise the target player will be hidden. This
* value is true by default.
*/
final public boolean setVision(Player player, boolean enabled) {
if (player == null) {
return false;
}
if (!isReplay() && (self() == null || player.equals(self()))) {
return false;
}
addCommand(CommandType.SetVision, player.getID(), enabled ? 1 : 0);
return true;
}
/**
* Checks if the GUI is enabled.
*
* The GUI includes all drawing functions of BWAPI, as well as screen updates from Broodwar.
*
* @return true if the GUI is enabled, and everything is visible, false if the GUI is disabled and drawing
* functions are rejected
* @see #setGUI
*/
boolean isGUIEnabled() {
return gameData().getHasGUI();
}
/**
* Sets the rendering state of the Starcraft GUI.
*
* This typically gives Starcraft a very low graphical frame rate and disables all drawing functionality in BWAPI.
*
* @param enabled A boolean value that determines the state of the GUI. Passing false to this function
* will disable the GUI, and true will enable it.
* @see #isGUIEnabled
*/
public void setGUI(boolean enabled) {
gameData().setHasGUI(enabled);
//queue up command for server so it also applies the change
addCommand(CommandType.SetGui, enabled ? 1 : 0, 0);
}
/**
* Retrieves the amount of time (in milliseconds) that has elapsed when running the last AI
* module callback.
*
* This is used by tournament modules to penalize AI modules that use too
* much processing time.
*
* @return Time in milliseconds spent in last AI module call. Returns 0 When called from an AI module.
*/
public int getLastEventTime() {
return 0;
}
/**
* Changes the map to the one specified.
*
* Once restarted, the game will load the map that was provided.
* Changes do not take effect unless the game is restarted.
*
* @param mapFileName A string containing the path and file name to the desired map.
* @return Returns true if the function succeeded and has changed the map. Returns false if the function failed,
* does not have permission from the tournament module, failed to find the map specified, or received an invalid
* parameter.
*/
final public boolean setMap(final String mapFileName) {
if (mapFileName == null || mapFileName.length() >= 260 || mapFileName.charAt(0) == 0) {
return false;
}
addCommand(CommandType.SetMap, mapFileName, 0);
return true;
}
/**
* Sets the state of the fog of war when watching a replay.
*
* @param reveal The state of the reveal all flag. If false, all fog of war will be enabled. If true,
* then the fog of war will be revealed. It is true by default.
*/
final public boolean setRevealAll(boolean reveal) {
if (!isReplay()) {
return false;
}
addCommand(CommandType.SetRevealAll, reveal ? 1 : 0, 0);
return true;
}
final public boolean setRevealAll() {
return setRevealAll(true);
}
/**
* Checks if there is a path from source to destination. This only checks
* if the source position is connected to the destination position. This function does not
* check if all units can actually travel from source to destination. Because of this
* limitation, it has an O(1) complexity, and cases where this limitation hinders gameplay is
* uncommon at best.
*
* If making queries on a unit, it's better to call {@link Unit#hasPath}, since it is
* a more lenient version of this function that accounts for some edge cases.
*
* @param source The source position.
* @param destination The destination position.
* @return true if there is a path between the two positions, and false if there is not.
* @see Unit#hasPath
*/
final public boolean hasPath(final Position source, final Position destination) {
if (source == null || destination == null) {
return false;
}
if (source.isValid(this) && destination.isValid(this)) {
final Region rgnA = getRegionAt(source);
final Region rgnB = getRegionAt(destination);
return rgnA != null && rgnB != null && rgnA.getRegionGroupID() == rgnB.getRegionGroupID();
}
return false;
}
public void setTextSize() {
setTextSize(Text.Size.Default);
}
/**
* Sets the size of the text for all calls to {@link #drawText} following this one.
*
* @param size The size of the text. This value is one of Text#Size. If this value is omitted, then a default value of {@link Text.Size#Default} is used.
* @see Text.Size
*/
public void setTextSize(final Text.Size size) {
textSize = size;
}
/**
* Retrieves current amount of time in seconds that the game has elapsed.
*
* @return Time, in seconds, that the game has elapsed as an integer.
*/
public int elapsedTime() {
return gameData().getElapsedTime();
}
/**
* Sets the command optimization level. Command optimization is a feature
* in BWAPI that tries to reduce the APM of the bot by grouping or eliminating unnecessary
* game actions. For example, suppose the bot told 24 @Zerglings to @Burrow. At command
* optimization level 0, BWAPI is designed to select each Zergling to burrow individually,
* which costs 48 actions. With command optimization level 1, it can perform the same
* behaviour using only 4 actions. The command optimizer also reduces the amount of bytes used
* for each action if it can express the same action using a different command. For example,
* Right_Click uses less bytes than Move.
*
* @param level An integer representation of the aggressiveness for which commands are optimized. A lower level means less optimization, and a higher level means more optimization.
*
* The values for level are as follows:
* - 0: No optimization.
* - 1: Some optimization.
* - Is not detected as a hack.
* - Does not alter behaviour.
* - Units performing the following actions are grouped and ordered 12 at a time:
* - Attack_Unit
* - Morph (@Larva only)
* - Hold_Position
* - Stop
* - Follow
* - Gather
* - Return_Cargo
* - Repair
* - Burrow
* - Unburrow
* - Cloak
* - Decloak
* - Siege
* - Unsiege
* - Right_Click_Unit
* - Halt_Construction
* - Cancel_Train (@Carrier and @Reaver only)
* - Cancel_Train_Slot (@Carrier and @Reaver only)
* - Cancel_Morph (for non-buildings only)
* - Use_Tech
* - Use_Tech_Unit
* .
* - The following order transformations are applied to allow better grouping:
* - Attack_Unit becomes Right_Click_Unit if the target is an enemy
* - Move becomes Right_Click_Position
* - Gather becomes Right_Click_Unit if the target contains resources
* - Set_Rally_Position becomes Right_Click_Position for buildings
* - Set_Rally_Unit becomes Right_Click_Unit for buildings
* - Use_Tech_Unit with Infestation becomes Right_Click_Unit if the target is valid
* .
* .
* - 2: More optimization by grouping structures.
* - Includes the optimizations made by all previous levels.
* - May be detected as a hack by some replay utilities.
* - Does not alter behaviour.
* - Units performing the following actions are grouped and ordered 12 at a time:
* - Attack_Unit (@Turrets, @Photon_Cannons, @Sunkens, @Spores)
* - Train
* - Morph
* - Set_Rally_Unit
* - Lift
* - Cancel_Construction
* - Cancel_Addon
* - Cancel_Train
* - Cancel_Train_Slot
* - Cancel_Morph
* - Cancel_Research
* - Cancel_Upgrade
* .
* .
* - 3: Extensive optimization
* - Includes the optimizations made by all previous levels.
* - Units may behave or move differently than expected.
* - Units performing the following actions are grouped and ordered 12 at a time:
* - Attack_Move
* - Set_Rally_Position
* - Move
* - Patrol
* - Unload_All
* - Unload_All_Position
* - Right_Click_Position
* - Use_Tech_Position
* .
* .
* - 4: Aggressive optimization
* - Includes the optimizations made by all previous levels.
* - Positions used in commands will be rounded to multiples of 32.
* - @High_Templar and @Dark_Templar that merge into @Archons will be grouped and may
* choose a different target to merge with. It will not merge with a target that
* wasn't included.
* .
* .
*/
public void setCommandOptimizationLevel(final int level) {
addCommand(SetCommandOptimizerLevel, level, 0);
}
/**
* Returns the remaining countdown time. The countdown timer is used in @CTF and @UMS game types.
*
* @return Integer containing the time (in game seconds) on the countdown timer.
*/
public int countdownTimer() {
return gameData().getCountdownTimer();
}
/**
* Retrieves the set of all regions on the map.
*
* @return List
* This function is nearly the same as {@link #getDamageFrom}. The only difference is that
* the last parameter is intended to default to {@link #self}.
*
* @param toType The unit type that will be receiving the damage.
* @param fromType The unit type that will be dealing the damage.
* @param toPlayer The player owner of the type that will be receiving the damage. If omitted, then no player will be used to calculate the upgrades for toType.
* @param fromPlayer The player owner of the given type that will be dealing the damage. If omitted, then this parameter will default to {@link #self}).
* @return The amount of damage that fromType would deal to toType.
* @see #getDamageFrom
*/
public int getDamageTo(final UnitType toType, final UnitType fromType, final Player toPlayer, final Player fromPlayer) {
return getDamageFromImpl(fromType, toType, fromPlayer == null ? self() : fromPlayer, toPlayer);
}
/**
* Retrieves the initial random seed that was used in this game's creation.
* This is used to identify the seed that started this game, in case an error occurred, so
* that developers can deterministically reproduce the error. Works in both games and replays.
*
* @return This game's random seed.
* @since 4.2.0
*/
public int getRandomSeed() {
return randomSeed;
}
/**
* Convenience method for adding a unit command from raw arguments.
*/
void addUnitCommand(final int type, final int unit, final int target, final int x, final int y, final int extra) {
enqueueOrDo(SideEffect.addUnitCommand(type, unit, target, x, y, extra));
}
/**
* Convenience method for adding a game command from raw arguments.
*/
void addCommand(final CommandType type, final int value1, final int value2) {
enqueueOrDo(SideEffect.addCommand(type, value1, value2));
}
/**
* Convenience method for adding a game command from raw arguments.
*/
void addCommand(final CommandType type, final String value1, final int value2) {
enqueueOrDo(SideEffect.addCommand(type, value1, value2));
}
/**
* Convenience method for adding a shape from raw arguments.
*/
void addShape(final ShapeType type, final CoordinateType coordType, final int x1, final int y1, final int x2, final int y2, final int extra1, final int extra2, final int color, final boolean isSolid) {
enqueueOrDo(SideEffect.addShape(type, coordType, x1, y1, x2, y2, extra1, extra2, color, isSolid));
}
/**
* Convenience method for adding a shape from raw arguments.
*/
void addShape(final ShapeType type, final CoordinateType coordType, final int x1, final int y1, final int x2, final int y2, final String text, final int extra2, final int color, final boolean isSolid) {
enqueueOrDo(SideEffect.addShape(type, coordType, x1, y1, x2, y2, text, extra2, color, isSolid));
}
/**
* Applies a side effect, either immediately (if operating synchronously)
* or by enqueuing it for later execution (if operating asynchronously).
*
* @param sideEffect
*/
void enqueueOrDo(SideEffect sideEffect) {
if (configuration.getAsync()) {
sideEffects.enqueue(sideEffect);
} else {
sideEffect.apply(gameData());
}
}
void setAllUnits(List