Files
EscapistsReintroduced/tests/test_prison_escape_policy.py
T

80 lines
4.8 KiB
Python

"""Boundary/discontinuity regressions execute production policy bodies, not a copy.
Native probe separately exercises the direct locked-door boundary and destroyed gate.
"""
from policy_harness import ROOT, body, run
path=ROOT/'addons/core/Scripts/Game/ERR/ERR_PrisonEscapeService.c'
functions='\n'.join(body(path,s) for s in ('static bool Inside(', 'static bool Continuous(', 'static bool Registration(', 'static bool Grounded(', 'static bool Crossing(')).replace('Math.AbsFloat','std::abs')
run('''#include <cassert>
#include <cmath>
#include <initializer_list>
'''+functions+'''
int main() {
// Initial identity, unique intact gate and complete bounded traversal required.
assert(Registration(true,1,true,true));
assert(!Registration(false,1,true,true));
assert(!Registration(true,0,true,true));
assert(!Registration(true,2,true,true));
assert(!Registration(true,1,false,true));
assert(!Registration(true,1,true,false));
// Four ordinary sides and diagonal boundary behavior; exact boundary still in.
for (float sign : {-1.f,1.f}) {
assert(Crossing(true,sign*7,0,sign*9,0,1000,2));
assert(Crossing(true,0,sign*7,0,sign*9,1000,2));
assert(!Crossing(true,sign*7,0,sign*8,0,1000,1));
}
assert(Crossing(true,7,7,9,9,1000,std::sqrt(8.f)));
// Gate health is deliberately absent: a registered genuine exit counts even
// when intact. Missing registration is still rejected above and by Tick.
// An unarmed/already-outside body or no crossing cannot finish prison.
assert(!Crossing(false,7,0,9,0,1000,2));
assert(!Crossing(true,4,0,5,0,1000,1));
assert(!Crossing(true,9,0,10,0,1000,1));
// Reject far teleport, expired sample, clock reversal/duplicate and flight.
assert(!Crossing(true,0,0,35,0,1000,35));
assert(!Crossing(true,7,0,9,0,2501,2));
assert(!Crossing(true,7,0,9,0,0,2));
assert(!Crossing(true,7,0,9,0,-1,2));
assert(Grounded(0.1f) && Grounded(2.5f));
assert(!Grounded(2.501f) && !Grounded(-0.501f));
// Native spawn candidates can arm; an outside/perimeter-only arrival cannot.
for (float x : {-4.5f,-1.5f,1.5f,4.5f})
for (float z : {-4.5f,-1.5f,1.5f,4.5f}) assert(Inside(x,z,5.5));
assert(!Inside(6,0,5.5) && Inside(6,0,8));
assert(Continuous(2500,31.5f) && !Continuous(2500,31.501f));
}
''')
print('PASS: actual prison registration/crossing policies reject missing/duplicate/destroyed initial gate, incomplete ownership/scan, outside-only body, jumps and stale samples; physical exit independent of later gate damage')
# Actual action bodies, with only native type/member syntax adapted to C++.
# This tests direct execution, not merely a duplicate availability predicate.
action_path=ROOT/'addons/core/Scripts/Game/ERR/ERR_Actions.c'
class ActionSource:
def read_text(self):
source=action_path.read_text()
return source[source.index('class ERR_PrisonDoorAction'):source.index('class ERR_TuneRadioAction')]
action=ActionSource()
availability=body(action,'override bool CanBePerformedScript(').replace('override ','').replace('ERR_GameMode mode = ERR_GameMode.Get();','ERR_GameMode* mode = ERR_GameMode::Get();').replace('mode.Phase()','mode->Phase()').replace('ERR_Phase.PRISON','ERR_Phase::PRISON').replace('super.CanBePerformedScript','Base::CanBePerformedScript').replace('string.Empty','std::string{}')
execution=body(action,'override void PerformAction(').replace('override ','').replace('super.PerformAction','Base::PerformAction')
run('''#include <cassert>
#include <string>
using IEntity=int;
enum ERR_Phase {PREPARING,PRISON,RADIO_SEARCH,RADIO_DEFENCE};
struct ERR_GameMode {int phase=PRISON;static ERR_GameMode* current;static ERR_GameMode* Get(){return current;}int Phase(){return phase;}};
ERR_GameMode* ERR_GameMode::current=nullptr;
struct Base {void SetCannotPerformReason(const std::string&){}bool nativeAllowed=true;int calls=0,owner=0,user=0;bool CanBePerformedScript(IEntity){return nativeAllowed;}void PerformAction(IEntity pOwnerEntity,IEntity pUserEntity){calls++;owner=pOwnerEntity;user=pUserEntity;}};
struct Action:Base {
'''+availability+execution+'''
};
int main(){
Action action;action.PerformAction(42,7);assert(action.calls==0);
ERR_GameMode mode;ERR_GameMode::current=&mode;
mode.phase=PREPARING;action.PerformAction(42,7);assert(action.calls==0);
mode.phase=PRISON;action.PerformAction(42,7);assert(action.calls==0); // AI direct invocation blocked
mode.phase=RADIO_SEARCH;action.nativeAllowed=false;action.PerformAction(42,7);assert(action.calls==0);
action.nativeAllowed=true;action.PerformAction(42,7);assert(action.calls==1&&action.owner==42&&action.user==7);
mode.phase=RADIO_DEFENCE;action.PerformAction(42,8);assert(action.calls==2&&action.user==8);
mode.phase=PRISON;action.PerformAction(42,7);assert(action.calls==2); // revalidated at execution time
}
''')
print('PASS: actual prison door execution blocks direct AI/UI bypass while locked and delegates unchanged native action once after unlock and permission approval')