package com.projectsacrifice.game; /** Declarative intended-route scenarios for the first four teaching levels. */ public final class EarlyLevelScenarios { private EarlyLevelScenarios() {} public static LevelPlaytestBot.Scenario levelOne() { return LevelPlaytestBot.Scenario.builder(1, "Level 1: movement and jump") .step("Approach the first ledge", 3_000L, LevelPlaytestBot.Input.right(), snapshot -> snapshot.playerX() >= 500f) .step("Jump over the first ledge", 3_000L, LevelPlaytestBot.Input.rightJump(), snapshot -> snapshot.playerX() >= 900f) .step("Release jump before the upper ledge", 1_000L, LevelPlaytestBot.Input.right(), snapshot -> snapshot.playerX() >= 950f) .step("Jump over the upper ledge", 3_000L, LevelPlaytestBot.Input.rightJump(), snapshot -> snapshot.playerX() >= 1_330f) .step("Reach the relic", 3_000L, LevelPlaytestBot.Input.right(), GameView.AutomationSnapshot::completed) .build(); } public static LevelPlaytestBot.Scenario levelTwo() { return LevelPlaytestBot.Scenario.builder(2, "Level 2: three-corpse bridge") .step("Place the first bridge body", 4_000L, LevelPlaytestBot.Input.right(), snapshot -> snapshot.deaths() >= 1) .step("Wait for the second volunteer", 2_000L, LevelPlaytestBot.Input.none(), EarlyLevelScenarios::respawnedAtStart) .step("Approach the first bridge body", 3_000L, LevelPlaytestBot.Input.right(), snapshot -> snapshot.playerX() >= 470f) .step("Jump to the middle of the spikes", 2_000L, LevelPlaytestBot.Input.rightJump(), snapshot -> snapshot.playerX() >= 730f) .step("Place the second bridge body", 2_000L, LevelPlaytestBot.Input.none(), snapshot -> snapshot.deaths() >= 2) .step("Wait for the third volunteer", 2_000L, LevelPlaytestBot.Input.none(), EarlyLevelScenarios::respawnedAtStart) .step("Return to the corpse bridge", 3_000L, LevelPlaytestBot.Input.right(), snapshot -> snapshot.playerX() >= 470f) .step("Jump to the far side of the spikes", 2_000L, LevelPlaytestBot.Input.rightJump(), snapshot -> snapshot.playerX() >= 750f) .step("Step off the middle bridge body", 2_000L, LevelPlaytestBot.Input.left(), snapshot -> snapshot.playerX() <= 690f) .step("Place the third bridge body", 2_000L, LevelPlaytestBot.Input.none(), snapshot -> snapshot.deaths() >= 3) .step("Wait for the crossing volunteer", 2_000L, LevelPlaytestBot.Input.none(), EarlyLevelScenarios::respawnedAtStart) .step("Approach the completed bridge", 3_000L, LevelPlaytestBot.Input.right(), snapshot -> snapshot.playerX() >= 470f) .step("Land on the far bridge body", 3_000L, LevelPlaytestBot.Input.rightJump(), snapshot -> snapshot.playerOnGround() && snapshot.playerX() >= 800f) .step("Jump from the bridge to safe floor", 3_000L, LevelPlaytestBot.Input.rightJump(), snapshot -> snapshot.playerX() >= 900f) .step("Release jump before the final ledge", 2_000L, LevelPlaytestBot.Input.right(), snapshot -> snapshot.playerX() >= 1_030f) .step("Jump over the final ledge", 3_000L, LevelPlaytestBot.Input.rightJump(), snapshot -> snapshot.playerX() >= 1_450f) .step("Reach the relic", 4_000L, LevelPlaytestBot.Input.right(), GameView.AutomationSnapshot::completed) .build(); } public static LevelPlaytestBot.Scenario levelThree() { return LevelPlaytestBot.Scenario.builder(3, "Level 3: saw corpse pressure signal") .step("Leave a volunteer at the saw", 4_000L, LevelPlaytestBot.Input.right(), snapshot -> snapshot.deaths() >= 1) .step("Prove the corpse opens the pressure door", 3_000L, LevelPlaytestBot.Input.none(), GameView.AutomationSnapshot::allDoorsOpen) .step("Wait for the next volunteer", 2_000L, LevelPlaytestBot.Input.none(), EarlyLevelScenarios::respawnedAtStart) .step("Approach the saw", 3_000L, LevelPlaytestBot.Input.right(), LevelPlaytestBot.whileDeathsAtMost(1, snapshot -> snapshot.playerAlive() && snapshot.playerOnGround() && snapshot.playerX() >= 360f)) .step("Take off before the saw", 1_000L, LevelPlaytestBot.Input.rightJump(), LevelPlaytestBot.whileDeathsAtMost(1, snapshot -> snapshot.playerAlive() && !snapshot.playerOnGround() && snapshot.playerY() <= 620f)) .step("Clear the saw and plate body", 3_000L, LevelPlaytestBot.Input.right(), 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(); } public static LevelPlaytestBot.Scenario levelFour() { return LevelPlaytestBot.Scenario.builder(4, "Level 4: toggle lift to gallery") .step("Cross the toggle once and activate the lift", 3_000L, LevelPlaytestBot.Input.right(), GameView.AutomationSnapshot::firstMovingPlatformPowered) .step("Approach the powered moving lift", 3_000L, LevelPlaytestBot.Input.right(), snapshot -> snapshot.firstMovingPlatformPowered() && snapshot.playerX() >= 800f) .step("Jump onto the moving lift", 3_000L, LevelPlaytestBot.Input.rightJump(), snapshot -> snapshot.playerX() >= 1_050f && snapshot.playerY() < 690f) .step("Ride the lift to its upper phase", 7_000L, LevelPlaytestBot.Input.none(), snapshot -> snapshot.playerY() <= 330f) .step("Move to the lift's right edge", 2_000L, LevelPlaytestBot.Input.right(), snapshot -> snapshot.playerX() >= 1_225f) .step("Jump from the lift to the upper gallery", 3_000L, LevelPlaytestBot.Input.rightJump(), snapshot -> snapshot.playerX() >= 1_610f && snapshot.playerY() <= 400f) .step("Reach the upper relic", 4_000L, LevelPlaytestBot.Input.right(), GameView.AutomationSnapshot::completed) .build(); } private static boolean respawnedAtStart(GameView.AutomationSnapshot snapshot) { return snapshot.playerAlive() && snapshot.playerX() < 250f; } }