From 9d792bdee4cd456cb8269e1ed53132dc34ea7da0 Mon Sep 17 00:00:00 2001 From: "E.Gavrilov" Date: Tue, 18 Aug 2026 18:27:33 +0300 Subject: [PATCH] =?UTF-8?q?=D0=97=D0=B0=D0=B2=D0=B5=D1=80=D1=88=D0=B8?= =?UTF-8?q?=D1=82=D1=8C=20=D0=B8=D0=BD=D1=82=D0=B5=D0=B3=D1=80=D0=B0=D1=86?= =?UTF-8?q?=D0=B8=D0=BE=D0=BD=D0=BD=D1=83=D1=8E=20=D1=83=D1=81=D1=82=D0=BE?= =?UTF-8?q?=D0=B9=D1=87=D0=B8=D0=B2=D0=BE=D1=81=D1=82=D1=8C=20=D0=B1=D0=BE?= =?UTF-8?q?=D1=82=D0=BE=D0=B2=20=D1=8D=D1=82=D0=B0=D0=BF=D0=B0=203?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../game/GameLifecycleTest.java | 11 ++- .../game/LateLevelScenarios.java | 26 ++++-- .../game/LevelEightScenario.java | 87 +++++++++++++++---- .../game/EarlyLevelScenarios.java | 11 +-- .../com/projectsacrifice/game/GameView.java | 23 ++++- .../game/LevelPlaytestBot.java | 9 +- .../game/MovingPlatformLaunchPolicy.java | 6 ++ .../game/MovingPlatformLaunchPolicyTest.java | 27 ++++-- 8 files changed, 156 insertions(+), 44 deletions(-) diff --git a/app/src/androidTest/java/com/projectsacrifice/game/GameLifecycleTest.java b/app/src/androidTest/java/com/projectsacrifice/game/GameLifecycleTest.java index 4c7497d..5add511 100644 --- a/app/src/androidTest/java/com/projectsacrifice/game/GameLifecycleTest.java +++ b/app/src/androidTest/java/com/projectsacrifice/game/GameLifecycleTest.java @@ -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 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()); diff --git a/app/src/androidTest/java/com/projectsacrifice/game/LateLevelScenarios.java b/app/src/androidTest/java/com/projectsacrifice/game/LateLevelScenarios.java index 2ca71ce..0cc41de 100644 --- a/app/src/androidTest/java/com/projectsacrifice/game/LateLevelScenarios.java +++ b/app/src/androidTest/java/com/projectsacrifice/game/LateLevelScenarios.java @@ -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, diff --git a/app/src/androidTest/java/com/projectsacrifice/game/LevelEightScenario.java b/app/src/androidTest/java/com/projectsacrifice/game/LevelEightScenario.java index 2c5ae00..3666368 100644 --- a/app/src/androidTest/java/com/projectsacrifice/game/LevelEightScenario.java +++ b/app/src/androidTest/java/com/projectsacrifice/game/LevelEightScenario.java @@ -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(); } } diff --git a/app/src/main/java/com/projectsacrifice/game/EarlyLevelScenarios.java b/app/src/main/java/com/projectsacrifice/game/EarlyLevelScenarios.java index e11a365..995941f 100644 --- a/app/src/main/java/com/projectsacrifice/game/EarlyLevelScenarios.java +++ b/app/src/main/java/com/projectsacrifice/game/EarlyLevelScenarios.java @@ -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(); diff --git a/app/src/main/java/com/projectsacrifice/game/GameView.java b/app/src/main/java/com/projectsacrifice/game/GameView.java index 900edb5..195fbea 100644 --- a/app/src/main/java/com/projectsacrifice/game/GameView.java +++ b/app/src/main/java/com/projectsacrifice/game/GameView.java @@ -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 ); diff --git a/app/src/main/java/com/projectsacrifice/game/LevelPlaytestBot.java b/app/src/main/java/com/projectsacrifice/game/LevelPlaytestBot.java index 6ef240d..dda0763 100644 --- a/app/src/main/java/com/projectsacrifice/game/LevelPlaytestBot.java +++ b/app/src/main/java/com/projectsacrifice/game/LevelPlaytestBot.java @@ -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); diff --git a/app/src/main/java/com/projectsacrifice/game/MovingPlatformLaunchPolicy.java b/app/src/main/java/com/projectsacrifice/game/MovingPlatformLaunchPolicy.java index 2049df4..448ba88 100644 --- a/app/src/main/java/com/projectsacrifice/game/MovingPlatformLaunchPolicy.java +++ b/app/src/main/java/com/projectsacrifice/game/MovingPlatformLaunchPolicy.java @@ -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() diff --git a/app/src/test/java/com/projectsacrifice/game/MovingPlatformLaunchPolicyTest.java b/app/src/test/java/com/projectsacrifice/game/MovingPlatformLaunchPolicyTest.java index b56184b..c4deac6 100644 --- a/app/src/test/java/com/projectsacrifice/game/MovingPlatformLaunchPolicyTest.java +++ b/app/src/test/java/com/projectsacrifice/game/MovingPlatformLaunchPolicyTest.java @@ -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 ); } }