Завершить интеграционную устойчивость ботов этапа 3
This commit is contained in:
@@ -2,7 +2,6 @@ package com.projectsacrifice.game;
|
||||
|
||||
import android.app.Instrumentation;
|
||||
|
||||
import androidx.lifecycle.Lifecycle;
|
||||
import androidx.test.core.app.ActivityScenario;
|
||||
import androidx.test.ext.junit.runners.AndroidJUnit4;
|
||||
import androidx.test.platform.app.InstrumentationRegistry;
|
||||
@@ -21,12 +20,16 @@ public final class GameLifecycleTest {
|
||||
public void returningFromBackgroundKeepsPuzzleVisiblePausedAndClearsHeldInput() {
|
||||
Instrumentation instrumentation = InstrumentationRegistry.getInstrumentation();
|
||||
try (ActivityScenario<MainActivity> scenario = ActivityScenario.launch(MainActivity.class)) {
|
||||
final MainActivity[] activity = new MainActivity[1];
|
||||
final GameView[] view = new GameView[1];
|
||||
scenario.onActivity(activity -> view[0] = activity.gameViewForAutomation());
|
||||
scenario.onActivity(current -> {
|
||||
activity[0] = current;
|
||||
view[0] = current.gameViewForAutomation();
|
||||
});
|
||||
createRetainedCorpse(instrumentation, view[0]);
|
||||
|
||||
runOnGame(instrumentation, view[0], false, false, true, false);
|
||||
scenario.moveToState(Lifecycle.State.STARTED);
|
||||
instrumentation.runOnMainSync(activity[0]::onPause);
|
||||
GameView.AutomationSnapshot backgroundStart = snapshot(instrumentation, view[0]);
|
||||
sleep(700L);
|
||||
GameView.AutomationSnapshot backgroundEnd = snapshot(instrumentation, view[0]);
|
||||
@@ -37,7 +40,7 @@ public final class GameLifecycleTest {
|
||||
assertEquals(backgroundStart.playerX(), backgroundEnd.playerX(), 0.01f);
|
||||
assertEquals(backgroundStart.elapsedMilliseconds(), backgroundEnd.elapsedMilliseconds());
|
||||
|
||||
scenario.moveToState(Lifecycle.State.RESUMED);
|
||||
instrumentation.runOnMainSync(activity[0]::onResume);
|
||||
GameView.AutomationSnapshot returned = snapshot(instrumentation, view[0]);
|
||||
assertTrue("Returning to an active puzzle must show the pause screen", returned.visiblyPaused());
|
||||
assertFalse("Held touch input must not survive backgrounding", returned.inputActive());
|
||||
|
||||
@@ -20,10 +20,13 @@ final class LateLevelScenarios {
|
||||
snapshot -> snapshot.playerX() >= 626f
|
||||
&& snapshot.playerY() >= 668f
|
||||
&& snapshot.playerY() <= 690f)
|
||||
.step("Jump from the block to the first ledge", 2_500L,
|
||||
.step("Land on the first ledge from the frozen block", 3_000L,
|
||||
LevelPlaytestBot.Input.rightJump(),
|
||||
snapshot -> snapshot.playerX() >= 750f
|
||||
&& snapshot.playerY() <= 505f)
|
||||
LevelPlaytestBot.whileDeathsAtMost(1,
|
||||
snapshot -> snapshot.playerAlive()
|
||||
&& snapshot.playerOnGround()
|
||||
&& snapshot.playerX() >= 810f
|
||||
&& snapshot.playerY() <= 500f))
|
||||
.step("Cross the first ledge", 3_000L, LevelPlaytestBot.Input.right(),
|
||||
snapshot -> snapshot.playerX() >= 1_230f)
|
||||
.step("Jump the gap to the second ledge", 2_500L,
|
||||
@@ -117,19 +120,24 @@ final class LateLevelScenarios {
|
||||
LevelPlaytestBot.Input.right(),
|
||||
snapshot -> snapshot.deaths() == 1
|
||||
&& snapshot.corpseCount() == 1)
|
||||
.step("Observe the delivered body power the lift", 3_000L,
|
||||
LevelPlaytestBot.Input.none(),
|
||||
snapshot -> snapshot.deaths() == 1
|
||||
&& snapshot.corpseCount() == 1
|
||||
&& snapshot.firstMovingPlatformPowered())
|
||||
.step("Wait for the freezer volunteer", 3_000L,
|
||||
LevelPlaytestBot.Input.none(),
|
||||
snapshot -> snapshot.playerAlive() && snapshot.playerX() < 250f)
|
||||
.step("Approach the launch saw", 2_500L,
|
||||
LevelPlaytestBot.Input.right(),
|
||||
LevelPlaytestBot.whileDeathsAtMost(1,
|
||||
LevelPlaytestBot.groundedAliveAtOrBeyond(280f)))
|
||||
LevelPlaytestBot.groundedAliveAtOrBeyond(320f)))
|
||||
.step("Take off before the launch saw", 1_000L,
|
||||
LevelPlaytestBot.Input.rightJump(),
|
||||
LevelPlaytestBot.whileDeathsAtMost(1,
|
||||
snapshot -> snapshot.playerAlive()
|
||||
&& !snapshot.playerOnGround()
|
||||
&& snapshot.playerY() <= 680f))
|
||||
&& snapshot.playerY() <= 580f))
|
||||
.step("Clear the launch saw", 2_000L,
|
||||
LevelPlaytestBot.Input.right(),
|
||||
LevelPlaytestBot.whileDeathsAtMost(1,
|
||||
@@ -150,13 +158,13 @@ final class LateLevelScenarios {
|
||||
.step("Return to the launch saw", 2_500L,
|
||||
LevelPlaytestBot.Input.right(),
|
||||
LevelPlaytestBot.whileDeathsAtMost(2,
|
||||
LevelPlaytestBot.groundedAliveAtOrBeyond(280f)))
|
||||
LevelPlaytestBot.groundedAliveAtOrBeyond(320f)))
|
||||
.step("Take off before the saw again", 1_000L,
|
||||
LevelPlaytestBot.Input.rightJump(),
|
||||
LevelPlaytestBot.whileDeathsAtMost(2,
|
||||
snapshot -> snapshot.playerAlive()
|
||||
&& !snapshot.playerOnGround()
|
||||
&& snapshot.playerY() <= 680f))
|
||||
&& snapshot.playerY() <= 580f))
|
||||
.step("Clear the saw again", 2_000L,
|
||||
LevelPlaytestBot.Input.right(),
|
||||
LevelPlaytestBot.whileDeathsAtMost(2,
|
||||
@@ -203,13 +211,13 @@ final class LateLevelScenarios {
|
||||
.step("Approach the saw for the final crossing", 2_500L,
|
||||
LevelPlaytestBot.Input.right(),
|
||||
LevelPlaytestBot.whileDeathsAtMost(3,
|
||||
LevelPlaytestBot.groundedAliveAtOrBeyond(280f)))
|
||||
LevelPlaytestBot.groundedAliveAtOrBeyond(320f)))
|
||||
.step("Take off for the final saw crossing", 1_000L,
|
||||
LevelPlaytestBot.Input.rightJump(),
|
||||
LevelPlaytestBot.whileDeathsAtMost(3,
|
||||
snapshot -> snapshot.playerAlive()
|
||||
&& !snapshot.playerOnGround()
|
||||
&& snapshot.playerY() <= 680f))
|
||||
&& snapshot.playerY() <= 580f))
|
||||
.step("Clear the saw for the final crossing", 2_000L,
|
||||
LevelPlaytestBot.Input.right(),
|
||||
LevelPlaytestBot.whileDeathsAtMost(3,
|
||||
|
||||
@@ -33,6 +33,14 @@ final class LevelEightScenario {
|
||||
return failure("Cross the pit before the clock expires", snapshot, budget, driver);
|
||||
}
|
||||
|
||||
snapshot = await(driver, budget, "Move clear of the platform sweep",
|
||||
LevelPlaytestBot.Input.right(),
|
||||
current -> current.playerX() >= 1_680f
|
||||
&& current.playerY() >= 779f && current.allDoorsOpen());
|
||||
if (failed(snapshot, budget, driver)) {
|
||||
return failure("Move clear of the platform sweep", snapshot, budget, driver);
|
||||
}
|
||||
|
||||
snapshot = await(driver, budget, "Wait for the far-side trap",
|
||||
LevelPlaytestBot.Input.none(),
|
||||
current -> current.playerX() >= 1_510f && !current.allDoorsOpen());
|
||||
@@ -40,21 +48,21 @@ final class LevelEightScenario {
|
||||
return failure("Wait for the far-side trap", snapshot, budget, driver);
|
||||
}
|
||||
|
||||
snapshot = await(driver, budget, "Return beneath the recovery relay",
|
||||
LevelPlaytestBot.Input.left(),
|
||||
current -> current.playerX() <= 1_680f && current.playerY() >= 779f);
|
||||
snapshot = positionBeneathRecoveryRelay(driver, budget);
|
||||
if (failed(snapshot, budget, driver)) {
|
||||
return failure("Return beneath the recovery relay", snapshot, budget, driver);
|
||||
}
|
||||
|
||||
snapshot = pulseLeftJumpThenAwait(driver, budget, "Jump into the recovery relay",
|
||||
snapshot = pulseRightJumpThenAwait(driver, budget, "Jump into the recovery relay",
|
||||
current -> current.allDoorsOpen());
|
||||
if (failed(snapshot, budget, driver)) {
|
||||
return failure("Jump into the recovery relay", snapshot, budget, driver);
|
||||
}
|
||||
|
||||
snapshot = await(driver, budget, "Land after rearming the clock",
|
||||
LevelPlaytestBot.Input.none(), current -> current.playerY() >= 779f);
|
||||
LevelPlaytestBot.Input.right(),
|
||||
current -> current.playerX() >= 1_650f
|
||||
&& current.playerY() >= 779f && current.allDoorsOpen());
|
||||
if (failed(snapshot, budget, driver)) {
|
||||
return failure("Land after rearming the clock", snapshot, budget, driver);
|
||||
}
|
||||
@@ -85,10 +93,10 @@ final class LevelEightScenario {
|
||||
LevelPlaytestBot.Input.right(), current -> current.playerX() >= 760f);
|
||||
if (failed(snapshot, budget, driver)) return snapshot;
|
||||
|
||||
snapshot = await(driver, budget, "Wait for the moving platform",
|
||||
snapshot = await(driver, budget, "Wait for the outbound moving platform",
|
||||
LevelPlaytestBot.Input.none(),
|
||||
current -> current.elapsedMilliseconds() >= timerStartedAt + 2_250L
|
||||
&& current.firstMovingPlatformX() <= 1_050f);
|
||||
&& MovingPlatformLaunchPolicy.readyToBoard(current, 1_050f));
|
||||
if (failed(snapshot, budget, driver)) return snapshot;
|
||||
|
||||
driver.setInput(false, true, true);
|
||||
@@ -135,10 +143,8 @@ final class LevelEightScenario {
|
||||
private Result finishFromFarSide(LevelPlaytestBot.Driver driver,
|
||||
PlaytestSimulationBudget budget,
|
||||
GameView.AutomationSnapshot snapshot, String step) {
|
||||
snapshot = await(driver, budget, "Reach the open-door jump",
|
||||
LevelPlaytestBot.Input.right(),
|
||||
current -> current.playerX() >= 1_730f && current.allDoorsOpen());
|
||||
if (failed(snapshot, budget, driver)) {
|
||||
snapshot = positionForFinalJump(driver, budget);
|
||||
if (failed(snapshot, budget, driver) || !snapshot.allDoorsOpen()) {
|
||||
return failure("Reach the open-door jump", snapshot, budget, driver);
|
||||
}
|
||||
|
||||
@@ -154,14 +160,62 @@ final class LevelEightScenario {
|
||||
+ "; " + state(snapshot));
|
||||
}
|
||||
|
||||
private GameView.AutomationSnapshot pulseLeftJumpThenAwait(
|
||||
private GameView.AutomationSnapshot positionForFinalJump(
|
||||
LevelPlaytestBot.Driver driver, PlaytestSimulationBudget budget
|
||||
) {
|
||||
lastStep = "Reach the open-door jump";
|
||||
GameView.AutomationSnapshot snapshot = driver.snapshot();
|
||||
while (!budget.exhausted(snapshot.elapsedMilliseconds(), driver.currentTimeMillis())
|
||||
&& snapshot.playerAlive() && !snapshot.completed() && snapshot.allDoorsOpen()) {
|
||||
if (snapshot.playerOnGround()
|
||||
&& snapshot.playerX() >= 1_690f && snapshot.playerX() <= 1_730f) {
|
||||
driver.setInput(false, false, false);
|
||||
return snapshot;
|
||||
}
|
||||
if (snapshot.playerX() > 1_730f) {
|
||||
driver.setInput(true, false, false);
|
||||
} else {
|
||||
driver.setInput(false, true, false);
|
||||
}
|
||||
driver.waitForNextDecision(DECISION_MILLIS);
|
||||
snapshot = driver.snapshot();
|
||||
}
|
||||
driver.setInput(false, false, false);
|
||||
return snapshot;
|
||||
}
|
||||
|
||||
private GameView.AutomationSnapshot pulseRightJumpThenAwait(
|
||||
LevelPlaytestBot.Driver driver, PlaytestSimulationBudget budget, String step,
|
||||
LevelPlaytestBot.SnapshotCondition completion
|
||||
) {
|
||||
driver.setInput(true, false, true);
|
||||
driver.setInput(false, true, true);
|
||||
driver.waitForNextDecision(64L);
|
||||
driver.setInput(true, false, false);
|
||||
return await(driver, budget, step, LevelPlaytestBot.Input.left(), completion);
|
||||
driver.setInput(false, true, false);
|
||||
return await(driver, budget, step, LevelPlaytestBot.Input.right(), completion);
|
||||
}
|
||||
|
||||
private GameView.AutomationSnapshot positionBeneathRecoveryRelay(
|
||||
LevelPlaytestBot.Driver driver, PlaytestSimulationBudget budget
|
||||
) {
|
||||
lastStep = "Return beneath the recovery relay";
|
||||
GameView.AutomationSnapshot snapshot = driver.snapshot();
|
||||
while (!budget.exhausted(snapshot.elapsedMilliseconds(), driver.currentTimeMillis())
|
||||
&& snapshot.playerAlive() && !snapshot.completed()) {
|
||||
if (snapshot.playerOnGround()
|
||||
&& snapshot.playerX() >= 1_620f && snapshot.playerX() <= 1_650f) {
|
||||
driver.setInput(false, false, false);
|
||||
return snapshot;
|
||||
}
|
||||
if (snapshot.playerX() > 1_650f) {
|
||||
driver.setInput(true, false, false);
|
||||
} else {
|
||||
driver.setInput(false, true, false);
|
||||
}
|
||||
driver.waitForNextDecision(DECISION_MILLIS);
|
||||
snapshot = driver.snapshot();
|
||||
}
|
||||
driver.setInput(false, false, false);
|
||||
return snapshot;
|
||||
}
|
||||
|
||||
private GameView.AutomationSnapshot await(
|
||||
@@ -224,6 +278,7 @@ final class LevelEightScenario {
|
||||
+ ", platformY=" + snapshot.firstMovingPlatformY()
|
||||
+ ", onMovingPlatform=" + snapshot.playerOnMovingPlatform()
|
||||
+ ", onGround=" + snapshot.playerOnGround()
|
||||
+ ", platformPowered=" + snapshot.firstMovingPlatformPowered();
|
||||
+ ", platformPowered=" + snapshot.firstMovingPlatformPowered()
|
||||
+ ", platformMovingRight=" + snapshot.firstMovingPlatformMovingRight();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -67,15 +67,16 @@ public final class EarlyLevelScenarios {
|
||||
.step("Wait for the next volunteer", 2_000L, LevelPlaytestBot.Input.none(),
|
||||
EarlyLevelScenarios::respawnedAtStart)
|
||||
.step("Approach the saw", 3_000L, LevelPlaytestBot.Input.right(),
|
||||
snapshot -> snapshot.playerAlive()
|
||||
LevelPlaytestBot.whileDeathsAtMost(1, snapshot -> snapshot.playerAlive()
|
||||
&& snapshot.playerOnGround()
|
||||
&& snapshot.playerX() >= 280f)
|
||||
&& snapshot.playerX() >= 390f))
|
||||
.step("Take off before the saw", 1_000L, LevelPlaytestBot.Input.rightJump(),
|
||||
snapshot -> snapshot.playerAlive()
|
||||
LevelPlaytestBot.whileDeathsAtMost(1, snapshot -> snapshot.playerAlive()
|
||||
&& !snapshot.playerOnGround()
|
||||
&& snapshot.playerY() <= 680f)
|
||||
&& snapshot.playerY() <= 620f))
|
||||
.step("Clear the saw and plate body", 3_000L, LevelPlaytestBot.Input.right(),
|
||||
snapshot -> snapshot.playerAlive() && snapshot.playerX() >= 700f)
|
||||
LevelPlaytestBot.whileDeathsAtMost(1, snapshot ->
|
||||
snapshot.playerAlive() && snapshot.playerX() >= 700f))
|
||||
.step("Reach the relic through the open door", 5_000L, LevelPlaytestBot.Input.right(),
|
||||
GameView.AutomationSnapshot::completed)
|
||||
.build();
|
||||
|
||||
@@ -59,6 +59,7 @@ public final class GameView extends View implements Runnable {
|
||||
private final float firstMovingPlatformY;
|
||||
private final boolean playerOnMovingPlatform;
|
||||
private final boolean firstMovingPlatformPowered;
|
||||
private final boolean firstMovingPlatformMovingRight;
|
||||
private final float firstCorpseX;
|
||||
private final boolean playerOnGround;
|
||||
|
||||
@@ -68,7 +69,7 @@ public final class GameView extends View implements Runnable {
|
||||
float playerX, float playerY, int deaths, int corpseCount) {
|
||||
this(completed, playerAlive, allDoorsOpen, visiblyPaused, inputActive, levelNumber,
|
||||
elapsedMilliseconds, playerX, playerY, deaths, corpseCount,
|
||||
Float.NaN, Float.NaN, false, false, Float.NaN, false);
|
||||
Float.NaN, Float.NaN, false, false, false, Float.NaN, false);
|
||||
}
|
||||
|
||||
AutomationSnapshot(boolean completed, boolean playerAlive, boolean allDoorsOpen,
|
||||
@@ -79,6 +80,21 @@ public final class GameView extends View implements Runnable {
|
||||
boolean playerOnMovingPlatform,
|
||||
boolean firstMovingPlatformPowered, float firstCorpseX,
|
||||
boolean playerOnGround) {
|
||||
this(completed, playerAlive, allDoorsOpen, visiblyPaused, inputActive, levelNumber,
|
||||
elapsedMilliseconds, playerX, playerY, deaths, corpseCount,
|
||||
firstMovingPlatformX, firstMovingPlatformY, playerOnMovingPlatform,
|
||||
firstMovingPlatformPowered, false, firstCorpseX, playerOnGround);
|
||||
}
|
||||
|
||||
AutomationSnapshot(boolean completed, boolean playerAlive, boolean allDoorsOpen,
|
||||
boolean visiblyPaused, boolean inputActive, int levelNumber,
|
||||
long elapsedMilliseconds,
|
||||
float playerX, float playerY, int deaths, int corpseCount,
|
||||
float firstMovingPlatformX, float firstMovingPlatformY,
|
||||
boolean playerOnMovingPlatform,
|
||||
boolean firstMovingPlatformPowered,
|
||||
boolean firstMovingPlatformMovingRight, float firstCorpseX,
|
||||
boolean playerOnGround) {
|
||||
this.completed = completed;
|
||||
this.playerAlive = playerAlive;
|
||||
this.allDoorsOpen = allDoorsOpen;
|
||||
@@ -94,6 +110,7 @@ public final class GameView extends View implements Runnable {
|
||||
this.firstMovingPlatformY = firstMovingPlatformY;
|
||||
this.playerOnMovingPlatform = playerOnMovingPlatform;
|
||||
this.firstMovingPlatformPowered = firstMovingPlatformPowered;
|
||||
this.firstMovingPlatformMovingRight = firstMovingPlatformMovingRight;
|
||||
this.firstCorpseX = firstCorpseX;
|
||||
this.playerOnGround = playerOnGround;
|
||||
}
|
||||
@@ -113,6 +130,7 @@ public final class GameView extends View implements Runnable {
|
||||
public float firstMovingPlatformY() { return firstMovingPlatformY; }
|
||||
public boolean playerOnMovingPlatform() { return playerOnMovingPlatform; }
|
||||
public boolean firstMovingPlatformPowered() { return firstMovingPlatformPowered; }
|
||||
public boolean firstMovingPlatformMovingRight() { return firstMovingPlatformMovingRight; }
|
||||
public float firstCorpseX() { return firstCorpseX; }
|
||||
public boolean playerOnGround() { return playerOnGround; }
|
||||
}
|
||||
@@ -1958,11 +1976,13 @@ public final class GameView extends View implements Runnable {
|
||||
float firstMovingPlatformX = Float.NaN;
|
||||
float firstMovingPlatformY = Float.NaN;
|
||||
boolean firstMovingPlatformPowered = false;
|
||||
boolean firstMovingPlatformMovingRight = false;
|
||||
for (PlatformState state : platformStates) {
|
||||
if (state.definition.isMoving()) {
|
||||
firstMovingPlatformX = state.x;
|
||||
firstMovingPlatformY = state.y;
|
||||
firstMovingPlatformPowered = signalActive(state.definition.controlId);
|
||||
firstMovingPlatformMovingRight = state.x > state.previousX;
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -1986,6 +2006,7 @@ public final class GameView extends View implements Runnable {
|
||||
firstMovingPlatformY,
|
||||
playerOnMovingPlatform,
|
||||
firstMovingPlatformPowered,
|
||||
firstMovingPlatformMovingRight,
|
||||
corpses.isEmpty() ? Float.NaN : corpses.get(0).x,
|
||||
player.onGround
|
||||
);
|
||||
|
||||
@@ -6,6 +6,7 @@ import java.util.List;
|
||||
|
||||
/** Runs black-box acceptance scenarios through the same input and state boundary as touch play. */
|
||||
public final class LevelPlaytestBot {
|
||||
private static final long DECISION_MILLIS = 16L;
|
||||
private static final long MIN_WALL_WATCHDOG_MILLIS = 120_000L;
|
||||
private static final long WALL_WATCHDOG_MULTIPLIER = 10L;
|
||||
|
||||
@@ -58,7 +59,11 @@ public final class LevelPlaytestBot {
|
||||
return snapshot -> {
|
||||
if (snapshot.deaths() > maximumDeaths) {
|
||||
throw new AssertionError("Route expected at most " + maximumDeaths
|
||||
+ " deaths but observed " + snapshot.deaths());
|
||||
+ " deaths but observed " + snapshot.deaths()
|
||||
+ "; x=" + snapshot.playerX()
|
||||
+ ", y=" + snapshot.playerY()
|
||||
+ ", alive=" + snapshot.playerAlive()
|
||||
+ ", grounded=" + snapshot.playerOnGround());
|
||||
}
|
||||
return completion.reached(snapshot);
|
||||
};
|
||||
@@ -196,7 +201,7 @@ public final class LevelPlaytestBot {
|
||||
}
|
||||
|
||||
driver.setInput(step.input.moveLeft, step.input.moveRight, step.input.jump);
|
||||
driver.waitForNextDecision(32L);
|
||||
driver.waitForNextDecision(DECISION_MILLIS);
|
||||
}
|
||||
|
||||
driver.setInput(false, false, false);
|
||||
|
||||
@@ -4,6 +4,12 @@ package com.projectsacrifice.game;
|
||||
final class MovingPlatformLaunchPolicy {
|
||||
private MovingPlatformLaunchPolicy() {}
|
||||
|
||||
static boolean readyToBoard(GameView.AutomationSnapshot snapshot, float maximumPlatformX) {
|
||||
return snapshot.firstMovingPlatformPowered()
|
||||
&& snapshot.firstMovingPlatformMovingRight()
|
||||
&& snapshot.firstMovingPlatformX() <= maximumPlatformX;
|
||||
}
|
||||
|
||||
static boolean ready(GameView.AutomationSnapshot snapshot, float minimumPlatformX) {
|
||||
return snapshot.playerOnMovingPlatform()
|
||||
&& snapshot.playerOnGround()
|
||||
|
||||
@@ -6,22 +6,35 @@ import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
public final class MovingPlatformLaunchPolicyTest {
|
||||
@Test
|
||||
public void boardingWaitsForThePoweredOutboundPhaseNearTheLeftFloor() {
|
||||
assertFalse(MovingPlatformLaunchPolicy.readyToBoard(
|
||||
snapshot(1_000f, false, true, true, false), 1_050f));
|
||||
assertFalse(MovingPlatformLaunchPolicy.readyToBoard(
|
||||
snapshot(1_000f, false, true, false, true), 1_050f));
|
||||
assertFalse(MovingPlatformLaunchPolicy.readyToBoard(
|
||||
snapshot(1_100f, false, true, true, true), 1_050f));
|
||||
assertTrue(MovingPlatformLaunchPolicy.readyToBoard(
|
||||
snapshot(1_000f, false, true, true, true), 1_050f));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void launchRequiresStablePoweredSupportInTheLaunchZone() {
|
||||
assertFalse(MovingPlatformLaunchPolicy.ready(snapshot(910f, true, true, true), 1_150f));
|
||||
assertFalse(MovingPlatformLaunchPolicy.ready(snapshot(1_150f, false, true, true), 1_150f));
|
||||
assertFalse(MovingPlatformLaunchPolicy.ready(snapshot(1_150f, true, false, true), 1_150f));
|
||||
assertFalse(MovingPlatformLaunchPolicy.ready(snapshot(1_150f, true, true, false), 1_150f));
|
||||
assertTrue(MovingPlatformLaunchPolicy.ready(snapshot(1_150f, true, true, true), 1_150f));
|
||||
assertFalse(MovingPlatformLaunchPolicy.ready(snapshot(910f, true, true, true, true), 1_150f));
|
||||
assertFalse(MovingPlatformLaunchPolicy.ready(snapshot(1_150f, false, true, true, true), 1_150f));
|
||||
assertFalse(MovingPlatformLaunchPolicy.ready(snapshot(1_150f, true, false, true, true), 1_150f));
|
||||
assertFalse(MovingPlatformLaunchPolicy.ready(snapshot(1_150f, true, true, false, true), 1_150f));
|
||||
assertTrue(MovingPlatformLaunchPolicy.ready(snapshot(1_150f, true, true, true, true), 1_150f));
|
||||
}
|
||||
|
||||
private static GameView.AutomationSnapshot snapshot(
|
||||
float platformX, boolean supported, boolean grounded, boolean powered
|
||||
float platformX, boolean supported, boolean grounded, boolean powered,
|
||||
boolean movingRight
|
||||
) {
|
||||
return new GameView.AutomationSnapshot(
|
||||
false, true, true, false, false, 8,
|
||||
4_000L, 1_100f, 670f, 0, 0,
|
||||
platformX, 770f, supported, powered, Float.NaN, grounded
|
||||
platformX, 770f, supported, powered, movingRight, Float.NaN, grounded
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user