"""Actual finite service lifecycle methods; controller/physical APIs are fakes.""" from policy_harness import ROOT, body, run import re P=ROOT/'addons/core/Scripts/Game/ERR/10_AI/ERR_AircraftService.c' def cpp(s): s=s.replace('protected ','').replace('return null;', 'return nullptr;') for a,b in [('ERR_AircraftServiceEntry entry','Entry* entry'),('ERR_AircraftServiceEntry known','Entry* known'),('new ERR_AircraftServiceEntry()','new Entry()'),('ERR_AircraftRouteEnvelope qualification','Qualification* qualification'),('ERR_AircraftRouteFlight flight','RouteFlight* flight'),('ERR_AircraftFieldFlight flight','FieldFlight* flight'),('ERR_AircraftFieldEnvelope qualification','FieldQualification* qualification'),('new ERR_AircraftRouteFlight()','new RouteFlight()'),('new ERR_AircraftFieldFlight()','new FieldFlight()'),('ERR_GameMode mode','Mode* mode'),('ERR_GameMode.Get()','Mode::Get()'),('ERR_AircraftFlightRules.','Rules::'),('ERR_AircraftFlightState.','State::'),('Replication.IsServer()','server'),('string reason','std::string reason'),('vector destination = "0 0 0"','Vec destination')]:s=s.replace(a,b) s=re.sub(r'foreach \(Entry\* (entry|known) : m_Entries\)',r'for (Entry* \1 : m_Entries.values)',s) for name in ('entry','known','qualification','GetGame()','m_Mode','m_World','s_Retainers','entry.Flight','flight'): s=s.replace(name+'.',name+'->') s=s.replace('entry->Flight.','entry->Flight->').replace('entry->Reason.IsEmpty()','entry->Reason.empty()') return s.replace('ERR_AircraftServiceEntry BeginAttempt(', 'Entry* BeginAttempt(').replace('ERR_AircraftServiceEntry Find(', 'Entry* Find(').replace('ERR_AircraftServiceEntry entry)', 'Entry* entry)').replace('vector Destination(', 'Vec Destination(').replace('string Reason(', 'std::string Reason(') keys=['protected bool Context(', 'protected ERR_AircraftServiceEntry Find(', 'bool Register(', 'bool Ready(', 'protected ERR_AircraftServiceEntry BeginAttempt(', 'bool StartRoute(', 'bool StartField(', 'protected bool RecordStart(', 'protected void Finish(', 'bool Cancel(', 'void Tick(', 'void Stop(', 'protected void ReleaseRetainers(', 'bool Drained(', 'bool Stopping(', 'int RegisteredCount(', 'int AttemptedOrders(', 'bool Pending(', 'bool Retired(', 'int OrderToken(', 'float OrderDeadline(', 'int FlightState(', 'string Reason(', 'vector Destination('] run(r''' #include #include #include #include #include #include bool server=true; namespace State {enum {IDLE,HOOKS,STARTING,POSITIVE,NEGATIVE,CLIMB,LANDING,SHUTDOWN,COMPLETE,CANCELLED,FAILED,RELINQUISHED,TRANSLATING};} struct Vec {float x=0,y=0,z=0;}; struct World {float now=1000;float GetWorldTime(){return now;}}world; struct Game {World* current=&world;World* GetWorld(){return current;}}game;Game* gamePointer=&game;Game* GetGame(){return gamePointer;} struct Mode {bool active=true;World* world=&::world;static Mode* current;World* GetWorld(){return world;}bool Active(){return active;}static Mode* Get(){return current;}};Mode* Mode::current=nullptr; struct Rules {static bool Deadline(float now,float deadline){return now>=0&&deadline>now&&deadline-now<=240000;}}; struct Entity {bool original=true,ready=true;int startMode=0,next=State::HOOKS;}; using Vehicle=Entity*;using SCR_AIGroup=Entity*;using IEntity=Entity*;using PilotCompartmentSlot=Entity*; struct Qualification {bool claimed=false;Vec target={20,0,0};Vec Destination(){return target;}}; struct FieldQualification:Qualification {FieldQualification(){target={100,0,0};}}; int starts=0,claims=0,ticks=0,cancels=0,routeConstructions=0,fieldConstructions=0; struct Flight { virtual ~Flight()=default;int kind=0; Entity* aircraft=nullptr;int token=0,state=State::IDLE;float deadline=0;bool cancelled=false;std::string reason; bool Finished(){return state>=State::COMPLETE&&state<=State::RELINQUISHED;} bool StartRoute(Mode*,Vehicle a,SCR_AIGroup,IEntity,PilotCompartmentSlot,Qualification* q,int t,float d){ starts++;aircraft=a; if(a->startMode==1||q->claimed)return false; q->claimed=true;claims++;token=t;deadline=d;state=State::HOOKS; if(a->startMode==2){state=State::FAILED;return false;} if(a->startMode==3)return false; return true; } void Cancel(std::string r){if(Finished()||cancelled)return;cancelled=true;cancels++;reason=r;state=State::LANDING;} void Tick(){ticks++;if(!aircraft->original||!Mode::Get()||!Mode::Get()->active){state=State::RELINQUISHED;return;}if(world.now>=deadline){state=State::FAILED;return;}state=aircraft->next;} int State(){return state;}int OrderToken(){return token;}std::string Reason(){return reason;} }; struct RouteFlight:Flight {RouteFlight(){kind=1;routeConstructions++;}}; struct FieldFlight:Flight {FieldFlight(){kind=2;fieldConstructions++;}bool StartField(Mode* m,Vehicle a,SCR_AIGroup g,IEntity p,PilotCompartmentSlot s,FieldQualification* q,int t,float d){return StartRoute(m,a,g,p,s,q,t,d);}}; struct Entry {Vehicle Aircraft=nullptr;SCR_AIGroup Group=nullptr;IEntity Pilot=nullptr;PilotCompartmentSlot Seat=nullptr;struct Flight* Flight=nullptr;int Token=0;float Deadline=0;Vec Destination;bool Pending=false,CancelRequested=false,Retired=false;std::string Reason;}; struct Entries {std::vector values;int Count(){return values.size();}void Insert(Entry* e){values.push_back(e);}}; struct Tokens {std::set values;int Count(){return values.size();}bool Contains(int n){return values.count(n);}void Insert(int n){values.insert(n);}}; struct Service; struct Registry {std::map values;Service* Get(Entity* a){auto i=values.find(a);return i==values.end()?nullptr:i->second;}void Set(Entity* a,Service* s){values[a]=s;}void Remove(Entity* a){values.erase(a);}}registry; struct Service { static const int MAX_AIRCRAFT=4,MAX_ORDERS=128;static Registry* s_Retainers; Mode* m_Mode;World* m_World=&world;Entries m_Entries;Tokens m_UsedTokens;bool m_Stopping=false; Service(Mode* m):m_Mode(m){} bool Original(Entry* e){return Context()&&e&&e->Aircraft&&e->Aircraft->original;} bool PhysicalReady(Entry* e){return Original(e)&&e->Aircraft->ready;} ''' + '\n'.join(cpp(body(P,k)) for k in keys) + r''' };Registry* Service::s_Retainers=®istry; struct Setup { Mode mode;Entity a[5],g[5],p[5],seat[5];Service service;Qualification q; Setup():service(&mode){registry.values.clear();server=true;gamePointer=&game;game.current=&world;world.now=1000;Mode::current=&mode;starts=claims=ticks=cancels=routeConstructions=fieldConstructions=0;} bool Register(int i=0){return service.Register(&a[i],&g[i],&p[i],&seat[i]);} bool Start(int token=1){return service.StartRoute(&a[0],&q,token,200000);} }; int main(){ {Setup x;for(int i=0;i<4;i++)assert(x.Register(i));assert(!x.Register(4)&&x.service.RegisteredCount()==4&&starts==0&&claims==0);} {Setup x;assert(x.Register());assert(!x.Register());Service other(&x.mode);assert(!other.Register(&x.a[0],&x.g[0],&x.p[0],&x.seat[0]));assert(!x.service.Register(&x.a[1],&x.g[1],&x.p[0],&x.seat[1]));assert(!x.service.Register(&x.a[1],&x.g[0],&x.p[1],&x.seat[1]));assert(!x.service.Register(&x.a[1],&x.g[1],&x.p[1],&x.seat[0]));} {Setup x;x.a[0].ready=false;assert(!x.Register()&®istry.values.empty());x.a[0].ready=true;x.mode.active=false;assert(!x.Register());} {Setup x;assert(x.Register());Mode other;Mode::current=&other;assert(!x.Start()&&starts==0);Mode::current=&x.mode;World otherWorld;game.current=&otherWorld;assert(!x.Start()&&starts==0);game.current=&world;server=false;assert(!x.Start()&&starts==0);} {Setup x;assert(x.Register());assert(!x.service.StartRoute(&x.a[0],nullptr,1,200000));assert(!x.Start(0));assert(!x.service.StartRoute(&x.a[0],&x.q,1,world.now));assert(!x.service.StartRoute(&x.a[0],&x.q,1,world.now+240001));assert(!x.service.StartRoute(&x.a[0],&x.q,1,NAN));assert(starts==0&&x.service.AttemptedOrders()==0);} {Setup x;assert(x.Register());assert(x.Start());assert(starts==1&&claims==1&&x.service.Pending(&x.a[0]));assert(!x.Start()&&!x.Start(2)&&starts==1&&claims==1);assert(x.service.OrderToken(&x.a[0])==1&&x.service.OrderDeadline(&x.a[0])==200000);x.q.target.x=999;assert(x.service.Destination(&x.a[0]).x==20);} // Cancellation retains the same controller/token/deadline and continues Tick. {Setup x;assert(x.Register()&&x.Start());Entry* entry=x.service.Find(&x.a[0]);Flight* flight=entry->Flight;x.a[0].next=State::TRANSLATING;x.service.Tick();assert(!x.service.Cancel(&x.a[0],2,"foreign"));assert(x.service.Cancel(&x.a[0],1,"report lost"));assert(!x.service.Cancel(&x.a[0],1,"duplicate"));assert(cancels==1&&entry->Flight==flight&&x.service.Pending(&x.a[0])&&!x.service.Ready(&x.a[0]));x.a[0].next=State::LANDING;x.service.Tick();assert(ticks==2&&entry->Flight==flight&&x.service.OrderDeadline(&x.a[0])==200000);x.a[0].next=State::CANCELLED;x.service.Tick();assert(x.service.Drained()&&!x.service.Retired(&x.a[0])&&x.service.Ready(&x.a[0]));assert(!x.Start());Qualification q;assert(x.service.StartRoute(&x.a[0],&q,2,210000)&&starts==2&&claims==2);} // Stop is admission/cancellation, not fabricated completion or disposal. {Setup x;assert(x.Register()&&x.Start());x.service.Stop();x.service.Stop();assert(x.service.Stopping()&&!x.service.Drained()&&cancels==1&®istry.Get(&x.a[0])==&x.service);assert(!x.Register(1)&&!x.Start(2));x.a[0].next=State::LANDING;x.service.Tick();assert(!x.service.Drained()&®istry.Get(&x.a[0])==&x.service);x.a[0].next=State::CANCELLED;x.service.Tick();assert(x.service.Drained()&®istry.values.empty()&&!x.service.Ready(&x.a[0]));} // Completion must not overrule current seat/health/contact/fuel readiness. {Setup x;assert(x.Register()&&x.Start());x.a[0].next=State::COMPLETE;x.a[0].ready=false;x.service.Tick();assert(x.service.Drained()&&!x.service.Ready(&x.a[0]));x.a[0].ready=true;assert(x.service.Ready(&x.a[0]));x.a[0].original=false;x.service.Tick();assert(x.service.Retired(&x.a[0])&&!x.service.Ready(&x.a[0]));x.a[0].original=true;assert(!x.service.Ready(&x.a[0]));} // Native failure/capture and mode teardown never claim a usable returned asset. for(int state:{State::FAILED,State::RELINQUISHED}){Setup x;assert(x.Register()&&x.Start());x.a[0].next=state;x.service.Tick();assert(x.service.Drained()&&x.service.Retired(&x.a[0])&&!x.service.Ready(&x.a[0]));} {Setup x;assert(x.Register()&&x.Start());x.mode.active=false;x.service.Tick();assert(x.service.Stopping()&&x.service.Drained()&&x.service.Retired(&x.a[0])&®istry.values.empty());} // Expiry is owned by the original controller deadline, never renewed by Tick. {Setup x;assert(x.Register()&&x.Start());world.now=200000;x.service.Tick();assert(x.service.FlightState(&x.a[0])==State::FAILED&&x.service.Retired(&x.a[0])&&x.service.Drained()&&x.service.OrderDeadline(&x.a[0])==200000&&!x.service.Ready(&x.a[0]));} // Unclaimed/claimed/ambiguous Start failures burn the attempted token; a // nonterminal partial lease remains retained and canceled until actual result. for(int fail:{1,2,3}){Setup x;assert(x.Register());x.a[0].startMode=fail;assert(!x.Start());assert(starts==1&&x.service.AttemptedOrders()==1&&x.service.Retired(&x.a[0]));assert(!x.Start(2)&&starts==1);if(fail==3){assert(x.service.Pending(&x.a[0])&&cancels==1);assert(!x.service.Cancel(&x.a[0],1,"duplicate"));x.a[0].next=State::CANCELLED;x.service.Tick();assert(x.service.Drained());}else assert(x.service.Drained());} {Setup x;assert(x.Register());x.q.claimed=true;assert(!x.Start()&&starts==1&&claims==0&&x.service.AttemptedOrders()==1);} {Setup x;assert(x.Register());for(int i=1;i<=Service::MAX_ORDERS;i++){Qualification q;assert(x.service.StartRoute(&x.a[0],&q,i,200000));x.a[0].next=State::COMPLETE;x.service.Tick();}assert(x.service.AttemptedOrders()==128);Qualification q;assert(!x.service.StartRoute(&x.a[0],&q,129,200000)&&starts==128);} // Explicit field kind constructs one known controller, records actual target, // and shares tokens/reservations with the normal route kind. {Setup x;assert(x.Register()&&x.Register(1));FieldQualification field;assert(x.service.StartField(&x.a[0],&field,10,241000));Entry* e=x.service.Find(&x.a[0]);Flight* original=e->Flight;assert(original->kind==2&&fieldConstructions==1&&routeConstructions==0&&starts==1&&claims==1);assert(x.service.Destination(&x.a[0]).x==100);field.target.x=999;assert(x.service.Destination(&x.a[0]).x==100); Qualification normal;FieldQualification another;assert(!x.service.StartRoute(&x.a[0],&normal,11,200000));assert(!x.service.StartRoute(&x.a[1],&normal,10,200000));assert(!x.service.StartField(&x.a[1],&another,10,241000));assert(starts==1&&claims==1); assert(x.service.Cancel(&x.a[0],10,"field radio loss")&&!x.service.Cancel(&x.a[0],10,"duplicate"));assert(e->Flight==original&&x.service.Pending(&x.a[0])&&cancels==1&&x.service.OrderDeadline(&x.a[0])==241000); x.a[0].next=State::LANDING;x.service.Tick();assert(e->Flight==original&&x.service.Pending(&x.a[0]));x.a[0].next=State::CANCELLED;x.service.Tick();assert(x.service.Drained()&&!x.service.Retired(&x.a[0])); assert(!x.service.StartRoute(&x.a[0],&normal,10,200000));assert(x.service.StartRoute(&x.a[0],&normal,11,200000));assert(x.service.Find(&x.a[0])->Flight->kind==1&&routeConstructions==1&&claims==2); } // Tokens attempted by normal routes cannot replay as field routes even on // another ready asset after physical completion. {Setup x;assert(x.Register()&&x.Register(1)&&x.Start(21));x.a[0].next=State::COMPLETE;x.service.Tick();FieldQualification q;assert(!x.service.StartField(&x.a[1],&q,21,241000)&&fieldConstructions==0);assert(x.service.StartField(&x.a[1],&q,22,241000)&&claims==2);} {Setup x;assert(x.Register());FieldQualification q;assert(!x.service.StartField(&x.a[0],nullptr,1,241000));assert(!x.service.StartField(&x.a[0],&q,0,241000));assert(!x.service.StartField(&x.a[0],&q,1,NAN));assert(starts==0&&claims==0&&x.service.AttemptedOrders()==0&&fieldConstructions==0);} // Failed field admission/claim uses exactly the existing retirement and // retained partial-start protocol. Changing kind cannot create a retry. for(int fail:{1,2,3}){Setup x;assert(x.Register()&&x.Register(1));x.a[0].startMode=fail;FieldQualification q;assert(!x.service.StartField(&x.a[0],&q,31,241000));assert(x.service.Retired(&x.a[0])&&x.service.AttemptedOrders()==1&&fieldConstructions==1);Qualification route;assert(!x.service.StartRoute(&x.a[0],&route,32,200000)&&!x.service.StartRoute(&x.a[1],&route,31,200000));if(fail==3){Flight* retained=x.service.Find(&x.a[0])->Flight;assert(x.service.Pending(&x.a[0])&&cancels==1);x.a[0].next=State::LANDING;x.service.Tick();assert(x.service.Find(&x.a[0])->Flight==retained&&x.service.Pending(&x.a[0]));x.a[0].next=State::CANCELLED;x.service.Tick();}assert(x.service.Drained()&&x.service.Retired(&x.a[0]));} {Setup x;assert(x.Register());FieldQualification q;q.claimed=true;assert(!x.service.StartField(&x.a[0],&q,41,241000)&&starts==1&&claims==0&&x.service.Retired(&x.a[0]));} // Stop drains both kinds together; no early release or additional starts. {Setup x;assert(x.Register()&&x.Register(1)&&x.Start(51));FieldQualification q;assert(x.service.StartField(&x.a[1],&q,52,241000));Flight* field=x.service.Find(&x.a[1])->Flight;x.service.Stop();x.service.Stop();assert(cancels==2&&x.service.Stopping()&&!x.service.Drained());x.a[0].next=State::CANCELLED;x.a[1].next=State::LANDING;x.service.Tick();assert(!x.service.Drained()&®istry.Get(&x.a[0])==&x.service&&x.service.Find(&x.a[1])->Flight==field);x.a[1].next=State::CANCELLED;x.service.Tick();assert(x.service.Drained()&®istry.values.empty()&&!x.service.Ready(&x.a[1]));} // One bounded attempt budget covers both kinds without independent counters. {Setup x;assert(x.Register());for(int i=1;i<=Service::MAX_ORDERS;i++){if(i%2){FieldQualification q;assert(x.service.StartField(&x.a[0],&q,i,241000));}else{Qualification q;assert(x.service.StartRoute(&x.a[0],&q,i,200000));}x.a[0].next=State::COMPLETE;x.service.Tick();}FieldQualification q;assert(!x.service.StartField(&x.a[0],&q,129,241000)&&starts==128&&claims==128&&routeConstructions==64&&fieldConstructions==64);} } ''') source=P.read_text() # Native-boundary inventory: readiness invokes original occupancy/player/world # checks plus actual fuel, rotor, engine and settled ground predicates. original=body(P,'protected bool Original(');ready=body(P,'protected bool PhysicalReady(') for required in ('entry.Seat.GetOccupant() != entry.Pilot','controller.GetPilotCompartmentSlot() != entry.Seat','CompartmentAccessComponent.GetVehicleIn(entry.Pilot) != entry.Aircraft','entry.Group.GetPlayerCount(true) > 0','GetPlayerControlledEntity(id)','entry.Aircraft.GetWorld() != m_World','entry.Pilot.GetWorld() != m_World'): assert required in original for required in ('!Original(entry)','!ERR_Actors.CanFight(entry.Pilot)','!fuel.HasFuel()','!damage.GetEngineFunctional()','simulation.RotorGetState(rotor) == RotorState.DESTROYED','!simulation.HasAnyGroundContact()','!physics.IsActive()','controller.IsEngineOn()'): assert required in ready assert source.count('new ERR_AircraftRouteFlight()')==1 and source.count('new ERR_AircraftFieldFlight()')==1 assert 'ref ERR_AircraftFlight Flight;' in source assert source.count('m_UsedTokens.Insert(token)')==1 for signature in ('bool StartRoute(', 'bool StartField('): method=body(P,signature) assert method.index('if (!qualification) return false;')(entry->Flight)').replace('ERR_AircraftRouteFlight ','Route* ').replace('ERR_AircraftServiceEntry entry','Entry* entry').replace('Vehicle aircraft','int aircraft').replace('null','nullptr') run(r'''#include struct Base {virtual ~Base()=default;};struct Route:Base{};struct Field:Base{}; struct Entry {Base* Flight=nullptr;}; struct Observer {Entry* entry=nullptr;Entry* Find(int){return entry;} '''+getter+r''' }; int main(){Observer o;assert(!o.ERR_NativeOriginalFlight(1));Entry e;o.entry=&e;assert(!o.ERR_NativeOriginalFlight(1));Route route;e.Flight=&route;assert(o.ERR_NativeOriginalFlight(1)==&route);Field field;e.Flight=&field;assert(!o.ERR_NativeOriginalFlight(1));} ''') print('PASS: actual WORKBENCH route observer returns exact retained route subtype and refuses absent/field controllers')