Repository navigation
Expand file tree
/
Copy pathCache.java
More file actions
126 lines (109 loc) · 3.5 KB
/
Copy pathCache.java
File metadata and controls
126 lines (109 loc) · 3.5 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
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;
private T obj;
void set(T obj, int frame) {
this.frame = frame;
this.obj = obj;
}
boolean valid(int currentFrame) {
return frame == currentFrame;
}
T get() {
return obj;
}
}
class IntegerCache extends Cache<Integer> {
void setOrAdd(int obj, int frame) {
if (valid(frame)) {
set(get() + obj, frame);
}
else {
set(obj, frame);
}
}
}
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 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();
}
}