Initialize Project Sacrifice backlog and source baseline
This commit is contained in:
@@ -0,0 +1,91 @@
|
||||
package com.projectsacrifice.game;
|
||||
|
||||
/**
|
||||
* Black-box playtest bot for the fifth level. It operates through the same input
|
||||
* flags used by touch controls and observes only player-visible session state.
|
||||
*/
|
||||
public final class LevelPlaytestBot {
|
||||
public interface Driver {
|
||||
void startLevel(int oneBasedLevelNumber);
|
||||
void setInput(boolean moveLeft, boolean moveRight, boolean jump);
|
||||
GameView.AutomationSnapshot snapshot();
|
||||
void waitForNextDecision(long millis);
|
||||
}
|
||||
|
||||
public static final class Result {
|
||||
private final boolean completed;
|
||||
private final boolean doorOpened;
|
||||
private final int deaths;
|
||||
private final int corpseCount;
|
||||
private final String diagnostic;
|
||||
|
||||
Result(boolean completed, boolean doorOpened, int deaths, int corpseCount, String diagnostic) {
|
||||
this.completed = completed;
|
||||
this.doorOpened = doorOpened;
|
||||
this.deaths = deaths;
|
||||
this.corpseCount = corpseCount;
|
||||
this.diagnostic = diagnostic;
|
||||
}
|
||||
|
||||
public boolean completed() { return completed; }
|
||||
public boolean doorOpened() { return doorOpened; }
|
||||
public int deaths() { return deaths; }
|
||||
public int corpseCount() { return corpseCount; }
|
||||
public String diagnostic() { return diagnostic; }
|
||||
}
|
||||
|
||||
public Result proveLevelFive(Driver driver, long timeoutMillis) {
|
||||
driver.startLevel(5);
|
||||
long deadline = System.currentTimeMillis() + timeoutMillis;
|
||||
boolean doorOpened = false;
|
||||
int jumpStage = 0;
|
||||
int respawnsAfterSacrifice = 0;
|
||||
boolean wasAlive = true;
|
||||
GameView.AutomationSnapshot last = driver.snapshot();
|
||||
|
||||
while (System.currentTimeMillis() < deadline) {
|
||||
last = driver.snapshot();
|
||||
doorOpened |= last.allDoorsOpen();
|
||||
if (last.completed()) {
|
||||
driver.setInput(false, false, false);
|
||||
return new Result(true, doorOpened, last.deaths(), last.corpseCount(),
|
||||
"Level 5 completed by bot: deaths=" + last.deaths()
|
||||
+ ", corpses=" + last.corpseCount() + ", doorOpened=" + doorOpened);
|
||||
}
|
||||
|
||||
if (!last.playerAlive()) {
|
||||
driver.setInput(false, false, false);
|
||||
wasAlive = false;
|
||||
} else if (last.deaths() == 0) {
|
||||
driver.setInput(false, true, false);
|
||||
} else if (!doorOpened) {
|
||||
driver.setInput(false, false, false);
|
||||
} else {
|
||||
if (!wasAlive) {
|
||||
respawnsAfterSacrifice++;
|
||||
jumpStage = 0;
|
||||
}
|
||||
if (jumpStage == 0 && last.playerX() < 390f) {
|
||||
driver.setInput(false, true, false);
|
||||
} else if (jumpStage == 0) {
|
||||
driver.setInput(false, true, true);
|
||||
jumpStage = 1;
|
||||
} else if (jumpStage == 1 && last.playerX() >= 750f) {
|
||||
driver.setInput(false, true, true);
|
||||
jumpStage = 2;
|
||||
} else {
|
||||
driver.setInput(false, true, false);
|
||||
}
|
||||
wasAlive = true;
|
||||
}
|
||||
driver.waitForNextDecision(32L);
|
||||
}
|
||||
|
||||
driver.setInput(false, false, false);
|
||||
return new Result(false, doorOpened, last.deaths(), last.corpseCount(),
|
||||
"Bot timed out on level 5: x=" + last.playerX() + ", y=" + last.playerY()
|
||||
+ ", alive=" + last.playerAlive() + ", deaths=" + last.deaths()
|
||||
+ ", corpses=" + last.corpseCount() + ", doorOpened=" + doorOpened
|
||||
+ ", respawnsAfterSacrifice=" + respawnsAfterSacrifice);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user