51 lines
2.7 KiB
Python
51 lines
2.7 KiB
Python
"""Run actual fixture placement geometry; protect native clearance/stock boundary."""
|
|
import re
|
|
from policy_harness import ROOT, body, run
|
|
p = ROOT / 'addons/ai/Scripts/Game/ERR/ERR_NativeMortarCourierProbe.c'
|
|
text = p.read_text()
|
|
geometry = body(p, 'static vector StorageOffset(')
|
|
count = int(re.search(r'STORAGE_CANDIDATES = (\d+)', text).group(1))
|
|
required = int(re.search(r'STORAGE_COUNT = (\d+)', text).group(1))
|
|
assert count == 64 and required == 5
|
|
assert '%' not in geometry, 'Use native Math.Mod; C++ remainder hides Enforce errors'
|
|
run('''#include <cassert>
|
|
#include <cmath>
|
|
#include <vector>
|
|
struct vector {float x,y,z;static const vector Zero;};const vector vector::Zero{0,0,0};
|
|
vector Vector(float x,float y,float z){return {x,y,z};}
|
|
namespace Math {int Mod(int a,int b){return a%b;}}
|
|
constexpr int STORAGE_CANDIDATES=64;
|
|
''' + geometry.replace('Math.', 'Math::').replace('vector.Zero', 'vector::Zero') + '''
|
|
int main(){
|
|
std::vector<vector> seen;
|
|
for(int i=0;i<STORAGE_CANDIDATES;i++){
|
|
auto p=StorageOffset(i);
|
|
assert(p.y==0&&p.x>=20&&p.x<=41&&p.z>=15&&p.z<=36);
|
|
assert(std::hypot(p.x,p.z)<55);
|
|
for(auto old:seen)assert(std::hypot(p.x-old.x,p.z-old.z)>=3);
|
|
seen.push_back(p);
|
|
}
|
|
for(int x=20;x<=41;x+=3)for(int z=15;z<=36;z+=3){
|
|
int matches=0;for(auto p:seen)if(p.x==x&&p.z==z)matches++;assert(matches==1);
|
|
}
|
|
for(int invalid:{-1,64,999}){auto p=StorageOffset(invalid);assert(p.x==0&&p.y==0&&p.z==0);}
|
|
}
|
|
''')
|
|
tick = body(p, 'int Tick(')
|
|
start = tick.index('int tested, lowGround, obstructed;')
|
|
end = tick.index('m_Stage = 1;', start)
|
|
placement = tick[start:end]
|
|
assert 'i < STORAGE_CANDIDATES && m_Stores.Count() < STORAGE_COUNT' in placement
|
|
assert 'if (position[1] <= 1) { lowGround++; continue; }' in placement
|
|
assert 'if (!SCR_WorldTools.TraceCilinderUtil(position + "0 1 0", 1.3, 2, TraceFlags.ENTS | TraceFlags.WORLD)) { obstructed++; continue; }' in placement
|
|
assert placement.index('TraceCilinderUtil') < placement.index('ERR_Actors.Spawn(BOX, position)')
|
|
assert placement.index('m_Mode.Own(box)') < placement.index('box.FindComponent(')
|
|
assert placement.count('ERR_Actors.Spawn(') == 1
|
|
assert 'm_Boxes.Count() == STORAGE_COUNT && m_Stores.Count() == STORAGE_COUNT' in placement
|
|
assert ') return -1;' in placement[placement.index('m_Boxes.Count() == STORAGE_COUNT'):]
|
|
for forbidden in ('TryMoveItem', 'TrySpawn', 'Delete', 'SetOrigin', 'Teleport', 'HandleDamage', 'SHELL'):
|
|
assert forbidden not in placement, forbidden
|
|
assert tick.index('m_Stage = 1;', start) < tick.index('source.TryMoveItemToStorage(')
|
|
assert 'Boxes with borrowed originals remain owned by normal mission cleanup.' in text
|
|
print('PASS: 64 bounded distinct storage candidates; native gates, five-store barrier and finite-stock ownership retained; native placement pending')
|