Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 0 additions & 2 deletions src/main/java/bwapi/Bullet.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,6 @@

import bwapi.ClientData.BulletData;

import java.util.Objects;

/**
* An object representing a bullet or missile spawned from an attack.
* <p>
Expand Down
90 changes: 89 additions & 1 deletion src/main/java/bwapi/Cache.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,14 @@
package bwapi;

import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.function.Supplier;
import java.util.stream.Collectors;

class Cache<T> {
private int frame = -1;
Expand Down Expand Up @@ -35,4 +44,83 @@ class BooleanCache extends Cache<Boolean>{}
class OrderCache extends Cache<Order>{}
class UnitTypeCache extends Cache<UnitType>{}
class UpgradeTypeCache extends Cache<UpgradeType>{}
class TechTypeCache extends Cache<TechType>{}
class TechTypeCache extends Cache<TechType>{}

class ConnectedUnitCache {
private int lastUpdate = -1;
private final Map<Unit, List<Unit>> connectedUnits = new HashMap<>();
private final Function<Unit, Unit> condition;
private final Game game;

ConnectedUnitCache(final Game game, final Function<Unit, Unit> condition) {
this.game = game;
this.condition = condition;
}

/**
* 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 = game.getFrameCount();
if (lastUpdate < frame) {
connectedUnits.values().forEach(List::clear);
for (final Unit u : game.getAllUnits()) {
final Unit owner = condition.apply(u);
if (owner != null) {
connectedUnits.computeIfAbsent(owner, k -> new ArrayList<>()).add(u);
}
}
lastUpdate = frame;
}
List<Unit> connected = connectedUnits.get(unit);
return connected == null ?
Collections.emptyList() :
Collections.unmodifiableList(connected);
}

void reset() {
lastUpdate = -1;
connectedUnits.clear();
}
}

/**
* Lazily filters and caches an unmodifiable List<Unit> at most once per frame.
* Only callers of the corresponding getter pay for the filtering, and at most once per frame.
*/
class UnitListCache {
private final Game game;
private final Supplier<List<Unit>> source;
private final Predicate<Unit> filter;
private int lastFrame = -1;
private List<Unit> cached = Collections.emptyList();

UnitListCache(final Game game, final Predicate<Unit> filter) {
this(game, game::getAllUnits, filter);
}

UnitListCache(final Game game, final Supplier<List<Unit>> source, final Predicate<Unit> filter) {
this.game = game;
this.source = source;
this.filter = filter;
}

List<Unit> get() {
final int frame = game.getFrameCount();
if (lastFrame != frame) {
cached = source.get().stream()
.filter(filter)
.collect(Collectors.collectingAndThen(Collectors.toList(), Collections::unmodifiableList));
lastFrame = frame;
}
return cached;
}

void reset() {
lastFrame = -1;
cached = Collections.emptyList();
}
}
1 change: 0 additions & 1 deletion src/main/java/bwapi/Color.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@

import java.util.HashMap;
import java.util.Map;
import java.util.Objects;

/**
* The Color object is used in drawing routines to specify the color to use.
Expand Down
8 changes: 4 additions & 4 deletions src/main/java/bwapi/CommandTemp.java
Original file line number Diff line number Diff line change
Expand Up @@ -330,7 +330,7 @@ void execute(boolean isCurrentFrame) {
case Cancel_Train_Slot:
if (command.extra != 0) {
if (eventType == EventType.Resource) {
UnitType unitType = unit.getTrainingQueue().get(command.extra);
UnitType unitType = unit.getTrainingQueueAt(command.extra);
player.self().minerals.setOrAdd(unitType.mineralPrice(), frame);
player.self().gas.setOrAdd(unitType.gasPrice(), frame);

Expand All @@ -351,7 +351,7 @@ void execute(boolean isCurrentFrame) {
case Cancel_Train: {
switch (eventType) {
case Resource: {
UnitType unitType = unit.getTrainingQueue().get(unit.getTrainingQueueCount() - 1);
UnitType unitType = unit.getTrainingQueueAt(unit.getTrainingQueueCount() - 1);
player.self().minerals.setOrAdd(unitType.mineralPrice(), frame);
player.self().gas.setOrAdd(unitType.gasPrice(), frame);

Expand All @@ -366,14 +366,14 @@ void execute(boolean isCurrentFrame) {

case Order: {
unit.self().trainingQueueCount.setOrAdd(-1, frame);
UnitType unitType = unit.getTrainingQueue().get(unit.getTrainingQueueCount());
UnitType unitType = unit.getTrainingQueueAt(unit.getTrainingQueueCount());
player.self().supplyUsed[unitType.getRace().id]
.setOrAdd(-unitType.supplyRequired(), frame);

if (unit.getTrainingQueueCount() == 0) {
unit.self().buildType.set(UnitType.None, frame);
} else {
UnitType ut = unit.getTrainingQueue().get(unit.getTrainingQueueCount() - 1);
UnitType ut = unit.getTrainingQueueAt(unit.getTrainingQueueCount() - 1);
// Actual time decreases, but we'll let it be the buildTime until latency catches up.
unit.self().remainingTrainTime.set(ut.buildTime(), frame);
unit.self().buildType.set(ut, frame);
Expand Down
44 changes: 0 additions & 44 deletions src/main/java/bwapi/ConnectedUnitCache.java

This file was deleted.

1 change: 0 additions & 1 deletion src/main/java/bwapi/Force.java
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
import bwapi.ClientData.ForceData;

import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

/**
Expand Down
Loading
Loading