Capture current mission, AI, map and administration development

Include the current addon, terrain integrations, tools, regression tests and recorded development evidence.
This commit is contained in:
2026-10-13 22:52:53 +02:00
parent a951a96edc
commit 6a667d8deb
8104 changed files with 2124945 additions and 2061 deletions
+62 -4
View File
@@ -1,12 +1,19 @@
"""Execute actual delivered-belief pursuit rules as C++; no engine/AI behavior claim."""
import re
import os, re
from pathlib import Path
from policy_harness import ROOT, body, run
P = ROOT/'addons/core/Scripts/Game/ERR/10_AI/ERR_HQPursuit.c'
P = Path(os.environ.get('ERR_HQ_PURSUIT_SOURCE',ROOT/'addons/core/Scripts/Game/ERR/10_AI/ERR_HQPursuit.c'))
source = P.read_text()
# Exercise the real planner expression against the same actual policy methods.
HQ = Path(os.environ.get('ERR_HQ_SOURCE', ROOT/'addons/core/Scripts/Game/ERR/10_AI/ERR_HQ.c'))
assignment = body(HQ, 'protected void Assign(')
selection = re.search(r'ERR_HQPursuitRole role = (ERR_HQPursuitRules\.Role\([^;]+\));', assignment)
assert selection, 'missing actual Assign role selection'
planner_role = selection.group(1).replace('ERR_HQPursuitRules.', 'Rules::')
methods = '\n'.join(body(P, signature) for signature in (
'static bool Finite(', 'static bool PositionValid(', 'static int Limit(', 'static bool Actionable(',
'static bool Heading(', 'static ERR_HQPursuitRole Role(', 'static float LifetimeSeconds(',
'static float TaskLifetimeSeconds(', 'static bool CanCommit(', 'static int Bearing(', 'static bool BearingAllowed(', 'static vector Direction(',
'static float SearchRadius(', 'static float TaskLifetimeSeconds(', 'static bool CanCommit(', 'static int Bearing(', 'static bool BearingAllowed(', 'static vector Direction(',
'static vector Objective(', 'static float Score(', 'static bool Better('))
methods = methods.replace('Math.', 'Math::').replace('vector.', 'vector::')
methods = methods.replace('ERR_HQPursuitRole.', 'ERR_HQPursuitRole::')
@@ -44,8 +51,14 @@ vector Vector(float a,float b,float c){return {a,b,c};}
struct Rules {
'''+methods+r'''
};
struct Belief { float Confidence=.9f, Radius=50; vector Velocity; bool HasVelocity=true; };
ERR_HQPursuitRole PlannerRole(Belief belief,float age,int slot){return '''+planner_role+r''';}
bool near(float a,float b){return std::abs(a-b)<0.001f;}
int main(){
assert(Rules::SearchRadius(0)==45&&Rules::SearchRadius(44.99)==45&&Rules::SearchRadius(45)==45);
assert(Rules::SearchRadius(73)==73&&Rules::SearchRadius(110)==110&&Rules::SearchRadius(2000)==110);
assert(Rules::SearchRadius(-1)==0&&Rules::SearchRadius(std::numeric_limits<float>::quiet_NaN())==0&&Rules::SearchRadius(std::numeric_limits<float>::infinity())==0);
using Role=ERR_HQPursuitRole;
assert(Rules::Limit(-1)==0&&Rules::Limit(0)==0&&Rules::Limit(1)==1);
assert(Rules::Limit(3)==3&&Rules::Limit(8)==3);
@@ -64,6 +77,23 @@ int main(){
assert(Rules::Role(.9,10,50,true,0)==Role::INTERCEPT);
assert(Rules::Role(.9,10,50,true,1)==Role::SEARCH);
assert(Rules::Role(.9,10,50,true,2)==Role::CONTAIN);
// Memory can retain a valid slow-motion sample below the directed-task threshold.
// The actual Assign expression must not queue containment that delivery rejects.
Belief belief;
for(float speed:{0.f,.49f,70.01f})for(int slot=0;slot<3;slot++){
belief.Velocity={0,0,speed};
assert(PlannerRole(belief,10,slot)==Role::SEARCH);
}
for(float speed:{.5f,70.f}){
belief.Velocity={0,0,speed};
assert(PlannerRole(belief,10,0)==Role::INTERCEPT);
assert(PlannerRole(belief,10,1)==Role::SEARCH);
assert(PlannerRole(belief,10,2)==Role::CONTAIN);
}
belief.Velocity={nan,0,5};
assert(PlannerRole(belief,10,2)==Role::SEARCH);
belief.Velocity=north;belief.HasVelocity=false;
assert(PlannerRole(belief,10,0)==Role::SEARCH&&PlannerRole(belief,10,2)==Role::SEARCH);
for(int slot=0;slot<3;slot++){
assert(Rules::Role(.64,10,50,true,slot)==Role::SEARCH);
assert(Rules::Role(.9,46,50,true,slot)==Role::SEARCH);
@@ -79,7 +109,11 @@ int main(){
assert(Rules::TaskLifetimeSeconds(Role::SEARCH,0)==120);
assert(near(Rules::TaskLifetimeSeconds(Role::SEARCH,2000),2000.f/3+45));
assert(Rules::TaskLifetimeSeconds(Role::SEARCH,5000)==900);
assert(Rules::TaskLifetimeSeconds(Role::INTERCEPT,2000)==60);
assert(Rules::TaskLifetimeSeconds(Role::INTERCEPT,0)==180);
assert(near(Rules::TaskLifetimeSeconds(Role::INTERCEPT,2000),2000.f/3+180));
assert(Rules::TaskLifetimeSeconds(Role::INTERCEPT,5000)==900);
assert(Rules::TaskLifetimeSeconds(Role::INTERCEPT,-1)==0);
assert(Rules::TaskLifetimeSeconds(Role::INTERCEPT,nan)==0);
assert(Rules::TaskLifetimeSeconds(Role::CONTAIN,2000)==90);
assert(Rules::TaskLifetimeSeconds(Role::SEARCH,-1)==0);
assert(Rules::TaskLifetimeSeconds(Role::SEARCH,nan)==0);
@@ -160,3 +194,27 @@ for forbidden in ('GetGame(', 'GetOrigin(', 'GetPlayers(', 'GetControlledEntity(
assert forbidden not in source, f'pursuit must consume snapshots only: {forbidden}'
assert all(len(line)<120 for line in source.splitlines())
print('PASS: actual bounded pursuit roles/objectives/scores, stale search degradation, physical/busy/home guards, finite lifetime and two-bearing escape gap; no hidden player reads or spawning')
for signature in ('protected void Assign(', 'protected void Retask('):
section=body(HQ,signature)
line=next(line.strip() for line in section.splitlines() if 'task.SearchRadiusMetres =' in line)
line=line.replace('ERR_HQPursuitRules.', 'Rules::').replace('ERR_HQPursuitRole.', 'Role::')
run(r"""
#include <cassert>
#include <algorithm>
#include <cmath>
#include <limits>
enum class Role {SEARCH,INTERCEPT,CONTAIN};
struct Math{static float Clamp(float n,float a,float b){return std::clamp(n,a,b);}};
struct Rules{
"""+body(P,'static bool Finite(')+body(P,'static float SearchRadius(').replace('Math.','Math::')+r"""
};
struct Task{float SearchRadiusMetres=0;};struct Belief{float Radius=0;};
void Queue(Task& task,Belief& belief,Role role,bool roadIntercept){
"""+line+r"""
}
int main(){for(float radius:{0.f,60.f,500.f}){Task task;Belief belief{radius};Queue(task,belief,Role::SEARCH,false);float copied=Rules::SearchRadius(radius);assert(task.SearchRadiusMetres==copied);belief.Radius=1900;assert(task.SearchRadiusMetres==copied);}
"""+(r"""for(Role role:{Role::INTERCEPT,Role::CONTAIN}){Task task;Belief belief{100};Queue(task,belief,role,false);assert(task.SearchRadiusMetres==0);}Task road;Belief belief{100};Queue(road,belief,Role::SEARCH,true);assert(road.SearchRadiusMetres==0);""" if 'Assign' in signature else '')+r"""
}
""")
print('PASS: actual finite45..110 radius and both ordinary search queue snapshot expressions')