feat: PolicyControllerAi integration — Forge AI decision interception via policy server
## New File - PolicyControllerAi.java (840 lines): Extends Forge's PlayerControllerAi to intercept AI decisions at chooseSpellAbilityToPlay() and route them through the Python policy server. Falls back to Forge built-in AI on any failure. Inner PolicyAiController overrides AiController with full legal action gathering via ComputerUtilAbility. ## Wiring - GameSession.java: Import + Javadoc for PolicyControllerAi decision flow. Logs decision pipeline when policy server connects. End-of-game reward submission via PolicyControllerAi lifecycle. - BatchRunner.java: New setPolicyServer(url) method. Appends --policy midrange --policyServer <url> to Forge subprocess command when policy server URL is configured. ## Path Updates (Forge-Repo rename) - README.md: Forge link → KoalaTrapLord/Forge-Repo, build path updated - .env.example: FORGE_JAR_PATH and FORGE_WORKING_DIR → Forge-Repo - lab_api.py: Auto-detect paths try Forge-Repo first, forge-repo as legacy ## MacroActionExecutor - Added public isRemovalCard(), isDrawCard(), isRampCard() wrappers so PolicyControllerAi can consult the same card-role databases. Refs: Issue #83 Phase 2.4
This commit is contained in:
1 parent
4cae97ab44
commit
a23fdc55a4
7 files changed
+952
-8
No files matched your search
@@ -1,6 +1,7 @@
|
||||
package commanderailab.batch;
|
||||
|
||||
import commanderailab.ai.AiPolicy;
|
||||
import commanderailab.ai.PolicyControllerAi;
|
||||
import commanderailab.ml.DecisionExtractor;
|
||||
import commanderailab.ml.DecisionLogger;
|
||||
import commanderailab.schema.BatchResult;
|
||||
@@ -76,6 +77,12 @@ public class BatchRunner {
|
||||
private boolean useSimplifiedAi = false; // Use faster AI profile for sims
|
||||
private int aiThinkTimeMs = -1; // -1 = Forge default; >0 = cap AI think time
|
||||
|
||||
// ── Policy server integration (PolicyControllerAi) ────────
|
||||
// When set, the Forge command includes --policyServer so that
|
||||
// PolicyControllerAi (in-process) or the external policy server
|
||||
// can intercept AI decisions during batch simulations.
|
||||
private String policyServerUrl = null;
|
||||
|
||||
// ── Regex patterns for parsing Forge sim output ────────────────────
|
||||
|
||||
// "Game Outcome: Turn 11"
|
||||
@@ -186,6 +193,22 @@ public class BatchRunner {
|
||||
this.aiThinkTimeMs = thinkTimeMs;
|
||||
}
|
||||
|
||||
/**
|
||||
* Enable policy server integration for batch simulations.
|
||||
*
|
||||
* When set, the Forge subprocess command includes
|
||||
* {@code --policy midrange --policyServer <url>} flags, and
|
||||
* the log output notes that {@link PolicyControllerAi} is
|
||||
* available for decision interception.
|
||||
*
|
||||
* @param url Base URL of the Python policy server
|
||||
* (e.g. {@code "http://localhost:8080"})
|
||||
*/
|
||||
public void setPolicyServer(String url) {
|
||||
this.policyServerUrl = url;
|
||||
System.out.println("[BatchRunner] PolicyControllerAi integration enabled — server: " + url);
|
||||
}
|
||||
|
||||
public void enableMlLogging(String resultsDir, String batchId) {
|
||||
this.mlLoggingEnabled = true;
|
||||
this.mlResultsDir = resultsDir;
|
||||
@@ -438,6 +461,19 @@ public class BatchRunner {
|
||||
cmd.add("-c");
|
||||
cmd.add(String.valueOf(clockSeconds));
|
||||
|
||||
// Policy server integration (PolicyControllerAi)
|
||||
// When policyServerUrl is set, tell Forge to use policy-driven AI.
|
||||
// The Python policy server at this URL handles POST /api/policy/decide
|
||||
// and returns macro-actions that PolicyControllerAi maps to concrete
|
||||
// SpellAbility objects.
|
||||
if (policyServerUrl != null && !policyServerUrl.isBlank()) {
|
||||
cmd.add("--policy");
|
||||
cmd.add("midrange");
|
||||
cmd.add("--policyServer");
|
||||
cmd.add(policyServerUrl);
|
||||
System.out.println("[BatchRunner] Policy server: " + policyServerUrl);
|
||||
}
|
||||
|
||||
if (quiet) {
|
||||
cmd.add("-q");
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user