Ground bot intentions in live game knowledge and verify outcomes
Core tests / core (push) Successful in 28s

This commit is contained in:
Codex
2026-09-25 13:28:03 +08:00
parent 20ccd0fced
commit 502cb1e4fd
17 changed files with 251 additions and 24 deletions
+25
View File
@@ -0,0 +1,25 @@
import type {Bot,Decision,IntentCheck} from './types';
export function startIntentCheck(bot:Bot,decision:Decision,commandId:string,now:number,partyPeer?:string):IntentCheck|undefined{
const w=bot.world;if(!w||now-w.at>90||now<w.at)return;
return {id:commandId,action:decision.action,startedAt:now,baselineAt:w.at,status:'pending',detail:'Waiting for a fresh game observation; command submission is not completion.',partyPeer,baseline:{level:bot.level,xp:w.xp,map:w.mapId,x:w.x,y:w.y,hp:w.healthPct,mana:w.manaPct,food:w.foodCount,drink:w.drinkCount,durability:w.minDurabilityPct,readinessAt:w.readinessAt,groupNames:[...w.groupNames]}};
}
export function observeIntentChecks(bot:Bot){
const w=bot.world;if(!w)return;
for(const c of bot.autonomy?.intentChecks??[]){
if(c.status!=='pending'||w.at<=c.baselineAt||w.at<c.startedAt)continue;
const finish=(status:IntentCheck['status'],detail:string)=>{c.status=status;c.detail=detail;c.checkedAt=w.at;};
if(w.isDead||w.isGhost){finish('interrupted','Death interrupted the intention; native resurrection takes priority.');continue;}
if(w.humanControlled){finish('interrupted','Human control took priority.');continue;}
const b=c.baseline,elapsed=w.at-c.startedAt;
if(c.action==='quest'&&(bot.level>b.level||(w.xp!==undefined&&b.xp!==undefined&&w.xp>b.xp))){finish('observed','Experience or level increased after the intention; this alone does not prove a quest turn-in.');continue;}
if(c.action==='explore'&&(w.mapId!==b.map||Math.hypot(w.x-b.x,w.y-b.y)>=20)){finish('observed','Travel of at least 20 yards or a map change observed.');continue;}
if(c.action==='rest'&&!w.inCombat&&(w.healthPct??0)>=95&&(w.manaPct===undefined||w.manaPct>=65)){
finish('observed','Recovered health and sufficient mana observed out of combat.');continue;
}
if(c.action==='trade'&&(w.readinessAt??0)>(b.readinessAt??0)&&((w.foodCount??0)>(b.food??Infinity)||(w.drinkCount??0)>(b.drink??Infinity)||(w.minDurabilityPct??0)>(b.durability??Infinity))){finish('observed','Supplies or equipment condition improved; purchase attribution is not established.');continue;}
if(c.action==='socialize'&&c.partyPeer&&w.groupId&&w.groupNames.includes(c.partyPeer)){
finish('observed','Party membership with '+c.partyPeer+' verified in the game.');continue;
}
if(elapsed>=600)finish('no_progress',c.action==='socialize'&&!c.partyPeer?'No measurable party objective was attached; dialogue is counted separately.':'No matching outcome observed within ten minutes. This is not proof of an engine failure.');
}
}