"""Execute actual footprint sampling and native query callback policy with API doubles.""" import re,os from policy_harness import ROOT,body,run from pathlib import Path p=Path(os.environ.get('ERR_CONVOY_PLACEMENT_SOURCE',ROOT/'addons/core/Scripts/Game/ERR/10_AI/ERR_ConvoyPlacement.c')) code='\n'.join(body(p,s) for s in ('protected bool Occupancy(', 'static bool Terrain(', 'bool Clear(', 'bool ClearFootprint(')) code=code.replace('null','nullptr').replace('protected ','').replace('IEntity entity','IEntity* entity').replace('entity.GetVObject()', 'entity->GetVObject()') code=code.replace('ERR_InterceptVehicleFootprint footprint','ERR_InterceptVehicleFootprint* footprint').replace('footprint.','footprint->') code=code.replace('TraceBox volume', 'TraceBox* volume').replace('volume.', 'volume->').replace('\"0 0.01 0\"', 'Vector(0,.01,0)') for cls in ('Math','ERR_ForceRules','ERR_Actors','ChimeraWorldUtils','TraceFlags'):code=code.replace(cls+'.',cls+'::') code=code.replace('GetGame().GetWorld().','GetGame()->GetWorld()->').replace('GetGame().GetWorld()', 'GetGame()->GetWorld()') code=code.replace('GetGame().', 'GetGame()->') code=code.replace('low, high, Occupancy','low, high, [this](IEntity* entity){return Occupancy(entity);}') run(r''' #include #include #include #include #include struct vector{float x=0,y=0,z=0;float& operator[](int i){return i==0?x:i==1?y:z;}vector operator+(vector b)const{return{x+b.x,y+b.y,z+b.z};}vector operator-(vector b)const{return{x-b.x,y-b.y,z-b.z};}vector operator*(float n)const{return{x*n,y*n,z*n};}}; vector Vector(float x,float y,float z){return{x,y,z};} namespace Math{float Ceil(float n){return std::ceil(n);}float DEG2RAD=3.141592653589793/180;float Sin(float n){return std::sin(n);}float Cos(float n){return std::cos(n);}float Min(float a,float b){return std::min(a,b);}float Max(float a,float b){return std::max(a,b);}} namespace ERR_ForceRules{bool Finite(float n){return std::isfinite(n);}bool FiniteVector(vector v){return Finite(v.x)&&Finite(v.y)&&Finite(v.z);}} struct ERR_InterceptVehicleFootprint{bool valid=true;float radius=4,height=5;bool Valid(){return valid;}float Radius(){return radius;}float Height(){return height;}}; struct IEntity{bool visible=false;bool GetVObject(){return visible;}}; struct TraceBox {vector Start,End,Mins,Maxs;int Flags=0;IEntity* TraceEnt=nullptr;}; namespace TraceFlags{constexpr int ENTS=1,OCEAN=2,WORLD=4;} struct World{int traces=0;float fraction=1;IEntity* hit=nullptr;TraceBox last;float TraceMove(TraceBox* volume,void*){traces++;last=*volume;volume->TraceEnt=hit;return fraction;}int queries=0,visits=0;vector low,high;std::vector entities;templatevoid QueryEntitiesByAABB(vector a,vector b,C callback){queries++;low=a;high=b;for(auto e:entities){visits++;if(!callback(e))break;}}}; struct Game{World world;World* GetWorld(){return &world;}}game;bool gameAvailable=true;Game* GetGame(){return gameAvailable?&game:nullptr;} namespace ERR_Actors{int grounds=0;float elevation=10,slope=0;bool invalid=false;vector Ground(vector v){grounds++;v.y=invalid?NAN:elevation+slope*v.x;return v;}} namespace ChimeraWorldUtils{int waters=0;bool water=false;bool TryGetWaterSurfaceSimple(World*,vector){waters++;return water;}} struct Placement{float m_LastTrace=-1;std::string m_LastReason;float m_LastLowest=0,m_LastHighest=0;IEntity* m_FirstObstruction=nullptr;bool m_Obstructed=false;int m_Visited=0;'''+code+r'''}; void reset(){game.world=World();ERR_Actors::grounds=0;ERR_Actors::elevation=10;ERR_Actors::slope=0;ERR_Actors::invalid=false;ChimeraWorldUtils::waters=0;ChimeraWorldUtils::water=false;} bool near(float a,float b){return std::abs(a-b)<.001;} int main(){ Placement p;reset();assert(p.Clear({0,10,0},0));assert(ERR_Actors::grounds==9&&ChimeraWorldUtils::waters==9&&game.world.queries==1); assert(near(game.world.low.x,-2)&&near(game.world.high.x,2)&&near(game.world.low.z,-4.5)&&near(game.world.high.z,4.5));assert(near(game.world.low.y,10.05)&&near(game.world.high.y,13.5)); assert(game.world.traces==1&&game.world.last.Flags==(TraceFlags::ENTS|TraceFlags::OCEAN)); assert(near(game.world.last.Start.y+game.world.last.Mins.y,10.05)&&near(game.world.last.Start.y+game.world.last.Maxs.y,13.5)); assert(near(game.world.last.Mins.x,-2)&&near(game.world.last.Maxs.x,2)&&near(game.world.last.Mins.z,-4.5)&&near(game.world.last.Maxs.z,4.5)); assert(game.world.last.End.y>game.world.last.Start.y&&near(game.world.last.End.y-game.world.last.Start.y,.01)); reset();assert(p.Clear({0,10,0},90));assert(near(game.world.low.x,-4.5)&&near(game.world.high.x,4.5)&&near(game.world.low.z,-2)&&near(game.world.high.z,2)); reset();assert(!p.Clear({NAN,10,0},0)&&game.world.queries==0&&ERR_Actors::grounds==0);assert(!p.Clear({0,10,0},NAN)); reset();ERR_Actors::slope=.2;assert(!p.Clear({0,10,0},0)&&game.world.queries==0); // 0.8m cross-footprint rise. reset();ERR_Actors::slope=.2;assert(p.Clear({0,10,0},0,2.5)); // already physical driver may stage on this gentle slope reset();ERR_Actors::slope=.7;assert(!p.Clear({0,10,0},0,2.5)); // 2.8 m relief still rejected reset();assert(!p.Clear({0,10,0},0,NAN));assert(!p.Clear({0,10,0},0,3)); reset();ChimeraWorldUtils::water=true;assert(!p.Clear({0,10,0},0,2.5)); reset();game.world.fraction=0;assert(!p.Clear({0,10,0},0,2.5)); reset();ERR_Actors::elevation=.29;assert(!p.Clear({0,.29,0},0)&&game.world.queries==0); reset();assert(!p.Clear({0,10.31,0},0)&&game.world.queries==0); reset();ChimeraWorldUtils::water=true;assert(!p.Clear({0,10,0},0)&&game.world.queries==0&&ERR_Actors::grounds==1); reset();ERR_Actors::invalid=true;assert(!p.Clear({0,10,0},0)&&game.world.queries==0); IEntity abstract,obstacle;obstacle.visible=true; reset();game.world.entities={&abstract,&obstacle,&abstract};assert(p.Clear({0,10,0},0)&&game.world.visits==2&&!p.m_Obstructed&&!p.m_FirstObstruction&&p.m_LastReason=="clear"); // Broad tree/cable bounds overlap, but their actual low geometry does not: accept. assert(game.world.traces==1&&p.m_LastTrace==1); // Actual geometry refuses even when the broad diagnostic callback found only abstract entities. reset();game.world.entities={&abstract};game.world.fraction=.4;game.world.hit=&obstacle; assert(!p.Clear({0,10,0},0)&&p.m_Obstructed&&p.m_FirstObstruction==&obstacle&&p.m_LastReason=="native filled volume collision"); for(float fraction:{0.f,.999f,NAN,INFINITY}){reset();game.world.fraction=fraction;assert(!p.Clear({0,10,0},0));} // New query resets previous obstruction. Abstract logic entities do not block. reset();game.world.entities={nullptr,&abstract};assert(p.Clear({0,10,0},0)&&game.world.visits==2&&!p.m_Obstructed&&!p.m_FirstObstruction&&p.m_LastReason=="clear"); reset();game.world.entities.assign(128,&abstract);assert(p.Clear({0,10,0},0)&&game.world.visits==128); reset();game.world.entities.assign(130,&abstract);assert(p.Clear({0,10,0},0)&&game.world.visits==129&&game.world.traces==1&&p.m_LastReason=="clear"); assert(Placement::Terrain(10,9.7,10.4));assert(!Placement::Terrain(10,9.7,10.451));assert(!Placement::Terrain(10,10.1,10));assert(!Placement::Terrain(10,NAN,10)); // Execute new measured square while all legacy Clear assertions above remain. ERR_InterceptVehicleFootprint footprint;reset();gameAvailable=false;assert(!p.ClearFootprint({0,10,0},0,&footprint));gameAvailable=true;assert(p.ClearFootprint({0,10,0},0,&footprint)); assert(ERR_Actors::grounds==25&&ChimeraWorldUtils::waters==25&&game.world.traces==1); assert(near(game.world.low.x,-4)&&near(game.world.high.x,4)&&near(game.world.low.z,-4)&&near(game.world.high.z,4)); assert(near(game.world.low.y,10.05)&&near(game.world.high.y,15)); reset();assert(p.ClearFootprint({0,10,0},45,&footprint));assert(near(game.world.high.x,4*std::sqrt(2.f))&&near(game.world.high.z,4*std::sqrt(2.f))); reset();footprint.radius=19.5;footprint.height=14;assert(p.ClearFootprint({0,10,0},0,&footprint));assert(ERR_Actors::grounds==441&&near(game.world.high.y,24)); reset();footprint.radius=4;footprint.height=5;footprint.valid=false;assert(!p.ClearFootprint({0,10,0},0,&footprint)&&ERR_Actors::grounds==0);footprint.valid=true;assert(!p.ClearFootprint({0,10,0},0,nullptr)); reset();ChimeraWorldUtils::water=true;assert(!p.ClearFootprint({0,10,0},0,&footprint)&&game.world.traces==0); reset();ERR_Actors::invalid=true;assert(!p.ClearFootprint({0,10,0},0,&footprint)&&game.world.traces==0); reset();ERR_Actors::slope=.1;assert(!p.ClearFootprint({0,10,0},0,&footprint)&&game.world.traces==0); for(float fraction:{0.f,.99f,NAN,INFINITY}){reset();game.world.fraction=fraction;assert(!p.ClearFootprint({0,10,0},0,&footprint));} } ''') print('PASS: actual new measured ClearFootprint 25/441 sample grids, measured extents/height, water/invalid world/terrain/trace refusal plus legacy filled rotated-footprint TraceBox and nine terrain/water samples; broad tree/cable bounds alone accepted, actual collision/nonfinite trace refused, nonzero sweep and ENTS/OCEAN flags, bounded diagnostic query and reset')