nx_input_abstract_gate.nx source
↩ module page · 202 lines · 8257 B
1// nx_input_abstract_gate.nx -- proves the device-agnostic input core (F1102) does what the game
2// platform needs: four sources drive ONE action state, edges are real (no held-repeat), releasing one
3// device never eats another's hold, axis hysteresis is asymmetric, bindings are data, and the whole
4// thing is deterministic. T8 is the anti-vacuity tooth: the scripted mixed-source session must have
5// actually produced actions, or a lib that returns 0 forever would score 7/8.
6// license_tier: ORIGINAL expect_exit: 0
7import "nx_input_abstract.nx"
8
9func vw(s: *u8) -> i64 { var n: i64=0; while s[n]!=(0 as u8){n=n+1} sys_write(1,s,n); return 0 }
10func vn(v: i64) -> i64 {
11 let t: *u8 = sys_mmap(32) as *u8
12 var m: i64 = v; var w: i64 = 0
13 if m<0 { t[w]=45 as u8; w=w+1; m=0-m }
14 if m==0 { t[w]=48 as u8; sys_write(1,t,w+1); return 0 }
15 let d: *u8 = sys_mmap(32) as *u8
16 var k: i64=0
17 while m>0 { d[k]=(48+(m%10)) as u8; m=m/10; k=k+1 }
18 var j: i64=0
19 while j<k { t[w]=d[k-1-j]; w=w+1; j=j+1 }
20 sys_write(1,t,w); return 0
21}
22func pop8(v: i64) -> i64 {
23 var c: i64 = 0
24 var i: i64 = 0
25 while i < 8 { if ((v >> i) & 1) == 1 { c = c + 1 } i = i + 1 }
26 return c
27}
28
29// the scripted mixed-source session used by T7 (determinism) and T8 (anti-vacuity).
30// st[0]=rolling ck st[1]=pressed-edge count st[2]=OR of every held mask st[3]=touch contributed
31func seq(p: *i64, stt: *i64) -> i64 {
32 stt[0]=0; stt[1]=0; stt[2]=0; stt[3]=0
33 ia_init(p)
34 var f: i64 = 0
35 while f < 19 {
36 if f == 0 { ia_key(p, 87, 1) }
37 if f == 2 { ia_key(p, 87, 0) }
38 if f == 3 { ia_pad(p, 0, 1) }
39 if f == 4 { ia_pad(p, 0, 0) }
40 if f == 5 { ia_axis(p, 0, 500) }
41 if f == 6 { ia_axis(p, 0, 300) }
42 if f == 7 { ia_axis(p, 0, 100) }
43 if f == 8 { ia_touch(p, 150, 10, 300, 300, 1)
44 if p[IA_TOUCH] != 0 { stt[3] = 1 } }
45 if f == 9 { ia_touch(p, 0, 0, 0, 0, 0) }
46 if f == 10 { ia_key(p, 65, 1); ia_pad(p, 15, 1) }
47 if f == 11 { ia_key(p, 65, 0) }
48 if f == 12 { ia_pad(p, 15, 0) }
49 if f == 13 { ia_key(p, 69, 1) }
50 if f == 14 { ia_key(p, 69, 0) }
51 if f == 15 { ia_key(p, 66, 1) }
52 if f == 16 { ia_key(p, 66, 0) }
53 if f == 17 { ia_key(p, 13, 1) }
54 if f == 18 { ia_key(p, 13, 0) }
55 let held: i64 = ia_held(p)
56 let pressed: i64 = ia_frame(p)
57 stt[0] = (stt[0]*131 + held*3 + pressed) % 1000000007
58 stt[1] = stt[1] + pop8(pressed)
59 stt[2] = stt[2] | held
60 f = f + 1
61 }
62 return 0
63}
64
65func main() -> i64 {
66 let p: *i64 = sys_mmap(IA_WORDS*8) as *i64
67 var pass: i64 = 0
68 let total: i64 = 10
69 vw("=== nx_input_abstract gate (F1102 device-agnostic input) ===\n" as *u8)
70
71 // T1 UNIFICATION: keyboard, pad button, axis, and touch each alone produce IA_UP, then release to 0
72 ia_init(p)
73 var t1: i64 = 0
74 ia_key(p, 87, 1)
75 if ia_held(p) == IA_UP { t1 = t1 + 1 }
76 ia_key(p, 87, 0)
77 if ia_held(p) == 0 { t1 = t1 + 1 }
78 ia_pad(p, 12, 1)
79 if ia_held(p) == IA_UP { t1 = t1 + 1 }
80 ia_pad(p, 12, 0)
81 if ia_held(p) == 0 { t1 = t1 + 1 }
82 ia_axis(p, 1, 0-600)
83 if ia_held(p) == IA_UP { t1 = t1 + 1 }
84 ia_axis(p, 1, 0)
85 if ia_held(p) == 0 { t1 = t1 + 1 }
86 ia_touch(p, 150, 10, 300, 300, 1)
87 if ia_held(p) == IA_UP { t1 = t1 + 1 }
88 ia_touch(p, 0, 0, 0, 0, 0)
89 if ia_held(p) == 0 { t1 = t1 + 1 }
90 vw("T1 four sources -> one action, each asserts+releases: " as *u8); vn(t1); vw("/8\n" as *u8)
91 if t1 == 8 { pass = pass + 1 }
92
93 // T2 EDGE: held two frames -> pressed only on the first (kills interact-repeats-while-held)
94 ia_init(p)
95 ia_key(p, 69, 1)
96 let p1: i64 = ia_frame(p)
97 let p2: i64 = ia_frame(p)
98 vw("T2 pressed frame1=" as *u8); vn(p1); vw(" frame2=" as *u8); vn(p2)
99 vw(" (held both frames)\n" as *u8)
100 if p1 == IA_A { if p2 == 0 { if ia_held(p) == IA_A { pass = pass + 1 } } }
101
102 // T3 RELEASE: keyup drops the bit; a fresh press after release is a NEW edge
103 ia_key(p, 69, 0)
104 var t3: i64 = 0
105 if ia_held(p) == 0 { t3 = 1 }
106 let pr3: i64 = ia_frame(p)
107 ia_key(p, 69, 1)
108 let pr4: i64 = ia_frame(p)
109 vw("T3 release clears, re-press re-edges: held0=" as *u8); vn(t3)
110 vw(" edge=" as *u8); vn(pr4); vw("\n" as *u8)
111 if t3 == 1 { if pr3 == 0 { if pr4 == IA_A { pass = pass + 1 } } }
112
113 // T4 CROSS-DEVICE UNION: kb LEFT + pad RIGHT held together; releasing the KEY leaves the PAD hold
114 ia_init(p)
115 ia_key(p, 65, 1)
116 ia_pad(p, 15, 1)
117 var t4: i64 = 0
118 if ia_held(p) == (IA_LEFT | IA_RIGHT) { t4 = 1 }
119 ia_key(p, 65, 0)
120 vw("T4 union then key-release: both=" as *u8); vn(t4)
121 vw(" after=" as *u8); vn(ia_held(p)); vw(" (must be RIGHT=8)\n" as *u8)
122 if t4 == 1 { if ia_held(p) == IA_RIGHT { pass = pass + 1 } }
123
124 // T5 AXIS HYSTERESIS: assert at 400, keep at 300, drop at 200, and 300 must NOT re-assert
125 ia_init(p)
126 var t5: i64 = 0
127 ia_axis(p, 0, 400)
128 if ia_held(p) == IA_RIGHT { t5 = t5 + 1 }
129 ia_axis(p, 0, 300)
130 if ia_held(p) == IA_RIGHT { t5 = t5 + 1 }
131 ia_axis(p, 0, 200)
132 if ia_held(p) == 0 { t5 = t5 + 1 }
133 ia_axis(p, 0, 300)
134 if ia_held(p) == 0 { t5 = t5 + 1 }
135 vw("T5 hysteresis 400:on 300:kept 200:off 300:stays-off = " as *u8); vn(t5); vw("/4\n" as *u8)
136 if t5 == 4 { pass = pass + 1 }
137
138 // T6 BINDINGS ARE DATA: bind Z->B, unbind E, unbound key is a no-op
139 ia_init(p)
140 var t6: i64 = 0
141 ia_bind(p, 90, IA_B)
142 ia_key(p, 90, 1)
143 if ia_held(p) == IA_B { t6 = t6 + 1 }
144 ia_key(p, 90, 0)
145 ia_bind(p, 69, 0)
146 ia_key(p, 69, 1)
147 if ia_held(p) == 0 { t6 = t6 + 1 }
148 ia_key(p, 81, 1)
149 if ia_held(p) == 0 { t6 = t6 + 1 }
150 vw("T6 rebind/unbind/no-op = " as *u8); vn(t6); vw("/3\n" as *u8)
151 if t6 == 3 { pass = pass + 1 }
152
153 // T7 DETERMINISM: the same mixed-source session on two fresh arenas folds to the same checksum
154 let pa: *i64 = sys_mmap(IA_WORDS*8) as *i64
155 let pb: *i64 = sys_mmap(IA_WORDS*8) as *i64
156 let sa: *i64 = sys_mmap(8*8) as *i64
157 let sb: *i64 = sys_mmap(8*8) as *i64
158 seq(pa, sa)
159 seq(pb, sb)
160 vw("T7 session ck " as *u8); vn(sa[0]); vw(" == " as *u8); vn(sb[0]); vw("\n" as *u8)
161 if sa[0] == sb[0] { if sa[0] != 0 { pass = pass + 1 } }
162
163 // T8 ANTI-VACUITY: that session really produced input -- >=3 distinct actions, >=5 edges, touch fed
164 vw("T8 distinct-bits=" as *u8); vn(pop8(sa[2])); vw(" edges=" as *u8); vn(sa[1])
165 vw(" touch=" as *u8); vn(sa[3]); vw("\n" as *u8)
166 if pop8(sa[2]) >= 3 { if sa[1] >= 5 { if sa[3] == 1 { pass = pass + 1 } } }
167
168 // T9 16-ACTION WIDENING (seq1136): the original 8 values are FROZEN and the new bits bind+fire
169 var t9: i64 = 0
170 if IA_UP == 1 { if IA_DOWN == 2 { if IA_LEFT == 4 { if IA_RIGHT == 8 { t9 = t9 + 1 } } } }
171 if IA_A == 16 { if IA_B == 32 { if IA_MENU == 64 { if IA_PAUSE == 128 { t9 = t9 + 1 } } } }
172 if IA_JUMP == 256 { if IA_LUP == 512 { if IA_LDOWN == 1024 { if IA_MOD == 2048 { t9 = t9 + 1 } } } }
173 ia_init(p)
174 ia_bind(p, 32, IA_JUMP) // a consumer MAY rebind space -> jump
175 ia_key(p, 32, 1)
176 if ia_held(p) == IA_JUMP { t9 = t9 + 1 }
177 ia_key(p, 32, 0)
178 vw("T9 widened actions frozen+bindable: " as *u8); vn(t9); vw("/4\n" as *u8)
179 if t9 == 4 { pass = pass + 1 }
180
181 // T10 LOOK CHANNEL: deltas ACCUMULATE, drain exactly once, and clamp
182 ia_init(p)
183 var t10: i64 = 0
184 ia_look(p, 30, 0-10)
185 ia_look(p, 15, 0-5)
186 let lk: *i64 = sys_mmap(16) as *i64
187 ia_look_take(p, lk)
188 if lk[0] == 45 { if lk[1] == 0-15 { t10 = t10 + 1 } }
189 ia_look_take(p, lk)
190 if lk[0] == 0 { if lk[1] == 0 { t10 = t10 + 1 } }
191 ia_look(p, 999999, 0-999999)
192 ia_look_take(p, lk)
193 if lk[0] == IA_LOOK_CLAMP { if lk[1] == 0 - IA_LOOK_CLAMP { t10 = t10 + 1 } }
194 vw("T10 look accumulate/drain-once/clamp: " as *u8); vn(t10); vw("/3\n" as *u8)
195 if t10 == 3 { pass = pass + 1 }
196
197 vw("nx_input_abstract_gate: " as *u8); vn(pass); vw("/" as *u8); vn(total); vw("\n" as *u8)
198 if pass == total { vw("VERDICT GREEN -- one action state, four devices, edges+bindings proven\n" as *u8); sys_exit(0) }
199 vw("VERDICT RED\n" as *u8)
200 sys_exit(1)
201 return 0
202}