Include the current addon, terrain integrations, tools, regression tests and recorded development evidence.
60 lines
3.7 KiB
Python
60 lines
3.7 KiB
Python
"""Execute the finite identity reservation used by the real infantry selector."""
|
|
import os,re
|
|
from pathlib import Path
|
|
from policy_harness import ROOT,run
|
|
|
|
def translated_reservation():
|
|
p=Path(os.environ.get('ERR_FINITE_RESERVATION_SOURCE',ROOT/'addons/core/Scripts/Game/ERR/10_AI/ERR_FiniteMagazineReservation.c'))
|
|
source=p.read_text()
|
|
for forbidden in ('Spawn','DeleteEntity','SetAmmoCount','TryMove','TrySwap','GetOrigin'):
|
|
assert forbidden not in source,forbidden
|
|
code=re.sub(r'//[^\n]*','',source).replace('protected ','').replace('ref ','').replace('class ','struct ')
|
|
code=code.replace('array<IEntity>','Array<IEntity>*').replace('void ERR_FiniteMagazineReservation(','ERR_FiniteMagazineReservation(')
|
|
for name in ('m_Original','m_Spent'):code=code.replace(name+'.',name+'->')
|
|
code=re.sub(r'\b(bool|IEntity|Array<IEntity>\*) (\w+);',r'\1 \2{};',code)
|
|
return code.replace('\n}\n','\n};\n')
|
|
|
|
if __name__=='__main__':
|
|
run(r'''
|
|
#include <cassert>
|
|
#include <vector>
|
|
#include <algorithm>
|
|
struct Entity{};using IEntity=Entity*;
|
|
template<class T>struct Array:std::vector<T>{using std::vector<T>::vector;
|
|
int Count(){return this->size();}void Insert(T v){this->push_back(v);}
|
|
bool Contains(T v){return std::find(this->begin(),this->end(),v)!=this->end();}
|
|
void RemoveItem(T v){this->erase(std::remove(this->begin(),this->end(),v),this->end());}};
|
|
'''+translated_reservation()+r'''
|
|
int main(){
|
|
Entity a,b,foreign;
|
|
{Array<IEntity> stock{&a,&b},spent;
|
|
ERR_FiniteMagazineReservation infantry(&stock,&spent,&a),mounted(&stock,&spent,&a);
|
|
assert(infantry.Reserve()&&!infantry.Reserve()&&!mounted.Reserve()&&spent.Count()==1);
|
|
assert(infantry.ReleaseUnsubmitted()&&spent.Count()==0);
|
|
// A failed handle is terminal; a new attempt can claim the released identity.
|
|
assert(!mounted.Reserve());ERR_FiniteMagazineReservation next(&stock,&spent,&a);
|
|
assert(next.Reserve()&&!infantry.ReleaseUnsubmitted()&&!infantry.Commit()&&spent.Count()==1);
|
|
assert(next.Commit()&&!next.ReleaseUnsubmitted()&&!next.Commit());
|
|
ERR_FiniteMagazineReservation replay(&stock,&spent,&a),other(&stock,&spent,&b);
|
|
assert(!replay.Reserve()&&other.Reserve()&&other.Commit()&&spent.Count()==2);}
|
|
// An abandoned uncertain claim stays spent; destruction never implies rollback.
|
|
{Array<IEntity> stock{&a},spent;{ERR_FiniteMagazineReservation pending(&stock,&spent,&a);assert(pending.Reserve());}
|
|
ERR_FiniteMagazineReservation retry(&stock,&spent,&a);assert(!retry.Reserve()&&spent.Count()==1);}
|
|
for(int invalid=0;invalid<5;invalid++){
|
|
Array<IEntity> stock{&a},spent;
|
|
if(invalid==4){for(int i=0;i<96;i++)stock.Insert(&b);}
|
|
ERR_FiniteMagazineReservation r(invalid==0?nullptr:&stock,invalid==1?nullptr:&spent,invalid==2?nullptr:invalid==3?&foreign:&a);
|
|
assert(!r.Reserve()&&!r.Commit()&&!r.ReleaseUnsubmitted()&&spent.Count()==0);}
|
|
{Array<IEntity> stock,spent;std::vector<Entity> entities(97);
|
|
for(int i=0;i<96;i++)stock.Insert(&entities[i]);
|
|
for(int i=0;i<96;i++){ERR_FiniteMagazineReservation r(&stock,&spent,&entities[i]);assert(r.Reserve()&&r.Commit());}
|
|
assert(spent.Count()==96);ERR_FiniteMagazineReservation replay(&stock,&spent,&entities[0]);assert(!replay.Reserve());
|
|
stock.Insert(&entities[96]);ERR_FiniteMagazineReservation overflow(&stock,&spent,&entities[96]);assert(!overflow.Reserve());}
|
|
// The helper never changes the original stock set or grants release before reservation.
|
|
{Array<IEntity> stock{&a},spent;ERR_FiniteMagazineReservation r(&stock,&spent,&a);
|
|
assert(!r.ReleaseUnsubmitted()&&!r.Commit());assert(r.Reserve()&&r.ReleaseUnsubmitted());
|
|
assert(stock.Count()==1&&stock[0]==&a&&spent.Count()==0);}
|
|
}
|
|
''')
|
|
print('PASS: actual shared finite identity reservation; competing consumers, submission permanence, stale cleanup and96-item bound')
|