Skip to content

Commit

Permalink
Merge pull request #69 from JavaBWAPI/issue#86
Browse files Browse the repository at this point in the history
Cache getInterceptor/getLoaded/getLarva
  • Loading branch information
JasperGeurtz authored Mar 13, 2021
2 parents d21d42e + cf6d051 commit e5521b2
Show file tree
Hide file tree
Showing 2 changed files with 66 additions and 9 deletions.
63 changes: 63 additions & 0 deletions src/main/java/bwapi/Game.java
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,11 @@ public final class Game {
private static final int REGION_DATA_SIZE = 5000;

private final Set<Integer> visibleUnits = new HashSet<>();
private final Map<Unit, List<Unit>> connectedUnits = new HashMap<>();
private int lastConnectedUnitsUpdate = -1;
private final Map<Unit, List<Unit>> loadedUnits = new HashMap<>();
private int lastLoadedUnitsUpdate = -1;

private List<Unit> allUnits;
private final ClientData clientData;

Expand Down Expand Up @@ -146,6 +151,10 @@ private static boolean hasPower(final int x, final int y, final UnitType unitTyp
*/
void init() {
visibleUnits.clear();
connectedUnits.clear();
lastConnectedUnitsUpdate = -1;
loadedUnits.clear();
lastLoadedUnitsUpdate = -1;

final int forceCount = gameData().getForceCount();
forces = new Force[forceCount];
Expand Down Expand Up @@ -310,6 +319,60 @@ void onFrame(final int frame) {
getAllUnits().forEach(u -> u.updatePosition(frame));
}

/**
* Lazily update connectedUnits. Only users of the calls pay for it, and only
* pay once per frame.
* Avoids previous O(n^2) implementation which would be costly for
* lategame carrier fights
*/
List<Unit> getConnected(final Unit unit) {
final int frame = getFrameCount();
if (lastConnectedUnitsUpdate < frame) {
connectedUnits.values().forEach(List::clear);
for (final Unit u : getAllUnits()) {
Unit owner = u.getCarrier();
if (owner == null) {
owner = u.getHatchery();
}
if (owner != null) {
if (!connectedUnits.containsKey(owner)) {
connectedUnits.put(owner, new ArrayList<>());
}
connectedUnits.get(owner).add(u);
}
}
lastConnectedUnitsUpdate = frame;
}
if (!connectedUnits.containsKey(unit)) {
return Collections.emptyList();
}
return Collections.unmodifiableList(connectedUnits.get(unit));
}

/**
* @see #getConnected
*/
List<Unit> getLoadedUnits(final Unit unit) {
final int frame = getFrameCount();
if (lastLoadedUnitsUpdate < frame) {
loadedUnits.values().forEach(List::clear);
for (final Unit u : getAllUnits()) {
final Unit owner = u.getTransport();
if (owner != null) {
if (!loadedUnits.containsKey(owner)) {
loadedUnits.put(owner, new ArrayList<>());
}
loadedUnits.get(owner).add(u);
}
}
lastLoadedUnitsUpdate = frame;
}
if (!loadedUnits.containsKey(unit)) {
return Collections.emptyList();
}
return Collections.unmodifiableList(loadedUnits.get(unit));
}

/**
* Retrieves the set of all teams/forces. Forces are commonly seen in @UMS
* game types and some others such as @TvB and the team versions of game types.
Expand Down
12 changes: 3 additions & 9 deletions src/main/java/bwapi/Unit.java
Original file line number Diff line number Diff line change
Expand Up @@ -1157,9 +1157,7 @@ public List<Unit> getLoadedUnits() {
if (getType().spaceProvided() < 1) {
return Collections.emptyList();
}
return game.getAllUnits().stream()
.filter(u -> equals(u.getTransport()))
.collect(Collectors.toList());
return game.getLoadedUnits(this);
}

/**
Expand Down Expand Up @@ -1199,9 +1197,7 @@ public List<Unit> getInterceptors() {
if (getType() != Protoss_Carrier && getType() != Hero_Gantrithor) {
return Collections.emptyList();
}
return game.getAllUnits().stream()
.filter(u -> equals(u.getCarrier()))
.collect(Collectors.toList());
return game.getConnected(this);
}

/**
Expand Down Expand Up @@ -1229,9 +1225,7 @@ public List<Unit> getLarva() {
if (!getType().producesLarva()) {
return Collections.emptyList();
}
return game.getAllUnits().stream()
.filter(u -> equals(u.getHatchery()))
.collect(Collectors.toList());
return game.getConnected(this);
}

public List<Unit> getUnitsInRadius(final int radius) {
Expand Down

0 comments on commit e5521b2

Please sign in to comment.