Skip to content

Commit 3610db2

Browse files
author
Bytekeeper
committed
Added reaver support
1 parent 005a1c7 commit 3610db2

File tree

7 files changed

+205
-26
lines changed

7 files changed

+205
-26
lines changed

src/main/java/org/bk/ass/AgentUtil.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@ public class AgentUtil {
1212
// Retrieved from OpenBW
1313
private static final int STIM_TIMER = 37;
1414
private static final int STIM_ENERGY_COST_SHIFTED = 10 << 8;
15+
public static final int INTERCEPTOR_COOLDOWN = 45;
16+
public static final int REAVER_COOLDOWN = 60;
1517

1618

1719
private AgentUtil() {

src/main/java/org/bk/ass/BWAPI4JAgentFactory.java

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,9 @@ private Agent fromUnitType(
8888
maxAirHits = maxGroundHits = UnitType.Terran_Marine.maxAirHits();
8989
rangeExtension = 64;
9090
hitsFactor = 4;
91+
} else if (unitType == UnitType.Protoss_Reaver) {
92+
groundWeapon = WeaponType.Scarab;
93+
maxGroundHits = UnitType.Protoss_Scarab.maxGroundHits();
9194
}
9295

9396
float speed = (float) unitType.topSpeed();
@@ -102,6 +105,17 @@ private Agent fromUnitType(
102105
}
103106
}
104107
}
108+
int cd;
109+
switch (unitType) {
110+
case Protoss_Interceptor:
111+
cd = AgentUtil.INTERCEPTOR_COOLDOWN;
112+
break;
113+
case Protoss_Reaver:
114+
cd = AgentUtil.REAVER_COOLDOWN;
115+
break;
116+
default:
117+
cd = max(groundWeapon.damageCooldown(), airWeapon.damageCooldown());
118+
}
105119

