Merge owned systems into one addon while preserving resource identities. Gate player admission on the replicated prison scene, restore the original framed door, and hold enemy AI until escape. Correct scenario branding and author metadata, include publishing assets, and retain regression and native verification evidence.
58 lines
4.5 KiB
Python
58 lines
4.5 KiB
Python
"""Run actual companion dispatch and discovery ledger bodies; native RPC is separate."""
|
|
from policy_harness import ROOT, body, run
|
|
admin = ROOT / 'addons/core/Scripts/Game/ERR/00_Core/ERR_AdminService.c'
|
|
provider = ROOT / 'addons/core/Scripts/Game/ERR/20_Intel/ERR_IntelAdminProvider.c'
|
|
discovery = ROOT / 'addons/core/Scripts/Game/ERR/00_Core/ERR_DiscoveryService.c'
|
|
execute = body(admin, 'void Execute(')
|
|
assert execute.index('if (!Replication.IsServer()') < execute.index('if (!authorized)') < execute.index('if (Extension(mode, arguments, replies))')
|
|
extension = body(provider, 'override bool Execute(')
|
|
extension = (extension.replace('override ', '').replace('bool Execute(', 'bool Extension(').replace('array<string>', 'Array<string>&')
|
|
.replace('ERR_GameMode mode', 'Mode* mode').replace('ERR_IntelService intel', 'Intel* intel')
|
|
.replace('ERR_HQ hq', 'HQ* hq').replace('ERR_HQ.Cast(', 'HQ::Cast(')
|
|
.replace('super.Extension(', 'Base::Extension(').replace('Math.Max(', 'std::max(')
|
|
.replace('mode.', 'mode->').replace('intel.', 'intel->').replace('hq.', 'hq->')
|
|
.replace('Settings().', 'Settings()->').replace('Journal().', 'Journal()->'))
|
|
ledger = '\n'.join(body(discovery, signature) for signature in ('bool IsSpent(', 'bool CanMarkSpent(', 'bool MarkSpent('))
|
|
ledger = ledger.replace('Replication.', 'Replication::')
|
|
run(r'''
|
|
#include <cassert>
|
|
#include <algorithm>
|
|
#include <string>
|
|
#include <vector>
|
|
#include <set>
|
|
using string=std::string;
|
|
using IEntity=int;
|
|
template<class T> struct Array:std::vector<T>{void Insert(T v){this->push_back(v);}bool IsEmpty(){return this->empty();}};
|
|
template<class T> struct Set:std::set<T>{bool Contains(T v){return this->count(v);}void Insert(T v){this->insert(v);}int Count(){return this->size();}};
|
|
namespace Replication { bool server=true; bool IsServer(){return server;} }
|
|
struct Number {int n;string ToString(){return std::to_string(n);}};
|
|
struct Settings {Number Get(string key){return {key=="aiIntelChancePercent"?60:15};}};
|
|
struct Intel {int starts=0;bool canStart=true;bool BeginReroll(){starts++;return canStart;}string RerollStatus(){return "batch status";}};
|
|
struct Journal {int Sequence(){return 0;}void Read(int,Array<string>&,int&) {}};
|
|
struct HQ {struct Journal journal;static HQ* Cast(HQ* h){return h;}string Status(){return "hq";}struct Journal* Journal(){return &journal;}};
|
|
struct Mode {struct Settings settings;struct Intel* intel=nullptr;struct HQ* hq=nullptr;struct Settings* Settings(){return &settings;}struct Intel* Intel(){return intel;}struct HQ* Command(){return hq;}};
|
|
struct Base {bool Extension(Mode*,string,Array<string>&){return false;}};
|
|
struct Admin:Base {
|
|
'''+extension+r'''
|
|
};
|
|
struct Ledger {Set<IEntity> m_Spent;
|
|
'''+ledger+r'''
|
|
};
|
|
int main(){
|
|
Admin admin;Mode mode;Array<string> replies;Intel intel;mode.intel=&intel;
|
|
assert(admin.Extension(&mode,"intel show",replies));assert(replies.size()==2&&replies[0]=="aiIntelChancePercent=60"&&replies[1]=="intelRevealChancePercent=15"&&intel.starts==0);
|
|
replies.clear();assert(admin.Extension(&mode,"intel reroll show",replies));assert(intel.starts==0&&replies.size()==1&&replies[0]=="batch status");
|
|
replies.clear();assert(admin.Extension(&mode,"intel reroll",replies));assert(intel.starts==1&&replies.size()==1);
|
|
intel.canStart=false;replies.clear();assert(admin.Extension(&mode,"intel reroll",replies));assert(intel.starts==2&&replies.size()==2&&replies[1]=="batch status");
|
|
mode.intel=nullptr;replies.clear();assert(admin.Extension(&mode,"intel reroll",replies));assert(replies.size()==1&&intel.starts==2);
|
|
for(string invalid:{"intel reroll all","intel reroll show extra","intel reroll set 50","intel showing","intel"}) {replies.clear();assert(!admin.Extension(&mode,invalid,replies));assert(replies.empty()&&intel.starts==2);}
|
|
Ledger ledger;assert(!ledger.CanMarkSpent(0)&&!ledger.MarkSpent(0)&&!ledger.IsSpent(0));
|
|
Replication::server=false;assert(!ledger.MarkSpent(1)&&ledger.m_Spent.empty());Replication::server=true;
|
|
assert(ledger.MarkSpent(1)&&ledger.MarkSpent(1)&&ledger.IsSpent(1)&&ledger.m_Spent.size()==1);
|
|
for(int i=2;i<=4096;i++)assert(ledger.MarkSpent(i));
|
|
assert(!ledger.CanMarkSpent(4097)&&ledger.CanMarkSpent(1)&&!ledger.MarkSpent(4097)&&!ledger.IsSpent(4097)&&ledger.MarkSpent(1)&&ledger.m_Spent.size()==4096);
|
|
Replication::server=false;assert(!ledger.MarkSpent(1)&&!ledger.MarkSpent(4097)&&ledger.m_Spent.size()==4096);
|
|
}
|
|
''')
|
|
print('PASS: actual Intel commands distinguish status/start/failure, preserve authorization gate and reject malformed requests; spent ledger is idempotent, server-only and bounded')
|