Files
EscapistsReintroduced/tests/test_radio_waiting_text.py
T
2026-10-24 03:03:10 +02:00

89 lines
5.4 KiB
Python

"""Execute actual task/guide copy for initial waiting and subsequent radio states."""
from policy_harness import ROOT, body, run
from pathlib import Path
import os
source = Path(os.environ.get('ERR_OBJECTIVE_TEXT_SOURCE', ROOT / 'addons/core/Scripts/Game/ERR/00_Core/ERR_ObjectiveText.c'))
def translate(s):
s = s.replace('protected ', '').replace('ERR_GameMode mode,', 'ERR_GameMode* mode,')
s = s.replace('ERR_Phase phase', 'int phase').replace('mode.', 'mode->')
s = s.replace('ERR_RadioFeedback feedback', 'int feedback')
s = s.replace('array<ERR_LocationComponent>', 'std::vector<ERR_LocationComponent*>')
s = s.replace('foreach (ERR_LocationComponent location : locations)', 'for (ERR_LocationComponent* location : locations)')
s = s.replace('location.', 'location->').replace('bool roughRadio;', 'bool roughRadio = false;')
s = s.replace('.IsEmpty()', '.empty()').replace('string.Format(', 'Format(')
for name in ('ERR_Phase', 'ERR_LocationKind', 'ERR_RadioFeedback', 'Math'):
s = s.replace(name + '.', name + '::')
return s
methods = '\n'.join(translate(body(source, signature)) for signature in (
'static string RadioFeedbackMessage(', 'protected static string PhaseDescription('))
run(r'''
#include <cassert>
#include <string>
#include <vector>
#include <cmath>
using string=std::string;
namespace ERR_Phase {enum {PREPARING,PRISON,RADIO_SEARCH,RADIO_DEFENCE,EXTRACTION,VICTORY,DEFEAT};}
namespace ERR_LocationKind {enum {PRISON,RADIO,EXTRACTION,OUTPOST,DEPOT};}
namespace ERR_RadioFeedback {enum {INACTIVE,WAITING,TRANSMITTING,INTERRUPTED};}
namespace Math {float Ceil(float n){return std::ceil(n);}}
struct ERR_LocationComponent {int Kind(){return 0;}int Knowledge(){return 0;}};
struct ERR_GameMode {
int pickup=0;int PickupStage(){return pickup;}
int startMode=0;int StartMode(){return startMode;}
int phase=ERR_Phase::RADIO_DEFENCE, feedback=ERR_RadioFeedback::WAITING, remaining=180;
string error;bool occupied=false;int Phase(){return phase;}string PreparationError(){return error;}
void Locations(std::vector<ERR_LocationComponent*>& locations){locations.clear();}
int RadioFeedback(){return feedback;}int DefenceSecondsRemaining(){return remaining;}
bool DefenceOccupied(){return occupied;}float EscapeRadius(){return 9000;}
};
string Format(string s,int value){auto p=s.find("%1");assert(p!=string::npos);return s.replace(p,2,std::to_string(value));}
string Extraction(float radius){assert(radius==9000);return "extraction";}
struct Actual {
''' + methods + r'''
};
bool has(string text,string needle){return text.find(needle)!=string::npos;}
int main(){
ERR_GameMode mode;
mode.phase=ERR_Phase::PREPARING;
assert(has(Actual::PhaseDescription(&mode,false),"Preparing mission sites"));
mode.error="Terrain has no safe navigable placement for Prison. Checks: uneven ground=123; water=45";
auto failure=Actual::PhaseDescription(&mode,false);
assert(has(failure,mode.error)&&has(failure,"restart the scenario")&&!has(failure,"/esc"));
mode.error.clear();mode.phase=ERR_Phase::RADIO_DEFENCE;
for(int duration : {30,180,1800}) {
mode.remaining=duration;
auto task=Actual::PhaseDescription(&mode,true);
assert(has(task,"Waiting for a conscious defender")&&!has(task,"interrupted"));
assert(has(task,std::to_string(duration)+" seconds")&&has(task,"Leaving resets progress"));
auto guide=Actual::PhaseDescription(&mode,false);
assert(has(guide,"Waiting for")&&!has(guide,"interrupted"));
}
mode.feedback=ERR_RadioFeedback::TRANSMITTING;mode.occupied=true;mode.remaining=179;
auto active=Actual::PhaseDescription(&mode,true);
assert(has(active,"up to 180 seconds remaining")&&!has(active,"Waiting")&&!has(active,"interrupted"));
assert(has(Actual::PhaseDescription(&mode,false),"Transmission in progress"));
mode.feedback=ERR_RadioFeedback::INTERRUPTED;mode.occupied=false;mode.remaining=180;
auto interrupted=Actual::PhaseDescription(&mode,true);
assert(has(interrupted,"Transmission interrupted")&&has(interrupted,"180 seconds"));
assert(!has(interrupted,"Waiting")&&has(Actual::PhaseDescription(&mode,false),"Progress has reset"));
mode.feedback=ERR_RadioFeedback::TRANSMITTING;mode.occupied=true;mode.remaining=174;
assert(has(Actual::PhaseDescription(&mode,true),"up to 175 seconds remaining"));
// Occupancy remains the progress authority; WAITING only selects unoccupied copy.
mode.feedback=ERR_RadioFeedback::WAITING;
assert(has(Actual::PhaseDescription(&mode,true),"seconds remaining"));
mode.occupied=false;
assert(has(Actual::PhaseDescription(&mode,true),"Waiting for a conscious defender"));
mode.phase=ERR_Phase::EXTRACTION;assert(Actual::PhaseDescription(&mode,true)=="extraction");
mode.phase=ERR_Phase::VICTORY;assert(Actual::PhaseDescription(&mode,true).empty());
mode.phase=ERR_Phase::DEFEAT;assert(Actual::PhaseDescription(&mode,true).empty());
mode.phase=ERR_Phase::EXTRACTION;
for(int stage : {0,1}) {mode.pickup=stage;assert(Actual::PhaseDescription(&mode,true)=="extraction");}
for(int stage : {2,3}) {mode.pickup=stage;assert(has(Actual::PhaseDescription(&mode,true),"Smoke accepted"));}
mode.pickup=4;assert(has(Actual::PhaseDescription(&mode,true),"all living prisoners"));
assert(has(Actual::PhaseDescription(&mode,true),"eight seconds"));
mode.pickup=5;assert(has(Actual::PhaseDescription(&mode,true),"Stay aboard"));
}
''')
print('PASS: actual initial WAITING task/guide copy, configured duration, unchanged interruption and rounded progress; native task assertion pending')