221 lines
7.8 KiB
Java
221 lines
7.8 KiB
Java
package com.projectsacrifice.game;
|
|
|
|
import static org.junit.Assert.assertEquals;
|
|
import static org.junit.Assert.assertFalse;
|
|
import static org.junit.Assert.assertTrue;
|
|
|
|
import org.junit.Test;
|
|
|
|
public final class LevelPlaytestBotTest {
|
|
@Test
|
|
public void scenarioProgressesThroughNamedSteps() {
|
|
ScriptedDriver driver = new ScriptedDriver();
|
|
LevelPlaytestBot.Scenario scenario = LevelPlaytestBot.Scenario
|
|
.builder(7, "Reusable scenario")
|
|
.step("Create a corpse", 1_000L, LevelPlaytestBot.Input.right(),
|
|
snapshot -> snapshot.deaths() >= 1)
|
|
.step("Reach the goal", 1_000L, LevelPlaytestBot.Input.left(),
|
|
GameView.AutomationSnapshot::completed)
|
|
.build();
|
|
|
|
LevelPlaytestBot.Result result = new LevelPlaytestBot().run(driver, scenario, 5_000L);
|
|
|
|
assertTrue(result.diagnostic(), result.completed());
|
|
assertEquals(7, driver.startedLevel);
|
|
assertEquals("Reach the goal", result.lastStep());
|
|
}
|
|
|
|
@Test
|
|
public void sameDriverCanRestartTheCompleteScenarioThreeTimes() {
|
|
ScriptedDriver driver = new ScriptedDriver();
|
|
LevelPlaytestBot.Scenario scenario = LevelPlaytestBot.Scenario
|
|
.builder(7, "Repeated scenario")
|
|
.step("Create a corpse", 1_000L, LevelPlaytestBot.Input.right(),
|
|
snapshot -> snapshot.deaths() >= 1)
|
|
.step("Reach the goal", 1_000L, LevelPlaytestBot.Input.left(),
|
|
GameView.AutomationSnapshot::completed)
|
|
.build();
|
|
|
|
for (int pass = 1; pass <= 3; pass++) {
|
|
LevelPlaytestBot.Result result = new LevelPlaytestBot().run(driver, scenario, 5_000L);
|
|
assertTrue("Pass " + pass + ": " + result.diagnostic(), result.completed());
|
|
assertEquals("Pass " + pass, "Reach the goal", result.lastStep());
|
|
assertEquals("Pass " + pass, 1, result.deaths());
|
|
}
|
|
}
|
|
|
|
@Test
|
|
public void stepTimeoutReportsItsNameAndObservableSnapshot() {
|
|
ScriptedDriver driver = new ScriptedDriver(false);
|
|
LevelPlaytestBot.Scenario scenario = LevelPlaytestBot.Scenario
|
|
.builder(5, "Diagnostic scenario")
|
|
.step("Keep the plate pressed", 64L, LevelPlaytestBot.Input.right(),
|
|
GameView.AutomationSnapshot::allDoorsOpen)
|
|
.build();
|
|
|
|
LevelPlaytestBot.Result result = new LevelPlaytestBot().run(driver, scenario, 5_000L);
|
|
|
|
assertFalse(result.completed());
|
|
assertEquals("Keep the plate pressed", result.lastStep());
|
|
assertTrue(result.diagnostic(), result.diagnostic().contains("step=Keep the plate pressed"));
|
|
assertTrue(result.diagnostic(), result.diagnostic().contains("x=100.0"));
|
|
assertTrue(result.diagnostic(), result.diagnostic().contains("y=760.0"));
|
|
assertTrue(result.diagnostic(), result.diagnostic().contains("alive=true"));
|
|
assertTrue(result.diagnostic(), result.diagnostic().contains("deaths=0"));
|
|
assertTrue(result.diagnostic(), result.diagnostic().contains("corpses=0"));
|
|
assertTrue(result.diagnostic(), result.diagnostic().contains("allDoorsOpen=false"));
|
|
}
|
|
|
|
@Test
|
|
public void levelFiveUsesTheGenericNamedScenario() {
|
|
LevelFiveDriver driver = new LevelFiveDriver();
|
|
|
|
LevelPlaytestBot.Result result = new LevelPlaytestBot().proveLevelFive(driver, 25_000L);
|
|
|
|
assertTrue(result.diagnostic(), result.completed());
|
|
assertEquals(5, driver.startedLevel);
|
|
assertEquals("Reach the relic", result.lastStep());
|
|
assertEquals(1, result.deaths());
|
|
assertEquals(1, result.corpseCount());
|
|
assertTrue(result.doorOpened());
|
|
}
|
|
|
|
@Test
|
|
public void automationSnapshotDefaultsToNoMovingPlatform() {
|
|
GameView.AutomationSnapshot snapshot = new GameView.AutomationSnapshot(
|
|
false, true, false, false, false,
|
|
1, 0L, 130f, 760f, 0, 0);
|
|
|
|
assertTrue(Float.isNaN(snapshot.firstMovingPlatformY()));
|
|
assertFalse(snapshot.playerOnMovingPlatform());
|
|
}
|
|
|
|
private static final class ScriptedDriver implements LevelPlaytestBot.Driver {
|
|
private int startedLevel;
|
|
private long nowMillis;
|
|
private boolean moveLeft;
|
|
private boolean moveRight;
|
|
private int deaths;
|
|
private boolean completed;
|
|
private final boolean progresses;
|
|
|
|
ScriptedDriver() {
|
|
this(true);
|
|
}
|
|
|
|
ScriptedDriver(boolean progresses) {
|
|
this.progresses = progresses;
|
|
}
|
|
|
|
@Override
|
|
public void startLevel(int oneBasedLevelNumber) {
|
|
startedLevel = oneBasedLevelNumber;
|
|
nowMillis = 0L;
|
|
moveLeft = false;
|
|
moveRight = false;
|
|
deaths = 0;
|
|
completed = false;
|
|
}
|
|
|
|
@Override
|
|
public void setInput(boolean moveLeft, boolean moveRight, boolean jump) {
|
|
this.moveLeft = moveLeft;
|
|
this.moveRight = moveRight;
|
|
}
|
|
|
|
@Override
|
|
public GameView.AutomationSnapshot snapshot() {
|
|
return new GameView.AutomationSnapshot(
|
|
completed,
|
|
true,
|
|
false,
|
|
false,
|
|
moveLeft || moveRight,
|
|
startedLevel,
|
|
nowMillis,
|
|
100f,
|
|
760f,
|
|
deaths,
|
|
deaths
|
|
);
|
|
}
|
|
|
|
@Override
|
|
public void waitForNextDecision(long millis) {
|
|
nowMillis += millis;
|
|
if (progresses && moveRight && deaths == 0) {
|
|
deaths = 1;
|
|
} else if (progresses && moveLeft && deaths == 1) {
|
|
completed = true;
|
|
}
|
|
}
|
|
|
|
@Override
|
|
public long currentTimeMillis() {
|
|
return nowMillis;
|
|
}
|
|
}
|
|
|
|
private static final class LevelFiveDriver implements LevelPlaytestBot.Driver {
|
|
private int startedLevel;
|
|
private long nowMillis;
|
|
private boolean moveRight;
|
|
private boolean jump;
|
|
private boolean alive = true;
|
|
private boolean doorOpen;
|
|
private boolean completed;
|
|
private int deaths;
|
|
private int corpses;
|
|
private float x = 130f;
|
|
|
|
@Override
|
|
public void startLevel(int oneBasedLevelNumber) {
|
|
startedLevel = oneBasedLevelNumber;
|
|
}
|
|
|
|
@Override
|
|
public void setInput(boolean moveLeft, boolean moveRight, boolean jump) {
|
|
this.moveRight = moveRight;
|
|
this.jump = jump;
|
|
}
|
|
|
|
@Override
|
|
public GameView.AutomationSnapshot snapshot() {
|
|
return new GameView.AutomationSnapshot(
|
|
completed, alive, doorOpen, false, moveRight || jump,
|
|
startedLevel, nowMillis, x, 760f, deaths, corpses);
|
|
}
|
|
|
|
@Override
|
|
public void waitForNextDecision(long millis) {
|
|
nowMillis += millis;
|
|
if (!alive) {
|
|
alive = true;
|
|
x = 130f;
|
|
} else if (deaths == 0 && moveRight && !jump) {
|
|
deaths = 1;
|
|
corpses = 1;
|
|
alive = false;
|
|
doorOpen = true;
|
|
x = 570f;
|
|
} else if (moveRight && jump) {
|
|
x += 60f;
|
|
} else if (moveRight && x < 390f) {
|
|
x = 400f;
|
|
} else if (moveRight && x < 750f) {
|
|
x = 760f;
|
|
} else if (moveRight && x < 1_390f) {
|
|
x = 1_500f;
|
|
} else if (moveRight) {
|
|
x = 2_080f;
|
|
completed = true;
|
|
}
|
|
}
|
|
|
|
@Override
|
|
public long currentTimeMillis() {
|
|
return nowMillis;
|
|
}
|
|
}
|
|
}
|