Include the current addon, terrain integrations, tools, regression tests and recorded development evidence.
51 lines
3.9 KiB
Python
51 lines
3.9 KiB
Python
"""Actual delivered-search clock and bounded road selection, without engine navigation."""
|
|
import re
|
|
from policy_harness import ROOT, body, run
|
|
p = ROOT / 'addons/core/Scripts/Game/ERR/10_AI/ERR_HunterService.c'
|
|
state = body(p, 'class ERR_HunterSearch').replace('class ERR_HunterSearch', 'struct ERR_HunterSearch')
|
|
state = state.replace('vector ', 'Vec ').replace('int MessageId;', 'int MessageId=0;').replace('Math.Clamp', 'std::clamp<float>') + ';'
|
|
point = body(p, 'protected bool SearchPoint(').replace('protected ', '').replace('ERR_HunterVehicle unit', 'ERR_HunterVehicle* unit')
|
|
point = point.replace('out vector ', 'Vec& ').replace('vector ', 'Vec ')
|
|
point = point.replace('unit.', 'unit->').replace('Search.', 'Search->').replace('Entity.', 'Entity->')
|
|
point = point.replace('Math.', 'Math::').replace('ERR_SupplyConvoySystem.', 'ERR_SupplyConvoySystem::').replace('vector.', 'Geometry::')
|
|
run(r'''
|
|
#include <algorithm>
|
|
#include <cassert>
|
|
#include <cmath>
|
|
struct Vec{float x=0,y=0,z=0;Vec operator+(Vec b){return {x+b.x,y+b.y,z+b.z};}Vec operator*(float s){return {x*s,y*s,z*s};}
|
|
float Length(){return std::hypot(x,z);}Vec Normalized(){return *this*(1/Length());}};
|
|
Vec Vector(float x,float y,float z){return {x,y,z};}
|
|
namespace Geometry{float DistanceXZ(Vec a,Vec b){return std::hypot(a.x-b.x,a.z-b.z);}}
|
|
namespace Math{float random=1;float RandomFloat(float,float){return random;}}
|
|
'''+state+r'''
|
|
struct Entity{Vec position;Vec GetOrigin(){return position;}};
|
|
struct ERR_HunterVehicle{ERR_HunterSearch search;ERR_HunterSearch* Search=&search;struct Entity entity;struct Entity* Entity=&entity;};
|
|
namespace ERR_SupplyConvoySystem{int calls=0;bool road=true;Vec projection;float radius=0;
|
|
bool ApproachDirected(Vec seed,Vec& dst,Vec&,float distance){calls++;radius=distance;dst=seed+projection;return road;}}
|
|
struct Service{
|
|
'''+point+r'''
|
|
};
|
|
int main(){
|
|
ERR_HunterSearch search;assert(!search.Active(0));search.Remember({100,0,200},100,7);
|
|
assert(!search.Active(99)&&search.Active(100)&&search.Active(600100)&&!search.Active(600101));
|
|
assert(search.Radius(100)==250&&search.Radius(300100)==550&&search.Radius(600100)==850);
|
|
search.Remember({999,0,999},100,99);assert(search.Center.x==100&&search.MessageId==7); // replay cannot move/renew memory
|
|
search.Remember({999,0,999},99,100);assert(search.ObservedAt==100);
|
|
search.Remember({999,0,999},200,0);assert(search.ObservedAt==100); // not a delivered message
|
|
assert(!search.Ready(false,1000)&&!search.Ready(true,2000)&&!search.Ready(true,61999));
|
|
assert(search.Ready(true,62000));assert(!search.Ready(false,63000));assert(!search.Ready(true,64000));
|
|
search.Remember({300,0,400},65000,8);assert(search.ArrivedAt==-1&&!search.Ready(true,65000));
|
|
assert(!search.Ready(true,665001)&&search.ArrivedAt==-1); // absolute observation deadline
|
|
ERR_HunterVehicle unit;unit.Search->Remember({0,0,0},0,1);Service service;Vec dst,angles;
|
|
assert(service.SearchPoint(&unit,600000,dst,angles));assert(std::abs(Geometry::DistanceXZ(dst,{})-850)<0.1);
|
|
assert(ERR_SupplyConvoySystem::radius==100);
|
|
ERR_SupplyConvoySystem::projection={1000,0,1000};int calls=ERR_SupplyConvoySystem::calls;
|
|
assert(!service.SearchPoint(&unit,600000,dst,angles)&&ERR_SupplyConvoySystem::calls==calls+8); // projected roads cannot escape 1 km envelope
|
|
ERR_SupplyConvoySystem::projection={};unit.entity.position={601,0,601};calls=ERR_SupplyConvoySystem::calls;
|
|
assert(!service.SearchPoint(&unit,600000,dst,angles)&&ERR_SupplyConvoySystem::calls==calls+8); // avoid current road patch
|
|
unit.entity.position={};ERR_SupplyConvoySystem::road=false;assert(!service.SearchPoint(&unit,600000,dst,angles));
|
|
Math::random=0;calls=ERR_SupplyConvoySystem::calls;assert(!service.SearchPoint(&unit,600000,dst,angles)&&ERR_SupplyConvoySystem::calls==calls); // degenerate vector safely rejected
|
|
}
|
|
''')
|
|
print('PASS: searches expire ten minutes after observation, ignore replays, wait at arrival, widen within 1 km and bound road queries')
|