106120
Agent agent =
107121
new Agent(unitType.name())
@@ -112,10 +126,7 @@ private Agent fromUnitType(
112126
.setFlyer(unitType.isFlyer())
113127
.setHealer(unitType == UnitType.Terran_Medic)
114128
.setMaxHealth(unitType.maxHitPoints())
115-
.setMaxCooldown(
116-
unitType != UnitType.Protoss_Interceptor
117-
? max(groundWeapon.damageCooldown(), airWeapon.damageCooldown())
118-
: 45)
129+
.setMaxCooldown(cd)
119130
.setAirWeapon(
120131
weapon(
121132
airWeaponUpgrades,

src/main/java/org/bk/ass/BWMirrorAgentFactory.java

Lines changed: 17 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -90,8 +90,11 @@ private Agent fromUnitType(
9090
if (unitType == UnitType.Terran_Bunker) {
9191
airWeapon = groundWeapon = UnitType.Terran_Marine.groundWeapon();
9292
maxAirHits = maxGroundHits = UnitType.Terran_Marine.maxAirHits();
93-
rangeExtension += 64;
93+
rangeExtension = 64;
9494
hitsFactor = 4;
95+
} else if (unitType == UnitType.Protoss_Reaver) {
96+
groundWeapon = WeaponType.Scarab;
97+
maxGroundHits = UnitType.Protoss_Scarab.maxGroundHits();
9598
}
9699

97100
float speed = (float) unitType.topSpeed();
@@ -107,6 +110,18 @@ private Agent fromUnitType(
107110
}
108111
}
109112

113+
int cd;
114+
switch (unitType) {
115+
case Protoss_Interceptor:
116+
cd = AgentUtil.INTERCEPTOR_COOLDOWN;
117+
break;
118+
case Protoss_Reaver:
119+
cd = AgentUtil.REAVER_COOLDOWN;
120+
break;
121+
default:
122+
cd = max(groundWeapon.damageCooldown(), airWeapon.damageCooldown());
123+
}
124+
110125
Agent agent =
111126
new Agent(unitType.toString())
112127
.setAttackTargetPriority(
@@ -116,10 +131,7 @@ private Agent fromUnitType(
116131
.setFlyer(unitType.isFlyer())
117132
.setHealer(unitType == UnitType.Terran_Medic)
118133
.setMaxHealth(unitType.maxHitPoints())
119-
.setMaxCooldown(
120-
unitType != UnitType.Protoss_Interceptor
121-
? max(groundWeapon.damageCooldown(), airWeapon.damageCooldown())
122-
: 45)
134+
.setMaxCooldown(cd)
123135
.setAirWeapon(
124136
weapon(
125137
airWeaponUpgrades,

src/main/java/org/bk/ass/Evaluator.java

Lines changed: 4 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -143,12 +143,9 @@ private void sumAirDamage(Agent agent) {
143143
private double calculateDamage(Agent attacker, Weapon weapon) {
144144
double rangeFactor = 1.0 + weapon.maxRange * parameters.rangeScale;
145145
double speedFactor = 1.0 + attacker.speed * parameters.speedScale;
146-
double radialSplashFactor =
147-
weapon.splashType == SplashType.RADIAL_SPLASH ? parameters.radialSplashFactor : 1.0;
148-
double lineSplashFactor =
149-
weapon.splashType == SplashType.LINE_SPLASH ? parameters.lineSplashFactor : 1.0;
150-
double bounceSplashFactor =
151-
weapon.splashType == SplashType.BOUNCE ? parameters.radialSplashFactor : 1.0;
146+
double radialSplashFactor = weapon.splashType == SplashType.RADIAL_ENEMY_SPLASH || weapon.splashType == SplashType.RADIAL_SPLASH ? 1.0 + parameters.radialSplashFactor * weapon.innerSplashRadius : 1.0;
147+
double lineSplashFactor = weapon.splashType == SplashType.LINE_SPLASH ? 1.0 + parameters.lineSplashFactor * weapon.innerSplashRadius : 1.0;
148+
double bounceSplashFactor = weapon.splashType == SplashType.BOUNCE ? parameters.bounceSplashFactor : 1.0;
152149

153150
return weapon.damageShifted
154151
* rangeFactor
@@ -242,10 +239,7 @@ public Parameters(double[] source) {
242239
}
243240

244241
public Parameters() {
245-
this(
246-
new double[] {
247-
2.812625, 0.504625, 0.053, 1.2545, 2.27975, 1.86025, 976.7565, 513.109625, 586.87675
248-
});
242+
this(new double[] {62.55550402780286, 455.5108652989783, 16.644298951231356, 0.0881036657313995, 534.3720029493211, 2.2237277860926357, 506.53351985609726, 780.675841755981, 778.571115050493});
249243
}
250244
}
251245
}

src/test/java/org/bk/ass/EvaluatorParameterTuner.java

Lines changed: 98 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,13 +4,14 @@
44
import io.jenetics.engine.Engine;
55
import io.jenetics.engine.EvolutionResult;
66
import io.jenetics.engine.Limits;
7+
import io.jenetics.util.IntRange;
78
import org.bk.ass.Evaluator.Parameters;
89
import org.openbw.bwapi4j.org.apache.commons.lang3.time.StopWatch;
910
import org.openbw.bwapi4j.test.BWDataProvider;
1011

1112
import java.lang.reflect.Method;
1213
import java.lang.reflect.Modifier;
13-
import java.util.Arrays;
14+
import java.util.*;
1415
import java.util.function.Function;
1516
import java.util.stream.Collectors;
1617

@@ -19,8 +20,77 @@ public class EvaluatorParameterTuner {
1920
public static void main(String[] args) throws Exception {
2021
BWDataProvider.injectValues();
2122

23+
SplittableRandom prng = new SplittableRandom();
24+
List<Par> candidates = new ArrayList<>();
25+
int[] miss = new int[9];
26+
for (int i = 0; i < 20; i++) {
27+
double[] d = new double[9];
28+
for (int j = 0; j < d.length; j++) {
29+
d[j] = prng.nextDouble(0.0001, 1000.0);
30+
}
31+
Par e = new Par(d);
32+
if (e.score == TEST_METHODS.length) {
33+
System.out.println(d);
34+
return;
35+
}
36+
candidates.add(e);
37+
}
38+
int best = 0;
39+
for (int i = 0; i < 5000000; i++) {
40+
int ci = prng.nextInt(candidates.size() * 12 / 10);
41+
Par sub;
42+
if (ci < candidates.size()) {
43+
Par par = candidates.get(ci);
44+
45+
int index = prng.nextInt(par.d.length);
46+
47+
sub = IntRange.of(0, 50).stream()
48+
.mapToObj(d -> {
49+
double[] next = Arrays.copyOf(par.d, par.d.length);
50+
next[index] = prng.nextDouble(0.0001, 1000.0);
51+
return new Par(next);
52+
}).max(Comparator.comparingInt(p -> p.score)).get();
53+
if (sub.score == par.score) {
54+
miss[index]++;
55+
continue;
56+
}
57+
} else {
58+
double[] d = new double[9];
59+
for (int j = 0; j < d.length; j++) {
60+
d[j] = prng.nextDouble(0.0001, 1000.0);
61+
}
62+
sub = new Par(d);
63+
}
64+
int min = 0;
65+
for (int j = 1; j < candidates.size(); j++) {
66+
if (candidates.get(j).score + prng.nextDouble() < candidates.get(min).score + prng.nextDouble()) {
67+
min = j;
68+
}
69+
}
70+
if (sub.score >= candidates.get(min).score) {
71+
candidates.set(min, sub);
72+
if (sub.score > best) {
73+
best = sub.score;
74+
System.out.println("Best: " + best);
75+
System.out.println(Arrays.stream(sub.d)
76+
.mapToObj(String::valueOf)
77+
.collect(Collectors.joining(", ", "new double[] {", "}")));
78+
}
79+
}
80+
if (sub.score == TEST_METHODS.length) {
81+
System.out.println(Arrays.stream(sub.d)
82+
.mapToObj(String::valueOf)
83+
.collect(Collectors.joining(", ", "new double[] {", "}")));
84+
return;
85+
}
86+
}
87+
88+
System.out.println("NOT FOUND");
89+
System.out.println(Arrays.toString(miss));
90+
System.exit(0);
91+
2292
Genotype<DoubleGene> genotype =
23-
Genotype.of(DoubleChromosome.of(0.0001, 3.0, 6), DoubleChromosome.of(0, 1000, 3));
93+
Genotype.of(DoubleChromosome.of(0.0001, 20.0, 6), DoubleChromosome.of(300, 1300, 3));
2494

2595
Function<Genotype<DoubleGene>, Integer> eval =
2696
gt -> {
@@ -62,7 +132,7 @@ public static void main(String[] args) throws Exception {
62132
}
63133

64134
private static double round(double v) {
65-
return Math.round(v * 8000) / 8000.0;
135+
return Math.round(v * 1000) / 1000.0;
66136
}
67137

68138
private static final Method[] TEST_METHODS =
@@ -75,13 +145,36 @@ private static double round(double v) {
75145
.toArray(Method[]::new);
76146

77147
private static int hits(EvaluatorTest test) {
148+
int result = 0;
78149
for (int i = 0; i < TEST_METHODS.length; i++) {
79150
try {
80151
TEST_METHODS[i].invoke(test);
152+
result++;
81153
} catch (Exception e) {
82-
return i;
154+
// Ignore
83155
}
84156
}
85-
return TEST_METHODS.length;
157+
return result;
158+
}
159+
160+
private static class Par {
161+
final double[] d;
162+
final int score;
163+
164+
private Par(double[] d) {
165+
this.d = d;
166+
this.score = eval();
167+
}
168+
169+
private int eval() {
170+
EvaluatorTest test = new EvaluatorTest();
171+
test.evaluator = new Evaluator(new Parameters(d));
172+
return hits(test);
173+
}
174+
175+
@Override
176+
public String toString() {
177+
return score + " : " + Arrays.toString(d);
178+
}
86179
}
87180
}

src/test/java/org/bk/ass/EvaluatorTest.java

Lines changed: 34 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
package org.bk.ass;
22

3+
import io.jenetics.util.IntRange;
34
import org.junit.jupiter.api.BeforeAll;
45
import org.junit.jupiter.api.Test;
56
import org.openbw.bwapi4j.test.BWDataProvider;
@@ -9,6 +10,7 @@
910
import java.util.Arrays;
1011
import java.util.Collections;
1112
import java.util.List;
13+
import java.util.stream.Collectors;
1214

1315
import static org.assertj.core.api.Assertions.assertThat;
1416

@@ -267,7 +269,7 @@ void _3ZerglingVsSiegedTankAndMarine() {
267269
double result = evaluator.evaluate(a, b);
268270

269271
// THEN
270-
assertThat(result).isLessThan(0.5);
272+
assertThat(result).isBetween(0.2, 0.4);
271273
}
272274

273275
@Test
@@ -289,6 +291,36 @@ void _6ZerglingVsSiegedTankAndMarine() {
289291
double result = evaluator.evaluate(a, b);
290292

291293
// THEN
292-
assertThat(result).isGreaterThan(0.5);
294+
assertThat(result).isBetween(0.5, 0.7);
295+
}
296+
297+
@Test
298+
void reaverVs12Lings() {
299+
// GIVEN
300+
301+
List<Agent> a = Collections.singletonList(factory.of(UnitType.Protoss_Reaver));
302+
303+
List<Agent> b = IntRange.of(0, 11).stream().mapToObj(unused -> factory.of(UnitType.Zerg_Zergling)).collect(Collectors.toList());
304+
305+
// WHEN
306+
double result = evaluator.evaluate(a, b);
307+
308+
// THEN
309+
assertThat(result).isBetween(0.2, 0.4);
310+
}
311+
312+
@Test
313+
void reaverVs9Lings() {
314+
// GIVEN
315+
316+
List<Agent> a = Collections.singletonList(factory.of(UnitType.Protoss_Reaver));
317+
318+
List<Agent> b = IntRange.of(0, 9).stream().mapToObj(unused -> factory.of(UnitType.Zerg_Zergling)).collect(Collectors.toList());
319+
320+
// WHEN
321+
double result = evaluator.evaluate(a, b);
322+
323+
// THEN
324+
assertThat(result).isBetween(0.6, 0.8);
293325
}
294326
}

src/test/java/org/bk/ass/SimulatorTest.java

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -813,4 +813,39 @@ void shouldNotDieFromPlague() {
813813
.extracting(a -> a.healthShifted)
814814
.isEqualTo(512); // No damage taken
815815
}
816+
817+
@Test
818+
void reaverVs9Lings() {
819+
// GIVEN
820+
simulator.addAgentA(factory.of(UnitType.Protoss_Reaver));
821+
822+
for (int i = 0; i < 9; i++) {
823+
simulator.addAgentB(factory.of(UnitType.Zerg_Zergling).setX(i * 30));
824+
}
825+
826+
// WHEN
827+
simulator.simulate(-1);
828+
829+
// THEN
830+
assertThat(simulator.getAgentsA()).isNotEmpty();
831+
assertThat(simulator.getAgentsB()).isEmpty();
832+
833+
}
834+
835+
@Test
836+
void reaverVs12Lings() {
837+
// GIVEN
838+
simulator.addAgentA(factory.of(UnitType.Protoss_Reaver));
839+
840+
for (int i = 0; i < 12; i++) {
841+
simulator.addAgentB(factory.of(UnitType.Zerg_Zergling).setX(i * 30));
842+
}
843+
844+
// WHEN
845+
simulator.simulate(-1);
846+
847+
// THEN
848+
assertThat(simulator.getAgentsA()).isEmpty();
849+
assertThat(simulator.getAgentsB()).isNotEmpty();
850+
}
816851
}

0 commit comments

Comments
 (0)