Files
EscapistsReintroduced/tests/test_intel_body_inspection.py
T
jakub 1b1a8b5173 Add mission customization, HQ support and aggression-driven AI
Integrate faction and random settings menus, generated objectives, scouts, convoys, air support, mortar stations and body-intel recovery. Add identified-body aggression, finite hunter UAZ deployment, dedicated objective defence and maximum AI skill with separate reduced aim accuracy. Include policy tests, native probes, evidence and documentation.
2026-09-23 15:07:14 +02:00

89 lines
7.1 KiB
Python

"""Execute the production physical body-inspection gate; engine traces are boundary doubles."""
from policy_harness import ROOT, body, run
import re
p=ROOT/'addons/core/Scripts/Game/ERR/20_Intel/ERR_IntelEvidence.c'
s='\n'.join(body(p,sig) for sig in ('bool Inspect(', 'bool RetainedWithin(', 'void Delivered(', 'void Release('))
for old,new in [('out array<string> missing','Array<string>& missing'),('array<IEntity>','Array<IEntity>'),('array<string>','Array<string>'),('foreach (','for ('),('ERR_BodyEvidence record','ERR_BodyEvidence* record'),('ERR_IssuedIntel issued','ERR_IssuedIntel* issued'),('TraceParam trace','TraceParam* trace'),('InventoryStorageManagerComponent inventory','InventoryStorageManagerComponent* inventory'),('SCR_GarbageSystem garbage','SCR_GarbageSystem* garbage'),('null','nullptr')]:s=s.replace(old,new)
s=s.replace('InventoryStorageManagerComponent.Cast(body.FindComponent(InventoryStorageManagerComponent))','body->inventory')
for cls in ('Replication','ERR_GameMode','ERR_Actors','CompartmentAccessComponent','vector','TraceFlags','ERR_DiscoveryService','SCR_GarbageSystem'):
s=s.replace(cls+'.',cls+'::')
s=s.replace('parent.GetParent()', 'parent->GetParent()')
for v in ('body','observer','record','issued','trace','garbage'):
s=s.replace(v+'.',v+'->')
s=s.replace('ERR_GameMode::Get().','ERR_GameMode::Get()->').replace('GetGame().GetWorld().','GetGame()->GetWorld()->')
run(r'''
#include <cassert>
#include <string>
#include <vector>
#include <algorithm>
#include <cmath>
using string=std::string;
template<class T>struct Array:std::vector<T>{using std::vector<T>::vector;void Clear(){this->clear();}bool Contains(T t){return std::find(this->begin(),this->end(),t)!=this->end();}void Insert(T t){this->push_back(t);}};
struct vector {float x=0,y=0,z=0;vector()=default;vector(float a,float b,float c):x(a),y(b),z(c){}vector(const char*){}vector operator+(vector v){return {x+v.x,y+v.y,z+v.z};}static float Distance(vector a,vector b){return std::hypot(std::hypot(a.x-b.x,a.y-b.y),a.z-b.z);}};
struct Entity;using IEntity=Entity*;
struct InventoryStorageManagerComponent{Array<IEntity> folders;};
struct Entity{IEntity parent=nullptr;IEntity GetParent(){return parent;}bool alive=true,fit=true,player=false,seated=false;InventoryStorageManagerComponent* inventory=nullptr;vector position;vector GetOrigin(){return position;}};
struct ERR_Actors{static bool Alive(IEntity e){return e&&e->alive;}static bool CanFight(IEntity e){return e&&e->alive&&e->fit;}static bool Player(IEntity e){return e&&e->player;}};
struct CompartmentAccessComponent{static bool GetVehicleIn(IEntity e){return e->seated;}};
struct TraceFlags{enum{ENTS=1,WORLD=2};};struct TraceParam{vector Start,End;IEntity Exclude=nullptr,TraceEnt=nullptr;int Flags=0;};
struct World{float fraction=1;IEntity hit=nullptr;float TraceMove(TraceParam* t,void*){t->TraceEnt=hit;return fraction;}};
struct Game{World world;World* GetWorld(){return &world;}} game;Game* GetGame(){return &game;}
struct Replication{inline static bool server=true;static bool IsServer(){return server;}};
struct ERR_GameMode{bool active=true;static ERR_GameMode* Get(){static ERR_GameMode mode;return &mode;}bool Active(){return active;}};
struct ERR_DiscoveryService{static void Folders(InventoryStorageManagerComponent* inv,Array<IEntity>& folders){folders=inv->folders;}};
struct ERR_IssuedIntel{IEntity Folder;string SiteId;};
struct ERR_BodyEvidence{IEntity Actor;Array<ERR_IssuedIntel*> Issued;bool Searched=false;bool Reported=false;};
struct SCR_GarbageSystem {
inline static int releases=0,inserts=0;inline static bool blacklisted=true;inline static float delay=0;
static SCR_GarbageSystem* GetByEntityWorld(IEntity){static SCR_GarbageSystem g;return &g;}
void UpdateBlacklist(IEntity,bool value){blacklisted=value;releases++;}
void Insert(IEntity,float value){assert(!blacklisted);inserts++;delay=value;}
};
struct Evidence{Array<ERR_BodyEvidence*> m_Roster;bool m_Stopped=false;ERR_BodyEvidence* record=nullptr;ERR_BodyEvidence* Find(IEntity b){return record&&record->Actor==b?record:nullptr;}
'''+s+r'''
};
int main(){
for(int invalid=0;invalid<9;invalid++){
Entity body,observer,folder;body.alive=false;InventoryStorageManagerComponent inventory;body.inventory=&inventory;
ERR_IssuedIntel issued{&folder,"radio-1"};ERR_BodyEvidence record{&body,{&issued},false};Evidence service;service.record=&record;Array<string> result;
game.world.fraction=1;Replication::server=true;ERR_GameMode::Get()->active=true;
if(invalid==0)Replication::server=false;
if(invalid==1)service.m_Stopped=true;
if(invalid==2)body.alive=true;
if(invalid==3)observer.player=true;
if(invalid==4)observer.fit=false;
if(invalid==5)observer.seated=true;
if(invalid==6)observer.position={3.01f,0,0};
if(invalid==7)game.world.fraction=.5;
if(invalid==8)body.inventory=nullptr;
assert(!service.Inspect(&body,&observer,result)&&!record.Searched&&result.empty());
}
Replication::server=true;game.world.fraction=1;
Entity body,observer,present,missing;body.alive=false;InventoryStorageManagerComponent inv;body.inventory=&inv;inv.folders.Insert(&present);
ERR_IssuedIntel a{&present,"radio-1"},b{&missing,"mortar-3"},c{nullptr,"depot-1"};ERR_BodyEvidence record{&body,{&a,&b,&c},false};Evidence service;service.record=&record;Array<string> result;
observer.position={3,0,0};assert(service.Inspect(&body,&observer,result));assert(result.size()==2&&result.Contains("mortar-3")&&result.Contains("depot-1")&&!result.Contains("radio-1"));
assert(!service.Inspect(&body,&observer,result));
Entity wreck,seat,unrelated;body.parent=&seat;seat.parent=&wreck;service.m_Roster={&record};
assert(service.RetainedWithin(&body)&&service.RetainedWithin(&seat)&&service.RetainedWithin(&wreck));
assert(!service.RetainedWithin(&unrelated)&&!service.RetainedWithin(nullptr));
body.alive=true;assert(!service.RetainedWithin(&wreck));body.alive=false;
record.Reported=true;assert(!service.RetainedWithin(&wreck));record.Reported=false;
service.m_Stopped=true;assert(!service.RetainedWithin(&wreck));service.m_Stopped=false;
// Searching protects the body until HQ receives the report. Premature,
// client-side, stopped and repeated deliveries never release/renew cleanup.
record.Searched=false;service.Delivered(&body);assert(!record.Reported&&SCR_GarbageSystem::inserts==0);
record.Searched=true;Replication::server=false;service.Delivered(&body);assert(!record.Reported);
Replication::server=true;service.m_Stopped=true;service.Delivered(&body);assert(!record.Reported);
service.m_Stopped=false;service.Delivered(&unrelated);assert(!record.Reported);
assert(service.RetainedWithin(&body));service.Delivered(&body);
assert(record.Reported&&!service.RetainedWithin(&body));
assert(SCR_GarbageSystem::inserts==1&&SCR_GarbageSystem::releases==1&&SCR_GarbageSystem::delay==300);
service.Delivered(&body);assert(SCR_GarbageSystem::inserts==1&&SCR_GarbageSystem::releases==1);
record.Reported=false;
// Corrupt/cyclic parent links cannot cause unbounded cleanup traversal.
seat.parent=&seat;assert(!service.RetainedWithin(&wreck));
}
''')
print('PASS: physical inspection and parent-wreck retention; server-only searched/report delivery unlocks native cleanup once with a 300-second delay')