"""Execute the actual full-salvo evidence gates; this is not a native firing result.""" from policy_harness import ROOT, body, run p=ROOT/'addons/core/Scripts/Game/ERR/10_AI/ERR_NativeMortarSalvoProbe.c' base=ROOT/'addons/core/Scripts/Game/ERR/10_AI/ERR_NativeMortarFiringProbe.c' rules='\n'.join(body(base, sig) for sig in ['static bool AimFresh(', 'static bool CommitFresh(', 'static bool EventBound(']) rules=rules.replace('ERR_MortarPrediction.', 'ERR_MortarPrediction::') complete=body(p,'static bool Complete(').replace('ERR_MortarSalvo.', 'ERR_MortarSalvo::') methods='\n'.join(body(p,sig) for sig in ['void NativeCommit(', 'void NativeClosing(', 'void NativeProjectile(']) for a,b in [('ERR_MortarBattery battery','Battery* battery'),('IEntity gun, IEntity projectile','Entity* gun, Entity* projectile'),('string reason, string failure','std::string reason, std::string failure'),('m_Battery.','m_Battery->'),('battery.','battery->'),('Report.','Report->'),('projectile.GetOrigin()','projectile->GetOrigin()'),('GetGame().GetWorld().GetWorldTime()','clockNow'),('ERR_NativeMortarEvidenceRules.','ERR_NativeMortarEvidenceRules::'),('ERR_MortarSalvo.','ERR_MortarSalvo::')]: methods=methods.replace(a,b) run('''#include #include #include #include float clockNow=20000; struct ERR_MortarPrediction {static constexpr float MAX_REPORT_AGE_MS=60000;}; struct ERR_MortarSalvo {static constexpr int ROUNDS=8;}; struct ERR_NativeMortarEvidenceRules {'''+rules+'''}; struct Rules {'''+complete+'''}; struct Entity {int GetOrigin(){return 0;}}; struct Report {int MessageId=7;float ObservedAt=1000;}; struct Battery {void* Activity=nullptr;void* Refresh=nullptr;bool RefreshRejected=false;bool CommandOpen=true,Released=true,stopped=false;int SourceId=7,OrderId=1,OrderShots=0;float AimedAt=19000,AimValidatedAt=19000,FlightTime=20;struct Report report;struct Report* Report=&report;bool Stopped(){return stopped;}}; struct Items {std::vector values;bool Contains(Entity* p){return std::find(values.begin(),values.end(),p)!=values.end();}void Insert(Entity* p){values.push_back(p);}}; templatevoid PrintFormat(Args...args){} struct Probe { void* m_OriginalActivity=nullptr;bool m_RefreshCase=false;int m_UpdatedCommits=0,m_CommitSource=0;float m_CommitObservedAt=0; bool m_Stopped=false,m_BadProjectile=false,m_CommitPending=false,m_ClosureSeen=false,m_ClosureComplete=false; Battery* m_Battery;Entity* m_Gun;Items m_Projectiles;int m_Events=0,m_Step=1,m_Source=7,m_Order=1,m_Commits=0,m_CommitOrder=0,m_CommitShot=0;float m_ObservedAt=1000,m_CommittedAt=0;std::string m_BadReason; bool ReportKnown(Report* report){return report&&report->MessageId==m_Source&&report->ObservedAt==m_ObservedAt;} bool AllAccepted(){return !m_RefreshCase;} '''+methods+'''}; int main(){ assert(Rules::Complete(8,8,8,8,19,false)); for(int count=0;count<8;count++)assert(!Rules::Complete(count,count,count,count,27-count,false)); assert(!Rules::Complete(9,9,9,9,18,false)); assert(!Rules::Complete(8,7,8,8,19,false)); assert(!Rules::Complete(8,8,7,8,19,false)); assert(!Rules::Complete(8,8,8,7,19,false)); assert(!Rules::Complete(8,8,8,8,20,false)); assert(!Rules::Complete(8,8,8,8,18,false)); assert(!Rules::Complete(8,8,8,8,19,true)); Entity gun,foreign,shots[9];Battery b;Probe p;p.m_Battery=&b;p.m_Gun=&gun; p.NativeProjectile(&foreign,&shots[0]);assert(p.m_Events==0); for(int i=0;i<8;i++){ b.OrderShots=i;b.AimedAt=clockNow;b.AimValidatedAt=clockNow; p.NativeCommit(&b,clockNow);assert(p.m_CommitPending&&!p.m_BadProjectile&&p.m_Commits==i+1); clockNow+=500;p.NativeProjectile(&gun,&shots[i]);assert(p.m_Events==i+1&&!p.m_CommitPending&&!p.m_BadProjectile); } b.OrderShots=8;p.NativeClosing(&b,"native artillery activity COMPLETED (shot count is separate)",""); assert(p.m_ClosureSeen&&p.m_ClosureComplete&&!p.m_BadProjectile); p.NativeCommit(&b,clockNow);assert(p.m_BadProjectile&&p.m_Commits==8); // ninth commit forbidden for(int fault=0;fault<11;fault++){ Battery f;Probe q;q.m_Battery=&f;q.m_Gun=&gun;clockNow=20000; if(fault==0)f.report.ObservedAt=1001; // retimestamped contact if(fault==1)f.OrderId=2; if(fault==2)f.SourceId=8; if(fault==3)f.OrderShots=1; // skipped physical event if(fault==4)q.m_Step=2; // post-completion replay if(fault==5)q.m_CommitPending=true; if(fault==6){clockNow=61001;f.AimedAt=61000;f.AimValidatedAt=61000;} if(fault==7)f.AimValidatedAt=9999; if(fault==8)f.Released=false; if(fault==9)f.CommandOpen=false; if(fault==10)f.FlightTime=0; q.NativeCommit(&f,clockNow);assert(q.m_BadProjectile&&q.m_Commits==0); } Battery f;Probe q;q.m_Battery=&f;q.m_Gun=&gun;clockNow=20000; q.NativeCommit(&f,clockNow);q.NativeProjectile(&gun,&shots[0]);q.NativeProjectile(&gun,&shots[0]);assert(q.m_BadProjectile&&q.m_Events==1); for(int fault=0;fault<4;fault++){ Battery f;Probe q;q.m_Battery=&f;q.m_Gun=&gun;q.m_Events=8;q.m_Commits=8;f.OrderShots=8; std::string reason="native artillery activity COMPLETED (shot count is separate)"; if(fault==0){q.m_Events=4;q.m_Commits=4;f.OrderShots=4;} if(fault==1)reason="native aim or firing authorization rejected"; if(fault==2)f.stopped=true; if(fault==3)q.m_CommitPending=true; q.NativeClosing(&f,reason,"delivered target report expired");assert(q.m_BadProjectile); } Battery stopped;Probe quiet;quiet.m_Battery=&stopped;quiet.m_Gun=&gun;quiet.m_Stopped=true; quiet.NativeCommit(&stopped,20000);quiet.NativeProjectile(&gun,&shots[0]);quiet.NativeClosing(&stopped,"HQ stopped",""); assert(!quiet.m_BadProjectile&&quiet.m_Events==0&&quiet.m_Commits==0&&!quiet.m_ClosureSeen); } ''') # Native hooks must count only real events and retain the existing superclass behavior. s=p.read_text() assert s.startswith('#ifdef WORKBENCH') and 'outcome == "mortar-salvo"' in s assert 'super.OnWeaponFired(effectEntity, muzzle, projectileEntity);' in s assert 'super.ReserveShellAirspace(now);' in s and 'super.Cancel(reason);' in s assert 'm_StopUntil = now + 25000' in s assert 'm_Battery.CanRequest(m_Delivered, now)' in s assert 'm_Battery.Order(' not in s and 'm_Battery.BeginRequest(' not in s assert 'm_Battery.Stop();' in body(p,'void Stop(') print('PASS: actual full-salvo gates require eight fresh committed physical launches, natural closure and exact finite inventory; reject partial/extra/replayed events')