"""Execute tactical cue selection, queueing and playback revalidation from production.""" import re from policy_harness import ROOT, body, run P=ROOT/'addons/core/Scripts/Game/ERR/10_AI/ERR_HQOperationSpeech.c' C=ROOT/'addons/core/Scripts/Game/ERR/10_AI/ERR_SoldierSpeechContext.c' E=ROOT/'addons/core/Scripts/Game/ERR/10_AI/ERR_HQExecution.c' T=ROOT/'addons/core/Scripts/Game/ERR/10_AI/ERR_HQTask.c' def cpp(s): s=s.replace('protected ','').replace('null','nullptr') for typ in ('ERR_HQTask','ERR_HQExecutionReport','ERR_HQUnit','SCR_AITalkRequest'): s=re.sub(r'\b'+typ+r' (\w+)',typ+r'* \1',s) for n in ('task','report','unit','request','m_Agent','m_VoNComponent','Group','Task','Execution'): s=s.replace(n+'.',n+'->') for n in ('ERR_HQOperationRole','ERR_HQExecutionState','ERR_HQExecutionRules','ERR_HQOperationSpeechRules','ERR_SoldierConversationRules','ECommMethod','ECommunicationType','vector','SCR_EAITalkRequestPreset'): s=s.replace(n+'.',n+'::') return s enums=body(T,'enum ERR_HQOperationRole')+';'+body(E,'enum ERR_HQExecutionState')+';' enums=enums.replace('enum ','enum class ') rules=cpp(body(P,'static int Phrase(')+body(P,'static bool QueuedFresh(')) execute=cpp(body(C,'void ERR_SpeechOperation(')+body(C,'protected bool ERR_SpeechOperationValid(')) run(r''' #include #include '''+enums+r''' struct ERR_HQTask{int OperationId=1,OperationRevision=2,ExecutionId=10;float ExpiresAt=100000,SupportUntil=21000;ERR_HQOperationRole OperationRole=ERR_HQOperationRole::RESERVE;}; struct ERR_HQExecutionReport{int OperationId=1,OperationRevision=2,ExecutionId=10;float ObservedAt=10000,SupportUntil=21000,SearchedRadius=0;bool PhysicallyArrived=true,HasContact=false,SupportReady=false;ERR_HQExecutionState State=ERR_HQExecutionState::ARRIVED;}; struct ERR_HQExecutionRules{static bool Terminal(ERR_HQExecutionState s){return s==ERR_HQExecutionState::COMPLETED||s==ERR_HQExecutionState::FAILED||s==ERR_HQExecutionState::SUPERSEDED;}static bool SupportFresh(float at,float now){return at>now&&at<=now+30000;}}; struct ERR_HQOperationSpeechRules{ '''+rules+r''' }; struct Agent; struct Group{Agent*leader=nullptr;bool slave=false;int players=0;bool IsSlave(){return slave;}int GetPlayerCount(bool){return players;}Agent*GetLeaderAgent(){return leader;}}; struct Agent{Group*group=nullptr;Group*GetParentGroup(){return group;}}; struct Execution{ERR_HQExecutionReport report;bool pending=true;ERR_HQExecutionReport*Snapshot(int,int,float){return pending?&report:nullptr;}}; struct ERR_HQUnit{int Id=1,LogisticsReservation=0;bool HomeGuard=false,ReservedForSupport=false;struct Group*Group=nullptr;ERR_HQTask*Task=nullptr;struct Execution*Execution=nullptr;}; namespace ECommMethod{enum{DIRECT,RADIO};} namespace ECommunicationType{enum{REPORT_IDLE};} namespace SCR_EAITalkRequestPreset{enum{IRRELEVANT};} namespace vector{int Zero=0;} struct Von{int method=ECommMethod::DIRECT;int GetCommMethod(){return method;}}; struct SCR_AITalkRequest{int m_ERRSpeechPhrase=-1,m_ERROperationExecution=0;float m_ERROperationQueuedAt=-1;ERR_HQUnit*m_ERROperationUnit=nullptr;SCR_AITalkRequest(int,void*,int,int,bool,bool,int){}}; struct ERR_SoldierConversationRules{static bool Quiet(bool threat,bool overt){return threat&&!overt;}}; struct Handler{bool enabled=true,m_ERRSpeechThreat=false,m_ERRSpeechOvert=false;float m_ERROperationNext=0,m_ERRSpeechNextLine=0;int m_ERROperationLastExecution=0,m_ERROperationLastPhrase=-1,requests=0;Agent*m_Agent=nullptr;Von*m_VoNComponent=nullptr;SCR_AITalkRequest*queued=nullptr; bool ERR_SpeechEnabled(){return enabled;}void ERR_SpeechObserve(float){}void AddRequest(SCR_AITalkRequest*q){requests++;queued=q;} '''+execute+r''' }; struct Fixture{ERR_HQTask task;Execution exec;ERR_HQUnit unit;Agent actor;Group group;Von von;Handler comms; Fixture(){unit.Group=&group;unit.Task=&task;unit.Execution=&exec;actor.group=&group;group.leader=&actor;comms.m_Agent=&actor;comms.m_VoNComponent=&von;} int Phrase(float now=10000){return ERR_HQOperationSpeechRules::Phrase(&task,&exec.report,now);} }; int main(){ {Fixture f;assert(f.Phrase()==1203);f.exec.report.PhysicallyArrived=false;assert(f.Phrase()==-1);} for(int failure=0;failure<9;failure++){Fixture f; if(failure==0)f.exec.report.ExecutionId++; if(failure==1)f.exec.report.OperationId++; if(failure==2)f.exec.report.OperationRevision++; if(failure==3)f.task.ExpiresAt=10000; if(failure==4)f.exec.report.ObservedAt=10001; if(failure==5)f.exec.report.ObservedAt=7499; if(failure==6)f.exec.report.ObservedAt=-1; if(failure==7)f.exec.report.ObservedAt=std::numeric_limits::quiet_NaN(); if(failure==8)f.exec.report.State=ERR_HQExecutionState::FAILED; assert(f.Phrase()==-1); } {Fixture f;f.task.OperationRole=ERR_HQOperationRole::FIX;f.exec.report.HasContact=true; assert(f.Phrase()==-1);f.exec.report.SupportReady=true;assert(f.Phrase()==1200); f.exec.report.HasContact=false;assert(f.Phrase()==-1); // remembered-area fire never says it can cover an advance f.exec.report.HasContact=true;f.exec.report.SupportUntil=10000;assert(f.Phrase()==-1); f.exec.report.SupportUntil=21000;f.exec.report.State=ERR_HQExecutionState::SUPERSEDED;assert(f.Phrase()==-1); } {Fixture f;f.task.OperationRole=ERR_HQOperationRole::SEARCH;f.exec.report.State=ERR_HQExecutionState::COMPLETED; assert(f.Phrase()==-1);f.exec.report.SearchedRadius=10;assert(f.Phrase()==1204); f.exec.report.HasContact=true;assert(f.Phrase()==-1); } {Fixture f;f.task.OperationRole=ERR_HQOperationRole::FLANK;f.exec.report.State=ERR_HQExecutionState::TRAVELLING; assert(f.Phrase()==1201);f.task.SupportUntil=10000;assert(f.Phrase()==-1); f.task.OperationRole=ERR_HQOperationRole::WITHDRAW;assert(f.Phrase()==1202); f.exec.report.State=ERR_HQExecutionState::BLOCKED;assert(f.Phrase()==-1); } {Fixture f;f.comms.ERR_SpeechOperation(&f.unit,10000);assert(f.comms.requests==1&&f.comms.queued->m_ERRSpeechPhrase==1203); assert(f.comms.ERR_SpeechOperationValid(f.comms.queued,10001)); f.comms.ERR_SpeechOperation(&f.unit,10001);assert(f.comms.requests==1); f.exec.report.ObservedAt=40000;f.comms.ERR_SpeechOperation(&f.unit,40000);assert(f.comms.requests==1); // same order/action is not repeated f.task.ExecutionId++;f.exec.report.ExecutionId++;f.comms.ERR_SpeechOperation(&f.unit,40000);assert(f.comms.requests==2); } for(int failure=0;failure<11;failure++){Fixture f;f.comms.ERR_SpeechOperation(&f.unit,10000);auto q=f.comms.queued;assert(q); if(failure==0)f.unit.Task=nullptr; if(failure==1)f.task.ExecutionId++; if(failure==2)f.exec.pending=false; // acknowledgement is not fresh physical proof if(failure==3)f.unit.HomeGuard=true; if(failure==4)f.unit.ReservedForSupport=true; if(failure==5)f.unit.LogisticsReservation=1; if(failure==6)f.group.slave=true; if(failure==7)f.group.players=1; if(failure==8)f.group.leader=nullptr; if(failure==9)f.actor.group=nullptr; if(failure==10)f.exec.report.HasContact=true; assert(!f.comms.ERR_SpeechOperationValid(q,10001)); } {Fixture f;f.comms.ERR_SpeechOperation(&f.unit,10000);f.exec.report.ObservedAt=13000; assert(!f.comms.ERR_SpeechOperationValid(f.comms.queued,13000)); // stale queue cannot become true again } for(int failure=0;failure<4;failure++){Fixture f; if(failure==0)f.comms.enabled=false; if(failure==1)f.von.method=ECommMethod::RADIO; if(failure==2)f.comms.m_ERRSpeechThreat=true; if(failure==3)f.group.leader=nullptr; f.comms.ERR_SpeechOperation(&f.unit,10000);assert(!f.comms.requests); } assert(!ERR_HQOperationSpeechRules::QueuedFresh(10000,9999)); assert(ERR_HQOperationSpeechRules::QueuedFresh(10000,12500)); assert(!ERR_HQOperationSpeechRules::QueuedFresh(10000,12501)); } ''') print('PASS: actual-action speech, finite current cover, local search wording, silence after replacement/transfer/stale queue, stable cooldown and optional direct speech')