Завершить интеграционную устойчивость ботов этапа 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();
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user