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,70 @@
|
||||
"""Execute production speech gating with simulated native perception and playback."""
|
||||
import re
|
||||
from policy_harness import ROOT, body, run
|
||||
p=ROOT/'addons/core/Scripts/Game/ERR/10_AI/ERR_SoldierSpeechContext.c'
|
||||
rules='\n'.join(body(p,x) for x in ['static bool Quiet(', 'static bool Calm(', 'static int CountPhrase(', 'static bool Approaching('])
|
||||
s=body(p,'override protected void TransmitRequest(').replace('override protected ','')
|
||||
s=s.replace('SCR_AITalkRequest rq','SCR_AITalkRequest* rq').replace('SCR_AICommsHandler partner','Handler* partner')
|
||||
s=s.replace('m_Agent.GetParentGroup()', 'hasGroup')
|
||||
s=s.replace('super.TransmitRequest(rq)','Stock(rq)').replace('GetGame().GetWorld().GetWorldTime()','clockNow').replace('GetGame().ERR_SoldierCallout','Callout')
|
||||
for n in ['rq','partner','m_ERRSpeechPartner','m_Entity']:
|
||||
s=s.replace(n+'.',n+'->')
|
||||
for n in ['ERR_SoldierConversationRules','ECommunicationType','SCR_EAITalkRequestState','ERR_Actors']:
|
||||
s=s.replace(n+'.',n+'::')
|
||||
s=s.replace('vector.Distance','Distance')
|
||||
run(r'''
|
||||
#include <cassert>
|
||||
#include <cmath>
|
||||
#include <initializer_list>
|
||||
struct ERR_SoldierConversationRules{
|
||||
'''+rules+r'''
|
||||
};
|
||||
namespace ECommunicationType{enum{REPORT_IDLE,REPORT_CONTACT,REPORT_ENGAGING,REPORT_RELOADING};}
|
||||
namespace SCR_EAITalkRequestState{enum{IDLE,TRANSMITTING};}
|
||||
struct SCR_AITalkRequest{int m_ERRSpeechPhrase=-1,m_eCommType=ECommunicationType::REPORT_CONTACT,m_eState=0;};
|
||||
struct Actor{bool fit=true;float pos=0;float GetOrigin(){return pos;}};
|
||||
namespace ERR_Actors{bool CanFight(Actor*a){return a&&a->fit;}}
|
||||
float Distance(float a,float b){return std::abs(a-b);}
|
||||
float clockNow=100000;
|
||||
struct Handler{
|
||||
bool hasGroup=true,enabled=true,calm=true,plays=true,operationValid=true,m_ERRSpeechThreat=false,m_ERRSpeechOvert=false,m_ERRSpeechApproaching=false;
|
||||
float m_ERRSpeechNextLine=0,m_ERRSpeechNextReport=0,m_ERRSpeechReplyAt=0;
|
||||
int m_ERRSpeechConversation=0,m_ERRSpeechVisible=3,m_ERRSpeechReply=-1,stock=0,calls=0,lastPhrase=-1;
|
||||
Actor actor,other,*m_Entity=&actor,*m_ERRSpeechPartner=&other;
|
||||
void*m_VoNComponent=nullptr; Handler*mate=nullptr;
|
||||
bool ERR_SpeechEnabled(){return enabled;}void ERR_SpeechObserve(float){}bool ERR_SpeechGroupCalm(){return calm;}
|
||||
Handler*ERR_SpeechFindPartner(){return mate;}
|
||||
bool ERR_SpeechOperationValid(SCR_AITalkRequest*,float){return operationValid;}
|
||||
void Stock(SCR_AITalkRequest*){stock++;}
|
||||
bool Callout(Actor*,SCR_AITalkRequest*,void*,int phrase){calls++;lastPhrase=phrase;return plays;}
|
||||
'''+s+r'''
|
||||
};
|
||||
int main(){
|
||||
for(bool threat:{false,true})for(bool overt:{false,true}){
|
||||
assert(ERR_SoldierConversationRules::Quiet(threat,overt)==(threat&&!overt));
|
||||
assert(ERR_SoldierConversationRules::Calm(threat,overt)==(!threat&&!overt));
|
||||
}
|
||||
assert(ERR_SoldierConversationRules::CountPhrase(0)==-1);
|
||||
assert(ERR_SoldierConversationRules::CountPhrase(3)==1003);
|
||||
assert(ERR_SoldierConversationRules::CountPhrase(9)==1004);
|
||||
assert(ERR_SoldierConversationRules::Approaching(2000,100,95));
|
||||
assert(!ERR_SoldierConversationRules::Approaching(2000,100,100)); // observer movement alone
|
||||
assert(!ERR_SoldierConversationRules::Approaching(10000,100,90)); // stale track
|
||||
assert(!ERR_SoldierConversationRules::Approaching(100,100,90)); // tiny noisy interval
|
||||
{Handler h;SCR_AITalkRequest q;h.m_ERRSpeechThreat=true;h.plays=false;h.TransmitRequest(&q);assert(!h.stock&&!h.calls&&q.m_eState==1);} // no stock leak
|
||||
{Handler h;SCR_AITalkRequest q;h.enabled=false;h.TransmitRequest(&q);assert(h.stock==1&&!h.calls);} // optional feature off
|
||||
{Handler h;SCR_AITalkRequest q;q.m_ERRSpeechPhrase=1100;h.enabled=false;h.TransmitRequest(&q);assert(!h.stock&&!h.calls);} // generated request cannot leak after disable
|
||||
{Handler h;SCR_AITalkRequest q;h.m_ERRSpeechThreat=true;h.m_ERRSpeechOvert=true;h.TransmitRequest(&q);assert(h.calls==1&&h.lastPhrase==1003&&!h.stock);}
|
||||
{Handler h;SCR_AITalkRequest q;h.m_ERRSpeechOvert=true;h.m_ERRSpeechApproaching=true;h.TransmitRequest(&q);assert(h.lastPhrase==1005);}
|
||||
{Handler h;SCR_AITalkRequest q;h.plays=false;h.TransmitRequest(&q);assert(h.stock==1);} // allowed native fallback
|
||||
{Handler h;SCR_AITalkRequest q;q.m_eCommType=ECommunicationType::REPORT_IDLE;h.calm=false;h.TransmitRequest(&q);assert(!h.calls&&!h.stock);}
|
||||
{Handler h,partner;h.mate=&partner;SCR_AITalkRequest q;q.m_eCommType=ECommunicationType::REPORT_IDLE;q.m_ERRSpeechPhrase=1100;h.TransmitRequest(&q);assert(partner.m_ERRSpeechReply==1101&&partner.m_ERRSpeechReplyAt==107000&&partner.m_ERRSpeechPartner==h.m_Entity);}
|
||||
{Handler h,partner;h.mate=&partner;h.plays=false;SCR_AITalkRequest q;q.m_ERRSpeechPhrase=1100;q.m_eCommType=ECommunicationType::REPORT_IDLE;h.TransmitRequest(&q);assert(partner.m_ERRSpeechReply==-1&&!h.stock);} // no reply to an unheard question
|
||||
{Handler h;SCR_AITalkRequest q;q.m_ERRSpeechPhrase=1101;q.m_eCommType=ECommunicationType::REPORT_IDLE;h.other.pos=10;h.TransmitRequest(&q);assert(!h.calls&&!h.stock);} // separated after queueing
|
||||
{Handler h;SCR_AITalkRequest q;h.m_ERRSpeechNextLine=clockNow+1;h.TransmitRequest(&q);assert(!h.calls&&!h.stock);} // no overlapping lines
|
||||
{Handler h;SCR_AITalkRequest q;q.m_ERRSpeechPhrase=1200;q.m_eCommType=ECommunicationType::REPORT_IDLE;h.m_ERRSpeechThreat=true;h.m_ERRSpeechOvert=true;h.calm=false;h.TransmitRequest(&q);assert(h.calls==1&&h.lastPhrase==1200&&!h.stock);} // actual covering is tactical speech during overt combat
|
||||
{Handler h;SCR_AITalkRequest q;q.m_ERRSpeechPhrase=1200;h.operationValid=false;h.TransmitRequest(&q);assert(!h.calls&&!h.stock);} // changed action cannot leak through native fallback
|
||||
{Handler h;SCR_AITalkRequest q;q.m_ERRSpeechPhrase=1201;h.m_ERRSpeechThreat=true;h.TransmitRequest(&q);assert(!h.calls&&!h.stock);} // orders do not expose an undiscovered squad
|
||||
}
|
||||
''')
|
||||
print('PASS: covert silence including stock fallback, actual counts, observed approach, optional-feature isolation, reply guards and cooldown')
|
||||
Reference in New Issue
Block a user