nx_limb_count.nx source
↩ module page · 315 lines · 12234 B
1// nx_limb_count.nx -- Tier 6 anatomical limb-count detector.
2//
3// CAPABILITY_COMPLETENESS: FULL
4//
5// User feedback 2026-05-16 (image #3 thread): "there is no visible
6// nudity as her aerolas and vagina aqre covered but its a weird
7// melty body" -- and earlier: "her pose was odd with her touching
8// a wall." Generative AI produces the "three hands" failure with
9// alarming frequency: a body silhouette with more limbs than
10// anatomy allows.
11//
12// nx_finger_count counts FINGERS within a hand mask. This
13// primitive counts LIMBS attached to a torso. Anatomical norm:
14// 4 (2 arms + 2 legs). Verdict by deviation.
15//
16// Method:
17// Input: torso bbox + N candidate-limb records, each with:
18// - end_x, end_y (the limb's root point -- the end
19// closest to torso, e.g. shoulder for arm, hip for leg)
20// - role hint: ARM / LEG / UNKNOWN (caller-tagged)
21// - bbox
22// For each candidate, check if end-point is INSIDE the torso
23// bbox (with optional padding tolerance). Limbs that attach
24// to torso count. Limbs that DON'T attach are EXTRA / FLOATING.
25//
26// verdict by total-attached:
27// 4 -> OK
28// 5+ -> EXTRA (the "three hands" failure)
29// 3 -> MISSING (occlusion or actual missing limb)
30// 0-2 -> FUSED / SEVERE_OCCLUSION
31//
32// Plus separately track FLOATING limbs (candidates whose root
33// doesn't attach to torso): a single floating limb is the
34// canonical "extra arm floating in space" failure.
35//
36// genealogy_id: substrate_anatomical_limb_count_2026_05_16
37// lineage_id: tier_6_anatomy_coherence_v1
38
39import "nx_syscalls.nx"
40import "nx_runtime.nx"
41import "nx_tier.nx"
42
43// ===== sealed-enum: limb roles ===================================
44
45const NX_LIMB_ROLE_UNKNOWN: nx_int = 0
46const NX_LIMB_ROLE_ARM: nx_int = 1
47const NX_LIMB_ROLE_LEG: nx_int = 2
48const NX_LIMB_ROLE_WING: nx_int = 3 // for non-human / dragon / etc.
49const NX_LIMB_ROLE_TAIL: nx_int = 4
50const NX_LIMB_ROLE_N_KINDS: nx_int = 5
51
52// ===== sealed-enum: verdict ======================================
53
54const NX_LC_VERDICT_OK: nx_int = 0
55const NX_LC_VERDICT_EXTRA: nx_int = 1
56const NX_LC_VERDICT_MISSING: nx_int = 2
57const NX_LC_VERDICT_FUSED: nx_int = 3
58const NX_LC_VERDICT_FLOATING_LIMB: nx_int = 4
59const NX_LC_VERDICT_WRONG_ARM_LEG_RATIO: nx_int = 5
60
61// ===== caller bounds =============================================
62
63const NX_LC_MAX_LIMBS: nx_int = 32
64const NX_LC_DEFAULT_PADDING: nx_int = 8 // pixels around torso bbox
65
66// Anatomical norms.
67const NX_LC_HUMAN_ARMS: nx_int = 2
68const NX_LC_HUMAN_LEGS: nx_int = 2
69const NX_LC_HUMAN_TOTAL: nx_int = 4
70
71// ===== limb candidate struct =====================================
72
73struct NxLimbCandidate {
74 end_x: nx_int,
75 end_y: nx_int,
76 role: nx_int, // sealed enum above
77 bbox_x0: nx_int,
78 bbox_y0: nx_int,
79 bbox_x1: nx_int,
80 bbox_y1: nx_int,
81}
82
83const NX_LIMB_CANDIDATE_BYTES: nx_size = 56
84
85// ===== result struct =============================================
86
87struct NxLimbCountResult {
88 n_candidates: nx_int,
89 n_attached: nx_int,
90 n_floating: nx_int,
91 n_arms_attached: nx_int,
92 n_legs_attached: nx_int,
93 n_unknown_attached: nx_int,
94 delta_from_norm: nx_int,
95 verdict: nx_int,
96}
97
98const NX_LC_RESULT_BYTES: nx_size = 64
99
100// ===== helper: point inside bbox (with padding) ==================
101
102func _lc_point_in_bbox(x: nx_int, y: nx_int,
103 bx0: nx_int, by0: nx_int, bx1: nx_int, by1: nx_int,
104 padding: nx_int) -> nx_int {
105 if x < (bx0 - padding) { return 0 }
106 if x > (bx1 + padding) { return 0 }
107 if y < (by0 - padding) { return 0 }
108 if y > (by1 + padding) { return 0 }
109 return 1
110}
111
112// ===== check ====================================================
113
114func nx_limb_count_check(
115 torso_x0: nx_int, torso_y0: nx_int, torso_x1: nx_int, torso_y1: nx_int,
116 candidates: *NxLimbCandidate, n_candidates: nx_int,
117 padding: nx_int) -> *NxLimbCountResult {
118
119 if n_candidates < 0 { return 0 as *NxLimbCountResult }
120 if n_candidates > NX_LC_MAX_LIMBS { return 0 as *NxLimbCountResult }
121 var pad: nx_int = padding
122 if pad < 0 { pad = NX_LC_DEFAULT_PADDING }
123
124 let r_ptr: *u8 = sys_mmap(NX_LC_RESULT_BYTES)
125 let r: *NxLimbCountResult = r_ptr as *NxLimbCountResult
126 r.n_candidates = n_candidates
127 r.n_attached = 0
128 r.n_floating = 0
129 r.n_arms_attached = 0
130 r.n_legs_attached = 0
131 r.n_unknown_attached = 0
132
133 var i: nx_int = 0
134 while i < n_candidates {
135 let cand: *NxLimbCandidate =
136 (candidates as *u8 + (i as nx_size) * NX_LIMB_CANDIDATE_BYTES) as *NxLimbCandidate
137 let attached: nx_int = _lc_point_in_bbox(
138 cand.end_x, cand.end_y,
139 torso_x0, torso_y0, torso_x1, torso_y1, pad)
140 if attached == 1 {
141 r.n_attached = r.n_attached + 1
142 if cand.role == NX_LIMB_ROLE_ARM {
143 r.n_arms_attached = r.n_arms_attached + 1
144 } else {
145 if cand.role == NX_LIMB_ROLE_LEG {
146 r.n_legs_attached = r.n_legs_attached + 1
147 } else {
148 r.n_unknown_attached = r.n_unknown_attached + 1
149 }
150 }
151 } else {
152 r.n_floating = r.n_floating + 1
153 }
154 i = i + 1
155 }
156
157 let delta: nx_int = r.n_attached - NX_LC_HUMAN_TOTAL
158 r.delta_from_norm = delta
159
160 // Floating limbs are the canonical "extra hand in space" failure.
161 if r.n_floating >= 1 {
162 r.verdict = NX_LC_VERDICT_FLOATING_LIMB
163 return r
164 }
165
166 if r.n_attached == NX_LC_HUMAN_TOTAL {
167 // Right count. Check arm/leg ratio.
168 // Allow either explicit (2 arms + 2 legs) or all-unknown
169 // (2 unknown + 2 unknown). Reject 3 arms + 1 leg.
170 if r.n_arms_attached == NX_LC_HUMAN_ARMS {
171 if r.n_legs_attached == NX_LC_HUMAN_LEGS {
172 r.verdict = NX_LC_VERDICT_OK
173 return r
174 }
175 }
176 if r.n_arms_attached == 0 {
177 if r.n_legs_attached == 0 {
178 // All unknown; accept (caller didn't tag roles).
179 r.verdict = NX_LC_VERDICT_OK
180 return r
181 }
182 }
183 // 4 attached but wrong ratio.
184 r.verdict = NX_LC_VERDICT_WRONG_ARM_LEG_RATIO
185 return r
186 }
187 if r.n_attached > NX_LC_HUMAN_TOTAL {
188 r.verdict = NX_LC_VERDICT_EXTRA
189 return r
190 }
191 if r.n_attached == 3 {
192 r.verdict = NX_LC_VERDICT_MISSING
193 return r
194 }
195 r.verdict = NX_LC_VERDICT_FUSED
196 return r
197}
198
199// ===== self-test =================================================
200
201func _lc_set_candidate(arr: *NxLimbCandidate, idx: nx_int,
202 end_x: nx_int, end_y: nx_int, role: nx_int) -> nx_int {
203 let c: *NxLimbCandidate =
204 (arr as *u8 + (idx as nx_size) * NX_LIMB_CANDIDATE_BYTES) as *NxLimbCandidate
205 c.end_x = end_x
206 c.end_y = end_y
207 c.role = role
208 c.bbox_x0 = end_x - 20
209 c.bbox_y0 = end_y - 20
210 c.bbox_x1 = end_x + 20
211 c.bbox_y1 = end_y + 20
212 return 0
213}
214
215func main() -> nx_int {
216 // ---- OK human: 2 arms + 2 legs, all rooted in torso bbox ----
217 //
218 // Torso bbox (200, 100, 400, 400).
219 // Arms root at shoulders: (200, 150) and (400, 150).
220 // Legs root at hips: (220, 380) and (380, 380).
221 let arr_ok: *NxLimbCandidate =
222 (sys_mmap(NX_LIMB_CANDIDATE_BYTES * 4)) as *NxLimbCandidate
223 _lc_set_candidate(arr_ok, 0, 200, 150, NX_LIMB_ROLE_ARM)
224 _lc_set_candidate(arr_ok, 1, 400, 150, NX_LIMB_ROLE_ARM)
225 _lc_set_candidate(arr_ok, 2, 220, 380, NX_LIMB_ROLE_LEG)
226 _lc_set_candidate(arr_ok, 3, 380, 380, NX_LIMB_ROLE_LEG)
227 let r_ok: *NxLimbCountResult = nx_limb_count_check(
228 200, 100, 400, 400, arr_ok, 4, 10)
229 if r_ok == (0 as *NxLimbCountResult) { return 1 }
230 if r_ok.n_attached != 4 { return 2 }
231 if r_ok.n_floating != 0 { return 3 }
232 if r_ok.n_arms_attached != 2 { return 4 }
233 if r_ok.n_legs_attached != 2 { return 5 }
234 if r_ok.verdict != NX_LC_VERDICT_OK { return 6 }
235
236 // ---- EXTRA: 5 limbs all attached (the "three hands" failure
237 // visible when 2 arms + 2 legs + 1 extra arm floats but
238 // somehow attaches to torso) ----
239 let arr_ex: *NxLimbCandidate =
240 (sys_mmap(NX_LIMB_CANDIDATE_BYTES * 5)) as *NxLimbCandidate
241 _lc_set_candidate(arr_ex, 0, 200, 150, NX_LIMB_ROLE_ARM)
242 _lc_set_candidate(arr_ex, 1, 400, 150, NX_LIMB_ROLE_ARM)
243 _lc_set_candidate(arr_ex, 2, 220, 380, NX_LIMB_ROLE_LEG)
244 _lc_set_candidate(arr_ex, 3, 380, 380, NX_LIMB_ROLE_LEG)
245 _lc_set_candidate(arr_ex, 4, 300, 200, NX_LIMB_ROLE_ARM) // extra arm
246 let r_ex: *NxLimbCountResult = nx_limb_count_check(
247 200, 100, 400, 400, arr_ex, 5, 10)
248 if r_ex.n_attached != 5 { return 10 }
249 if r_ex.verdict != NX_LC_VERDICT_EXTRA { return 11 }
250 if r_ex.delta_from_norm != 1 { return 12 }
251
252 // ---- FLOATING_LIMB: 4 attached + 1 floating (the canonical
253 // "extra hand in space" failure where the extra limb
254 // doesn't trace to torso) ----
255 let arr_fl: *NxLimbCandidate =
256 (sys_mmap(NX_LIMB_CANDIDATE_BYTES * 5)) as *NxLimbCandidate
257 _lc_set_candidate(arr_fl, 0, 200, 150, NX_LIMB_ROLE_ARM)
258 _lc_set_candidate(arr_fl, 1, 400, 150, NX_LIMB_ROLE_ARM)
259 _lc_set_candidate(arr_fl, 2, 220, 380, NX_LIMB_ROLE_LEG)
260 _lc_set_candidate(arr_fl, 3, 380, 380, NX_LIMB_ROLE_LEG)
261 _lc_set_candidate(arr_fl, 4, 50, 50, NX_LIMB_ROLE_ARM) // far from torso
262 let r_fl: *NxLimbCountResult = nx_limb_count_check(
263 200, 100, 400, 400, arr_fl, 5, 10)
264 if r_fl.n_attached != 4 { return 20 }
265 if r_fl.n_floating != 1 { return 21 }
266 if r_fl.verdict != NX_LC_VERDICT_FLOATING_LIMB { return 22 }
267
268 // ---- MISSING: 3 attached (one arm missing) ----
269 let arr_mi: *NxLimbCandidate =
270 (sys_mmap(NX_LIMB_CANDIDATE_BYTES * 3)) as *NxLimbCandidate
271 _lc_set_candidate(arr_mi, 0, 200, 150, NX_LIMB_ROLE_ARM)
272 _lc_set_candidate(arr_mi, 1, 220, 380, NX_LIMB_ROLE_LEG)
273 _lc_set_candidate(arr_mi, 2, 380, 380, NX_LIMB_ROLE_LEG)
274 let r_mi: *NxLimbCountResult = nx_limb_count_check(
275 200, 100, 400, 400, arr_mi, 3, 10)
276 if r_mi.n_attached != 3 { return 30 }
277 if r_mi.verdict != NX_LC_VERDICT_MISSING { return 31 }
278
279 // ---- FUSED: 2 attached ----
280 let arr_fu: *NxLimbCandidate =
281 (sys_mmap(NX_LIMB_CANDIDATE_BYTES * 2)) as *NxLimbCandidate
282 _lc_set_candidate(arr_fu, 0, 200, 150, NX_LIMB_ROLE_ARM)
283 _lc_set_candidate(arr_fu, 1, 220, 380, NX_LIMB_ROLE_LEG)
284 let r_fu: *NxLimbCountResult = nx_limb_count_check(
285 200, 100, 400, 400, arr_fu, 2, 10)
286 if r_fu.verdict != NX_LC_VERDICT_FUSED { return 40 }
287
288 // ---- WRONG_ARM_LEG_RATIO: 4 attached but 3 arms + 1 leg ----
289 let arr_wr: *NxLimbCandidate =
290 (sys_mmap(NX_LIMB_CANDIDATE_BYTES * 4)) as *NxLimbCandidate
291 _lc_set_candidate(arr_wr, 0, 200, 150, NX_LIMB_ROLE_ARM)
292 _lc_set_candidate(arr_wr, 1, 400, 150, NX_LIMB_ROLE_ARM)
293 _lc_set_candidate(arr_wr, 2, 300, 200, NX_LIMB_ROLE_ARM) // 3rd arm
294 _lc_set_candidate(arr_wr, 3, 380, 380, NX_LIMB_ROLE_LEG)
295 let r_wr: *NxLimbCountResult = nx_limb_count_check(
296 200, 100, 400, 400, arr_wr, 4, 10)
297 if r_wr.n_attached != 4 { return 50 }
298 if r_wr.n_arms_attached != 3 { return 51 }
299 if r_wr.n_legs_attached != 1 { return 52 }
300 if r_wr.verdict != NX_LC_VERDICT_WRONG_ARM_LEG_RATIO { return 53 }
301
302 // ---- OK with all-unknown roles (caller didn't tag) ----
303 let arr_un: *NxLimbCandidate =
304 (sys_mmap(NX_LIMB_CANDIDATE_BYTES * 4)) as *NxLimbCandidate
305 _lc_set_candidate(arr_un, 0, 200, 150, NX_LIMB_ROLE_UNKNOWN)
306 _lc_set_candidate(arr_un, 1, 400, 150, NX_LIMB_ROLE_UNKNOWN)
307 _lc_set_candidate(arr_un, 2, 220, 380, NX_LIMB_ROLE_UNKNOWN)
308 _lc_set_candidate(arr_un, 3, 380, 380, NX_LIMB_ROLE_UNKNOWN)
309 let r_un: *NxLimbCountResult = nx_limb_count_check(
310 200, 100, 400, 400, arr_un, 4, 10)
311 if r_un.verdict != NX_LC_VERDICT_OK { return 60 }
312 if r_un.n_unknown_attached != 4 { return 61 }
313
314 return 0
315}