Build independent base gameplay and source-bound native verification
This commit is contained in:
@@ -0,0 +1,59 @@
|
||||
"""Execute the actual prison search body with a recording clearance predicate.
|
||||
This verifies bounded search order/termination, not terrain or body clearance.
|
||||
"""
|
||||
from policy_harness import ROOT,body,run
|
||||
source=ROOT/'addons/core/Scripts/Game/ERR/ERR_SpawnPlacement.c'
|
||||
search=(body(source,'bool Prison(').replace('map<int, vector> reservations','map<int, vector>* reservations')
|
||||
.replace('out vector position','vector& position').replace('ERR_Actors.', 'ERR_Actors::').replace('Math.', 'Math::'))
|
||||
run('''#include <cassert>
|
||||
#include <cmath>
|
||||
#include <vector>
|
||||
#include <set>
|
||||
#include <utility>
|
||||
struct vector {float x,y,z;};
|
||||
vector operator+(vector a,vector b){return {a.x+b.x,a.y+b.y,a.z+b.z};}
|
||||
vector Vector(float x,float y,float z){return {x,y,z};}
|
||||
template<class K,class V> struct map {};
|
||||
namespace ERR_Actors {vector Ground(vector value){return value;}}
|
||||
namespace Math {int AbsInt(int value){return std::abs(value);}}
|
||||
struct Search {
|
||||
std::vector<vector> visited;
|
||||
int accept=-1;
|
||||
bool Clear(vector candidate,map<int,vector>*){visited.push_back(candidate);return int(visited.size())-1==accept;}
|
||||
''' + search + '''
|
||||
};
|
||||
int main(){
|
||||
const vector center={6090,100,7160};
|
||||
vector result={-1,-1,-1};
|
||||
Search blocked;
|
||||
assert(!blocked.Prison(center,nullptr,result));
|
||||
assert(blocked.visited.size()==16);
|
||||
assert(result.x==-1&&result.y==-1&&result.z==-1); // no outside fallback
|
||||
std::set<std::pair<float,float>> unique;
|
||||
for(int i=0;i<16;++i){
|
||||
vector candidate=blocked.visited[i];
|
||||
float x=candidate.x-center.x,z=candidate.z-center.z;
|
||||
assert(std::abs(x)<=4.5f&&std::abs(z)<=4.5f);
|
||||
assert(unique.insert({x,z}).second);
|
||||
assert(std::abs(x)==1.5f||std::abs(x)==4.5f);
|
||||
assert(std::abs(z)==1.5f||std::abs(z)==4.5f);
|
||||
int outer=(std::abs(x)==4.5f)+(std::abs(z)==4.5f);
|
||||
assert(outer==(i<4?0:(i<12?1:2)));
|
||||
if(i<12)assert(std::hypot(x,z)<5); // inner and edge spawns meet prior 5m check
|
||||
for(int j=0;j<i;++j){
|
||||
vector previous=blocked.visited[j];
|
||||
assert(std::hypot(candidate.x-previous.x,candidate.z-previous.z)>=3);
|
||||
}
|
||||
}
|
||||
// Select any first available position; never bypass the native clearance predicate.
|
||||
for(int accepted=0;accepted<16;++accepted){
|
||||
Search search;search.accept=accepted;
|
||||
assert(search.Prison(center,nullptr,result));
|
||||
assert(search.visited.size()==unsigned(accepted+1));
|
||||
vector expected=blocked.visited[accepted];
|
||||
assert(result.x==expected.x&&result.y==expected.y&&result.z==expected.z);
|
||||
}
|
||||
|
||||
}
|
||||
''')
|
||||
print('PASS: prison search packs 16 unique 3m-spaced inside-wall centers, prioritizes inner/edge positions and never bypasses clearance')
|
||||
Reference in New Issue
Block a user