from pathlib import Path from policy_harness import body,run ROOT=Path(__file__).resolve().parents[1] import re production=(ROOT/'addons/core/Scripts/Game/ERR/10_AI/ERR_MortarSalvo.c').read_text() constants='\n'.join(re.findall(r'static const (?:int|float) [^;]+;',production)).replace('static const','constexpr') s=body(ROOT/'addons/core/Scripts/Game/ERR/10_AI/ERR_MortarSalvo.c','static vector Offset(').replace('Math.','Math::') run('''#include #include struct vector { float x,y,z;}; vector Vector(float x,float y,float z){return {x,y,z};} namespace Math {constexpr float DEG2RAD=0.01745329252;float Sqrt(float n){return std::sqrt(n);}float Sin(float n){return std::sin(n);}float Cos(float n){return std::cos(n);}} '''+constants+s+''' int main(){assert(ROUNDS>=8&&RADIUS_METRES>=80);for(int site=0;site<4;site++)for(int order=0;order<10;order++){ float previous=0; for(int shot=0;shot<8;shot++){ auto a=Offset(site,order,shot),b=Offset(site,order,shot); assert(a.x==b.x&&a.z==b.z&&a.y==0); float radius=std::hypot(a.x,a.z);assert(radius>previous&&radius<=80.0001);previous=radius; } }} ''') print('PASS: migrated salvo offsets are deterministic, spread and bounded (native firing and complete salvo qualification are separate)')