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:
@@ -1,6 +1,8 @@
|
||||
"""Actual bounded negative-search coverage rules; physical radio delivery is HQ's boundary."""
|
||||
from policy_harness import ROOT, body, run
|
||||
P=ROOT/'addons/core/Scripts/Game/ERR/10_AI/ERR_HQCoverage.c'
|
||||
from pathlib import Path
|
||||
import os
|
||||
P=Path(os.environ.get('ERR_HQ_COVERAGE_SOURCE', ROOT/'addons/core/Scripts/Game/ERR/10_AI/ERR_HQCoverage.c'))
|
||||
PURSUIT=ROOT/'addons/core/Scripts/Game/ERR/10_AI/ERR_HQPursuit.c'
|
||||
|
||||
def cpp(s):
|
||||
@@ -11,6 +13,7 @@ def cpp(s):
|
||||
.replace('reserved.Count()', 'reserved->Count()').replace('= null', '= nullptr')
|
||||
.replace('foreach (vector position : reserved)', 'for (vector position : *reserved)')
|
||||
.replace('foreach (int known, float searched : m_Cells)', 'for (auto [known, searched] : m_Cells)')
|
||||
.replace('foreach (int known, float seen : m_Positive)', 'for (auto [known, seen] : m_Positive)')
|
||||
.replace('int oldestKey;', 'int oldestKey=0;').replace('bool found;', 'bool found=false;'))
|
||||
common='\n'.join(cpp(body(PURSUIT,s)) for s in ('static bool Finite(', 'static bool PositionValid('))
|
||||
rules='\n'.join(cpp(body(P,s)) for s in ('static bool PositionValid(', 'static int Cell(', 'static int Key(',
|
||||
@@ -34,6 +37,7 @@ vector Vector(float x,float y,float z){return {x,y,z};}
|
||||
struct Math{
|
||||
static float Clamp(float n,float lo,float hi){return std::clamp(n,lo,hi);}
|
||||
static float Floor(float n){return std::floor(n);}
|
||||
static float Max(float a,float b){return std::max(a,b);}
|
||||
static float AbsFloat(float n){return std::abs(n);}
|
||||
};
|
||||
template<class T>struct Array:std::vector<T>{int Count(){return this->size();}};
|
||||
@@ -54,7 +58,7 @@ struct ERR_HQSearchReport{
|
||||
bool SweepCompleted=true,ContactFound=false;
|
||||
};
|
||||
struct Coverage{
|
||||
Map<int,float>m_Cells;Map<int,int>m_Messages;
|
||||
Map<int,float>m_Cells,m_Positive;Map<int,int>m_Messages;float m_PositiveFloor=-1;
|
||||
'''+methods+r'''
|
||||
};
|
||||
int main(){
|
||||
@@ -107,11 +111,46 @@ int main(){
|
||||
// A fresh positive sighting may reopen a coarse cell, without replaying an old negative.
|
||||
Coverage reopened;ERR_HQSearchReport searched;
|
||||
assert(reopened.Ingest(&searched,1000));
|
||||
reopened.Forget({1,12,1});assert(reopened.Count()==0);
|
||||
reopened.Forget({1,12,1},1000);assert(reopened.Count()==0);
|
||||
assert(!reopened.Ingest(&searched,1000));
|
||||
searched.MessageId=2;searched.ObservedAt=2000;
|
||||
assert(reopened.Ingest(&searched,2000));
|
||||
reopened.Forget({nan,0,0});assert(reopened.Count()==1);
|
||||
reopened.Forget({nan,0,0},2000);assert(reopened.Count()==1);
|
||||
// Different beliefs share coverage. Their individual revision gates cannot
|
||||
// protect a newer positive from a delayed negative for another target.
|
||||
Coverage chronology;ERR_HQSearchReport other;
|
||||
other.BeliefId=2;other.ObservedAt=1000;
|
||||
chronology.Forget(other.Position,2000);
|
||||
assert(!chronology.Ingest(&other,3000)&&!chronology.Recent(other.Position,3000));
|
||||
other.MessageId=2;other.ObservedAt=2000;
|
||||
assert(!chronology.Ingest(&other,3000)); // a simultaneous positive wins
|
||||
other.MessageId=3;other.ObservedAt=2001;
|
||||
assert(chronology.Ingest(&other,3000)); // genuinely later physical sweep
|
||||
chronology.Forget(other.Position,1500);
|
||||
assert(chronology.Recent(other.Position,3000)); // delayed old positive cannot reopen it
|
||||
chronology.Forget(other.Position,4000);
|
||||
assert(!chronology.Recent(other.Position,4000));
|
||||
chronology.Forget(other.Position,3500); // do not lower the positive watermark
|
||||
other.SourceId=2;other.MessageId=1;other.ObservedAt=3750;
|
||||
assert(!chronology.Ingest(&other,4500));
|
||||
chronology.Forget({750,0,250},nan);chronology.Forget({750,0,250},-1);
|
||||
assert(chronology.m_Positive.Count()==1);
|
||||
// Watermark pressure stays bounded without reopening an evicted cell to old
|
||||
// evidence. New sweeps still work; Clear resets round-local chronology.
|
||||
Coverage positives;
|
||||
for(int i=0;i<128;i++)positives.Forget({float(i*500+250),0,250},1000+i);
|
||||
positives.Forget({70000,0,250},2000);
|
||||
assert(positives.m_Positive.Count()==128&&positives.m_PositiveFloor==1000);
|
||||
ERR_HQSearchReport evicted;evicted.ObservedAt=999;
|
||||
assert(!positives.Ingest(&evicted,3000));
|
||||
evicted.MessageId=2;evicted.ObservedAt=1001;
|
||||
assert(positives.Ingest(&evicted,3000));
|
||||
positives.Forget({71000,0,250},1001); // older incoming watermark also leaves a floor
|
||||
assert(positives.m_Positive.Count()==128&&positives.m_PositiveFloor==1001);
|
||||
evicted.Position={71000,0,250};evicted.MessageId=3;evicted.ObservedAt=1000;
|
||||
assert(!positives.Ingest(&evicted,3000));
|
||||
positives.Clear();assert(positives.m_Positive.Count()==0&&positives.m_PositiveFloor==-1);
|
||||
evicted.MessageId=1;evicted.ObservedAt=0;assert(positives.Ingest(&evicted,0));
|
||||
// Delivery latency does not restart the 900-second coverage lifetime.
|
||||
Coverage delayed;ERR_HQSearchReport late;
|
||||
assert(delayed.Ingest(&late,120000));
|
||||
@@ -154,8 +193,8 @@ int main(){
|
||||
assert(vector::DistanceXZ(center,destination)<=600);
|
||||
Coverage tiny;reserved.clear();reserved.push_back({1,0,1});
|
||||
assert(!tiny.Select(center,25,center,1000,destination,&reserved));
|
||||
for(int i=0;i<7;i++)reserved.push_back(center);
|
||||
assert(reserved.Count()==8&&tiny.Select(center,2000,center,1000,destination,&reserved));
|
||||
for(int i=0;i<15;i++)reserved.push_back(center);
|
||||
assert(reserved.Count()==16&&tiny.Select(center,2000,center,1000,destination,&reserved));
|
||||
reserved.push_back(center);
|
||||
assert(!tiny.Select(center,2000,center,1000,destination,&reserved));
|
||||
assert(!tiny.Select(center,2001,center,1000,destination));
|
||||
|
||||
Reference in New Issue
Block a user