82 lines
6.5 KiB
Python
82 lines
6.5 KiB
Python
"""Execute actual fixture commit/event/closure gates; not native artillery simulation."""
|
|
from policy_harness import ROOT, body, run
|
|
p=ROOT/'addons/ai/Scripts/Game/ERR/ERR_NativeMortarFiringProbe.c'
|
|
policies='\n'.join(body(p, sig) for sig in ['static bool CommitFresh(', 'static bool EventBound(', 'static bool ExpiredClosure('])
|
|
policies=policies.replace('ERR_MortarPrediction.', 'ERR_MortarPrediction::').replace('string failure', 'Text failure')
|
|
methods='\n'.join(body(p,sig) for sig in ['void NativeCommit(', 'void NativeClosing(', 'void NativeProjectile('])
|
|
methods=methods.replace('ERR_MortarBattery battery','Battery* battery').replace('IEntity gun, IEntity projectile','Entity* gun, Entity* projectile').replace('string reason, string failure','Text reason, Text failure')
|
|
methods=methods.replace('m_Battery.', 'm_Battery->').replace('battery.', 'battery->').replace('Report.', 'Report->').replace('projectile.GetOrigin()', 'projectile->GetOrigin()')
|
|
methods=methods.replace('GetGame().GetWorld().GetWorldTime()', 'clockNow').replace('ERR_NativeMortarEvidenceRules.', 'ERR_NativeMortarEvidenceRules::').replace('ERR_MortarSalvo.', 'ERR_MortarSalvo::')
|
|
run('''#include <cassert>
|
|
#include <vector>
|
|
#include <algorithm>
|
|
#include <string>
|
|
float clockNow=20000;
|
|
struct Text:std::string {using std::string::string;bool Contains(const char* part){return find(part)!=npos;}};
|
|
struct ERR_MortarPrediction {static constexpr float MAX_REPORT_AGE_MS=60000;};
|
|
struct ERR_MortarSalvo {static constexpr int ROUNDS=8;};
|
|
struct ERR_NativeMortarEvidenceRules {
|
|
'''+policies+'''};
|
|
struct Entity {int GetOrigin(){return 0;}};
|
|
struct Report {int MessageId=7;float ObservedAt=1000;};
|
|
struct Battery {bool CommandOpen=true,Released=true,stopped=false;int SourceId=7,OrderId=1,OrderShots=0;float AimedAt=19000,FlightTime=20;struct Report report;struct Report* Report=&report;bool Stopped(){return stopped;}};
|
|
struct Items {std::vector<Entity*> values;bool Contains(Entity* p){return std::find(values.begin(),values.end(),p)!=values.end();}void Insert(Entity* p){values.push_back(p);}};
|
|
template<class... Args>void PrintFormat(Args...args){}
|
|
struct Probe {
|
|
bool m_Stopped=false,m_BadProjectile=false,m_WaitForExpiry=true,m_CommitPending=false,m_ClosureSeen=false,m_ClosureComplete=false,m_ClosureExpired=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;
|
|
'''+methods+'''
|
|
};
|
|
int main(){
|
|
using Rules=ERR_NativeMortarEvidenceRules;
|
|
assert(Rules::EventBound(true,1,1,0,0,60999,90000)); // original fresh commit survives delayed native emission
|
|
assert(Rules::CommitFresh(1000,1000,61000));assert(!Rules::CommitFresh(1000,1000,61001));
|
|
assert(!Rules::CommitFresh(1100,1000,20000));assert(!Rules::CommitFresh(1000,1000,999));
|
|
assert(Rules::ExpiredClosure(1000,61001,"aim: delivered target report expired or invalid"));
|
|
assert(!Rules::ExpiredClosure(1000,61000,"aim: delivered target report expired or invalid"));
|
|
assert(!Rules::ExpiredClosure(1000,65000,"native artillery activity FAILED"));
|
|
Entity gun,other,projectile;Battery b;Probe p;p.m_Battery=&b;p.m_Gun=&gun;
|
|
p.NativeProjectile(&other,&projectile);assert(!p.m_BadProjectile&&p.m_Events==0);
|
|
p.NativeCommit(&b,clockNow);assert(p.m_CommitPending&&p.m_Commits==1&&!p.m_BadProjectile);
|
|
p.NativeProjectile(&gun,&projectile);assert(p.m_Events==1&&!p.m_BadProjectile&&!p.m_CommitPending);
|
|
p.NativeProjectile(&gun,&projectile);assert(p.m_BadProjectile&&p.m_Events==1);
|
|
Probe nullEvent;nullEvent.m_Battery=&b;nullEvent.m_Gun=&gun;nullEvent.NativeProjectile(&gun,nullptr);assert(nullEvent.m_BadProjectile&&nullEvent.m_Events==0);
|
|
Probe stoppedObserver;stoppedObserver.m_Battery=&b;stoppedObserver.m_Gun=&gun;stoppedObserver.m_Stopped=true;stoppedObserver.NativeCommit(&b,20000);stoppedObserver.NativeProjectile(&gun,&projectile);assert(stoppedObserver.m_Commits==0&&stoppedObserver.m_Events==0&&!stoppedObserver.m_BadProjectile);
|
|
// Physical launch after report expiry is legitimate if its commit was fresh.
|
|
b=Battery();b.Report=&b.report;b.AimedAt=60500;Probe delayed;delayed.m_Battery=&b;delayed.m_Gun=&gun;delayed.m_Step=3;
|
|
delayed.NativeCommit(&b,60999);clockNow=62999;delayed.NativeProjectile(&gun,&projectile);
|
|
assert(delayed.m_Events==1&&!delayed.m_BadProjectile);
|
|
for(int fault=0;fault<10;++fault){
|
|
b=Battery();b.Report=&b.report;clockNow=20000;Probe q;q.m_Battery=&b;q.m_Gun=&gun;
|
|
if(fault==0)b.CommandOpen=false;
|
|
if(fault==1)b.Released=false;
|
|
if(fault==2)b.SourceId=8;
|
|
if(fault==3)b.AimedAt=-1;
|
|
if(fault==4)b.AimedAt=9999;
|
|
if(fault==5)b.FlightTime=0;
|
|
if(fault==6)q.m_Step=2;
|
|
if(fault==7)b.report.ObservedAt=1001;
|
|
if(fault==8)b.OrderId=2;
|
|
if(fault==9){clockNow=61001;b.AimedAt=61000;}
|
|
q.NativeCommit(&b,clockNow);assert(q.m_BadProjectile&&!q.m_CommitPending&&q.m_Commits==0);
|
|
}
|
|
b=Battery();b.Report=&b.report;clockNow=20000;Probe missing;missing.m_Battery=&b;missing.m_Gun=&gun;
|
|
missing.NativeProjectile(&gun,&projectile);assert(missing.m_BadProjectile);
|
|
Probe duplicate;duplicate.m_Battery=&b;duplicate.m_Gun=&gun;duplicate.NativeCommit(&b,20000);duplicate.NativeCommit(&b,20000);assert(duplicate.m_BadProjectile&&duplicate.m_Commits==1);
|
|
for(int fault=0;fault<3;++fault){
|
|
b=Battery();b.Report=&b.report;clockNow=20000;Probe changed;changed.m_Battery=&b;changed.m_Gun=&gun;changed.NativeCommit(&b,20000);
|
|
if(fault==0)b.OrderId++;
|
|
if(fault==1)b.OrderShots++;
|
|
if(fault==2)clockNow=19999;
|
|
|
|
changed.NativeProjectile(&gun,&projectile);assert(changed.m_BadProjectile);
|
|
}
|
|
b=Battery();b.Report=&b.report;clockNow=65000;Probe expired;expired.m_Battery=&b;expired.m_Gun=&gun;
|
|
expired.NativeClosing(&b,"native aim or firing authorization rejected","aim: delivered target report expired or invalid");assert(expired.m_ClosureSeen&&expired.m_ClosureExpired&&!expired.m_BadProjectile);
|
|
Probe unrelated;unrelated.m_Battery=&b;unrelated.NativeClosing(&b,"native activity FAILED","");assert(unrelated.m_BadProjectile);
|
|
Probe stopped;stopped.m_Battery=&b;b.stopped=true;stopped.NativeClosing(&b,"HQ stopped","aim: delivered target report expired or invalid");assert(stopped.m_BadProjectile);
|
|
b.stopped=false;b.OrderShots=8;Probe complete;complete.m_Battery=&b;complete.m_Events=8;clockNow=50000;complete.NativeClosing(&b,"native artillery activity COMPLETED","");assert(complete.m_ClosureComplete&&!complete.m_BadProjectile);
|
|
}
|
|
''')
|
|
print('PASS: actual probe binds native events to fresh immutable commits, permits delayed emission, rejects unrelated expiry closure and premature stop')
|