Files
jakub 6a667d8deb Capture current mission, AI, map and administration development
Include the current addon, terrain integrations, tools, regression tests and recorded development evidence.
2026-10-13 22:52:53 +02:00

54 lines
3.4 KiB
Python

"""Execute the actual objective-inference rules; audit the HQ ingestion boundaries."""
from policy_harness import ROOT, body, run
P=ROOT/'addons/core/Scripts/Game/ERR/10_AI/ERR_HQDoctrine.c'
methods='\n'.join(body(P,x) for x in ('static float Threat(', 'static bool Forward(', 'static vector Approach('))
methods=methods.replace('Math.','Math::').replace('vector.','vector::').replace('ERR_HQPursuitRules.','ERR_HQPursuitRules::').replace('float alignment;', 'float alignment=0;')
run(r'''
#include <cassert>
#include <cmath>
#include <algorithm>
struct vector {float x=0,y=0,z=0; vector()=default;vector(float a,float b,float c):x(a),y(b),z(c){}
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};}
float Length()const{return std::sqrt(x*x+y*y+z*z);}
vector Normalized()const{return *this*(1/Length());}
static float Dot(vector a,vector b){return a.x*b.x+a.y*b.y+a.z*b.z;}};
struct Math {static float Max(float a,float b){return std::max(a,b);}static float Clamp(float n,float a,float b){return std::clamp(n,a,b);}};
struct ERR_HQPursuitRules {
static bool Finite(float v){return std::isfinite(v);}
static bool PositionValid(vector v){return Finite(v.x)&&Finite(v.y)&&Finite(v.z);}
static bool Heading(vector v,bool known){return known&&PositionValid(v)&&v.Length()>=.5&&v.Length()<=70;}
static vector Direction(vector v,bool){v.y=0;return v.Normalized();}
};
struct Doctrine {'''+methods+r'''};
int main(){
vector origin{1000,0,1000},north{1000,0,3000},south{1000,0,0},velocity{0,0,4};
assert(Doctrine::Forward(north,origin,velocity,true));
assert(!Doctrine::Forward(south,origin,velocity,true));
assert(!Doctrine::Forward(north,origin,velocity,false));
assert(!Doctrine::Forward({1000,0,1100},origin,velocity,true));
assert(Doctrine::Threat(north,origin,velocity,true,1,50)>Doctrine::Threat(south,origin,velocity,true,1,50));
assert(std::abs(Doctrine::Threat(north,origin,velocity,false,0,50)-.2)<.0001);
assert(Doctrine::Threat(north,origin,velocity,true,.3,500)<Doctrine::Threat(north,origin,velocity,true,1,500));
auto ahead=Doctrine::Approach(north,origin);assert(std::abs(ahead.z-1200)<.001&&ahead.x==1000);
auto close=Doctrine::Approach({1000,0,1300},origin);assert(std::abs(close.z-1100)<.001);
auto same=Doctrine::Approach(origin,origin);assert(same.x==origin.x&&same.z==origin.z);
}
''')
hq=ROOT/'addons/core/Scripts/Game/ERR/10_AI/ERR_HQ.c'
a=body(hq,'protected void Accept(')
assert 'm_Memory.Ingest(report, now)' in a and 'm_Coverage.Forget(report.Position, report.ObservedAt)' in a
sweep=body(hq,'protected void AcceptSweep(')
assert sweep.index('belief.BeliefRevision != report.BeliefRevision')<sweep.index('m_Coverage.Ingest')
observe=body(hq,'protected void Observe(')
assert 'm_Memory.' not in observe and 'Accept(' not in observe
assert 'GetPlayer' not in P.read_text() and 'GetOrigin' not in P.read_text()
delivery=body(hq,'protected void DeliverOrder(')
assert delivery.index('if (!waypoint)')<delivery.index('unit.Release();')
assert 'LostOrder(unit, now)' in delivery
unit=body(hq,'void CancelPending(')
assert 'Waypoint' not in unit and 'Assignment' not in unit
print('PASS: actual objective heading/threat/approach rules, persistent doctrine weight, fresh-contact coverage invalidation, stale-sweep rejection and atomic radio retask ownership')