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:
@@ -0,0 +1,56 @@
|
||||
"""Run the production observation sampler against controlled native perception snapshots."""
|
||||
import re
|
||||
from policy_harness import ROOT,body,run
|
||||
p=ROOT/'addons/core/Scripts/Game/ERR/10_AI/ERR_SoldierSpeechContext.c'
|
||||
s=body(p,'protected void ERR_SpeechObserve(').replace('protected ','')
|
||||
s=s.replace('SCR_AIInfoComponent.Cast(m_Agent.FindComponent(SCR_AIInfoComponent))','infoValue')
|
||||
s=s.replace('array<BaseTarget> targets = {}','Array<BaseTarget*> targets').replace('array<IEntity> counted = {}','Array<IEntity*> counted')
|
||||
s=s.replace('foreach (','for (').replace('null','nullptr').replace('bool threat;','bool threat=false;').replace('BaseTarget anchor;','BaseTarget* anchor=nullptr;')
|
||||
for typ in ['SCR_AIInfoComponent','SCR_AIThreatSystem','BaseTarget','IEntity']:
|
||||
s=re.sub(r'\b'+typ+r' (?=\w)',typ+'* ',s)
|
||||
s=s.replace('vector position','float position').replace('ChimeraCharacter.Cast(seen)','(seen && seen->character)')
|
||||
for obj in ['info','system','target','seen','anchor','m_Entity']:
|
||||
s=s.replace(obj+'.',obj+'->')
|
||||
s=s.replace('m_Perception.','m_Perception->')
|
||||
for obj in ['EAIThreatState','ERR_HQObservation','ERR_Actors','ERR_SoldierConversationRules']:
|
||||
s=s.replace(obj+'.',obj+'::')
|
||||
s=s.replace('Math.Max','std::max').replace('vector.DistanceXZ','Distance')
|
||||
run(r'''
|
||||
#include <cassert>
|
||||
#include <vector>
|
||||
#include <algorithm>
|
||||
#include <cmath>
|
||||
template<class T>struct Array:std::vector<T>{using std::vector<T>::operator=;void Insert(T x){this->push_back(x);}bool Contains(T x){return std::find(this->begin(),this->end(),x)!=this->end();}int Count(){return this->size();}};
|
||||
struct IEntity{bool character=true,fit=true;float pos=0;float GetOrigin(){return pos;}};
|
||||
struct BaseTarget{IEntity*actor=nullptr;float age=0,trace=1,exposure=1,pos=100;float GetTimeSinceSeen(){return age;}float GetTraceFraction(){return trace;}float GetExposure(){return exposure;}IEntity*GetTargetEntity(){return actor;}float GetLastSeenPosition(){return pos;}};
|
||||
namespace ERR_HQObservation{bool IsClearSighting(float age,float trace,float exposure){return age>=0&&age<=.5f&&trace>=1&&exposure>0;}}
|
||||
namespace ERR_Actors{bool CanFight(IEntity*a){return a&&a->fit;}}
|
||||
namespace ETargetCategory{enum{ENEMY};}
|
||||
namespace EAIThreatState{enum{SAFE,ALERTED};}
|
||||
float Distance(float a,float b){return std::abs(a-b);}
|
||||
struct ERR_SoldierConversationRules{
|
||||
'''+body(p,'static bool Approaching(')+r'''
|
||||
};
|
||||
struct Perception{Array<BaseTarget*>targets;void GetTargetsList(Array<BaseTarget*>&out,int){out=targets;}};
|
||||
struct SCR_AIThreatSystem{float m_ERRSpeechOvertUntil=0;};
|
||||
struct SCR_AIInfoComponent{int state=EAIThreatState::SAFE;Perception perception,*m_Perception=&perception;SCR_AIThreatSystem threat;int GetThreatState(){return state;}auto GetThreatSystem(){return &threat;}};
|
||||
struct Sampler{SCR_AIInfoComponent info,*infoValue=&info;IEntity actor,*m_Entity=&actor,*m_ERRSpeechObserved=nullptr;int m_ERRSpeechVisible=0;
|
||||
bool m_ERRSpeechApproaching=false,m_ERRSpeechThreat=false,m_ERRSpeechOvert=false;
|
||||
float m_ERRSpeechOvertUntil=0,m_ERRSpeechThreatUntil=0,m_ERRSpeechApproachingUntil=0,m_ERRSpeechObservedAt=0,m_ERRSpeechTargetPosition=0,m_ERRSpeechObserverPosition=0;
|
||||
'''+s.replace('ETargetCategory.ENEMY','ETargetCategory::ENEMY')+r'''
|
||||
};
|
||||
int main(){
|
||||
Sampler s;IEntity a,b,c;BaseTarget one,two,three;one.actor=&a;two.actor=&b;three.actor=&c;
|
||||
s.info.perception.targets={&one,&one,&two,&three};
|
||||
s.ERR_SpeechObserve(10000);assert(s.m_ERRSpeechVisible==3&&s.m_ERRSpeechThreat&&!s.m_ERRSpeechOvert); // sighting is not open combat; duplicate ignored
|
||||
two.trace=.5;three.age=1;s.ERR_SpeechObserve(11000);assert(s.m_ERRSpeechVisible==1); // occluded and stale do not count
|
||||
s.actor.pos=50;s.ERR_SpeechObserve(12000);assert(!s.m_ERRSpeechApproaching); // our advance is not their advance
|
||||
one.pos=95;s.ERR_SpeechObserve(14000);assert(s.m_ERRSpeechApproaching); // actual observed target motion
|
||||
s.ERR_SpeechObserve(14001);assert(s.m_ERRSpeechApproaching); // immediate transmit retains observation
|
||||
s.info.threat.m_ERRSpeechOvertUntil=35000;s.ERR_SpeechObserve(15000);assert(s.m_ERRSpeechOvert);
|
||||
s.info.perception.targets.clear();s.ERR_SpeechObserve(16000);assert(!s.m_ERRSpeechVisible&&!s.m_ERRSpeechApproaching&&s.m_ERRSpeechThreat); // memory silences chatter, no invented visible count
|
||||
s.ERR_SpeechObserve(80000);assert(!s.m_ERRSpeechThreat&&!s.m_ERRSpeechOvert);
|
||||
c.character=false;three.age=0;s.info.perception.targets={&three};s.ERR_SpeechObserve(81000);assert(!s.m_ERRSpeechVisible); // vehicle never reveals passengers
|
||||
}
|
||||
''')
|
||||
print('PASS: production perception sampler deduplicates visible humans, excludes hidden contacts and vehicle occupants, distinguishes target motion, retains threat memory')
|
||||
Reference in New Issue
Block a user