Initialize Project Sacrifice backlog and source baseline

This commit is contained in:
2026-08-18 00:46:42 +03:00
parent d28ea8c3fd
commit 29d4a2d8d8
34 changed files with 4630 additions and 151 deletions
@@ -0,0 +1,70 @@
package com.projectsacrifice.game;
import android.app.Instrumentation;
import androidx.test.core.app.ActivityScenario;
import androidx.test.ext.junit.runners.AndroidJUnit4;
import androidx.test.platform.app.InstrumentationRegistry;
import org.junit.Test;
import org.junit.runner.RunWith;
/** Acceptance test: a bot must finish the same level implementation shipped in the APK. */
@RunWith(AndroidJUnit4.class)
public final class LevelFivePlaythroughTest {
@Test
public void testBotCompletesLevelFive() {
try (ActivityScenario<MainActivity> scenario = ActivityScenario.launch(MainActivity.class)) {
final GameView[] view = new GameView[1];
scenario.onActivity(activity -> view[0] = activity.gameViewForAutomation());
LevelPlaytestBot bot = new LevelPlaytestBot();
LevelPlaytestBot.Result result = bot.proveLevelFive(
new AndroidDriver(InstrumentationRegistry.getInstrumentation(), view[0]),
25_000L
);
org.junit.Assert.assertTrue(result.diagnostic(), result.completed());
org.junit.Assert.assertTrue("The solution must use at least one volunteer", result.deaths() >= 1);
org.junit.Assert.assertTrue("The delivered corpse must remain in the puzzle", result.corpseCount() >= 1);
org.junit.Assert.assertTrue("The pressure-plate door must open", result.doorOpened());
}
}
private static final class AndroidDriver implements LevelPlaytestBot.Driver {
private final Instrumentation instrumentation;
private final GameView gameView;
AndroidDriver(Instrumentation instrumentation, GameView gameView) {
this.instrumentation = instrumentation;
this.gameView = gameView;
}
@Override
public void startLevel(int oneBasedLevelNumber) {
instrumentation.runOnMainSync(() -> gameView.startLevelForAutomation(oneBasedLevelNumber));
}
@Override
public void setInput(boolean moveLeft, boolean moveRight, boolean jump) {
instrumentation.runOnMainSync(() -> gameView.setAutomationInput(moveLeft, moveRight, jump));
}
@Override
public GameView.AutomationSnapshot snapshot() {
final GameView.AutomationSnapshot[] value = new GameView.AutomationSnapshot[1];
instrumentation.runOnMainSync(() -> value[0] = gameView.automationSnapshot());
return value[0];
}
@Override
public void waitForNextDecision(long millis) {
try {
Thread.sleep(millis);
} catch (InterruptedException interrupted) {
Thread.currentThread().interrupt();
throw new AssertionError("Bot interrupted", interrupted);
}
}
}
}