Files
EscapistsReintroduced/tools/prison_action_selection_evidence.py
T

61 lines
6.8 KiB
Python

"""Independently validate a single wheel trial from native input/choice records."""
import math
import re
from ordinary_gate_choices import join_choice_snapshots,exact_prison_choices
from ordinary_gate_evidence import validate_gate_geometry
from prison_alignment_evidence import validate_facing_evidence
from prison_approach_evidence import need,number,neutral,yaw,angle,horizontal
def validate_selection_evidence(content,nonce,look_proof,approach_proof,facing_proof,proof,*,facing_profile="standard"):
result={'verified':False,'errors':[],'scope':'one guarded private wheel pair and native selection of the original prison lock after verified approach/facing; no F hold, unlock, exit or multiplayer qualification','held_action_verified':False,'escape_verified':False}
try:
facing=validate_facing_evidence(content,nonce,look_proof,approach_proof,facing_proof,profile=facing_profile)
need(facing['verified'],'independent native facing prerequisite failed: '+str(facing['errors']))
need(type(proof) is dict and proof.get('requested') is True and proof.get('completed') is True and proof.get('nonce')==nonce and not proof.get('error') and not proof.get('events') and not proof.get('motions'),'selection did not complete under exact nonce without extra input')
need(set(proof)=={'requested','completed','nonce','geometry','started_monotonic','finished_monotonic','deadline_monotonic','initial_sample','final_sample','selection_samples','actions','wheel','samples'},'unexpected selection proof fields or extra input')
start=number(proof['started_monotonic']);finish=number(proof['finished_monotonic']);deadline=number(proof['deadline_monotonic'])
need(facing_proof['finished_monotonic']<=start<finish<=deadline==facing_proof['deadline_monotonic'],'selection renewed or exceeded original facing deadline')
need(proof['geometry']==facing_proof['geometry'] and proof['actions']==facing_proof['actions'],'selection geometry/actions differ from original facing')
data=join_choice_snapshots(content,nonce);samples=data['snapshots'];anchor=facing['last_sample'];first=proof['initial_sample'];last=proof['final_sample']
need(type(first) is int and type(last) is int and anchor<=first<last and first in samples and last in samples,'invalid selection native references')
geometry=validate_gate_geometry(content,nonce,anchor,last);need(geometry['verified'],'selection gate geometry changed: '+str(geometry['errors']))
refs=proof['samples'];need(type(refs) is list and 2<=len(refs)<=450,'bounded selection receipts missing')
ids=[r['sample'] for r in refs];need(all(type(i) is int for i in ids) and ids==list(range(first,last+1)),'selection receipts missing, repeated or reversed')
receipts={};prior=0
for r in refs:
i=r['sample'];received=number(r['received_monotonic'])
need(type(r['real_ms']) is int and r['real_ms']==samples[i]['real_ms'] and prior<=received<=finish,'selection native/receipt clocks disagree')
receipts[i]=received;prior=received
need(0<=finish-receipts[last]<=.5,'final selection observation stale')
wheel=proof['wheel'];need(type(wheel) is dict and set(wheel)=={'button','attempted_monotonic','after_sample','confirmed','down_monotonic','up_monotonic','released'} and type(wheel['button']) is int and wheel['button']==5 and wheel['confirmed'] is True and wheel['released'] is True,'expected one confirmed wheel5 pair')
attempted=number(wheel['attempted_monotonic']);down=number(wheel['down_monotonic']);up=number(wheel['up_monotonic']);before=wheel['after_sample']
need(start<=attempted<=down<up<finish<=deadline and up-attempted<=1.5 and finish-up<=1.5 and deadline-attempted>=1.5,'wheel request/release/acknowledgement outside original bounds')
need(type(before) is int and first<=before<last and before in receipts and receipts[before]<=attempted and down-receipts[before]<=.5,'wheel proposal lacks fresh pre-input native sample')
queued=re.findall(r'ERR INPUT OBSERVE: run='+re.escape(nonce)+r' sample=0 real=(\d+) world=[^ ]+ QUEUED(?:\r?$)',content,re.MULTILINE)
need(len(queued)==1,'original native queued clock missing');queued=int(queued[0])
body=samples[anchor]['input']['origin'];view=yaw(samples[anchor]['look']['direction']);actions=facing_proof['actions'];acquired=None;previous=None
for i in range(anchor,last+1):
need(i in samples,'missing native handoff/selection sample');s=samples[i];a=s['action'];g=s['geometry'];c=exact_prison_choices(s)
need(queued<=s['real_ms']<queued+45000 and neutral(s) and math.dist(body,s['input']['origin'])<=.05,'selection body/input/lifetime changed')
need(a['phase']==1 and a['pressed']==0 and a['progress']==0 and not a['performing'] and g['door_state']==0 and g['door_control']==0,'selection-only stage operated gate/action')
eye=s['look']['camera'];handle=g['context'];need(.25<=horizontal(eye,handle)<=5,'selection bearing degenerate')
bearing=math.degrees(math.atan2(handle[0]-eye[0],handle[2]-eye[2]));heading=yaw(s['look']['direction'])
need(abs(angle(bearing,heading))<=3 and abs(angle(heading,view))<=.2,'view changed during wheel-only selection')
need(c['actions']==actions and a['context_selected'] and a['cached_performable'] and a['progress_bound'] is a['selected'],'original action list or native binding changed')
chosen=actions[1 if a['selected'] else 0]
need(c['selected_id']==chosen['id'] and c['selected_class']==chosen['class'],'native action class/ID disagrees')
if a['selected']:
need(i>before and i in receipts and receipts[i]>=down,'lock selected before wheel request')
if acquired is None:acquired=i
else:need(acquired is None,'native lock selection dropped after acknowledgement')
if previous is not None:need(0<s['real_ms']-previous<=500,'selection native sample gap')
previous=s['real_ms']
pair=proof['selection_samples'];need(type(pair) is list and len(pair)==2 and all(type(i) is int for i in pair) and before<pair[0] and pair[1]==pair[0]+1 and pair[1]==last,'native selection lacks consecutive references')
one,two=(samples[i] for i in pair)
need(acquired is not None and acquired<=pair[0] and 100<=two['real_ms']-one['real_ms']<=500 and abs(angle(yaw(two['look']['direction']),yaw(one['look']['direction'])))<=.2,'selected view did not settle')
result.update(verified=True,first_sample=first,last_sample=last,selection_samples=pair,selected_action_id=actions[1]['id'],wheel_button=5,native_duration_ms=samples[last]['real_ms']-samples[first]['real_ms'])
except (ValueError,KeyError,TypeError,OverflowError,IndexError) as error:
result['errors'].append(str(error))
return result