P23-03: 生活の観察

This commit is contained in:
Agent Control Runner
2026-10-15 18:01:00 +09:00
parent 49445d4a4d
commit 19fc3f50c7
8 changed files with 1888 additions and 71 deletions
+59
View File
@@ -56,6 +56,61 @@ func run() -> void:
view.size = Vector2(1440, 810)
view.set_runtime(runtime)
root.add_child(view)
# R13's four same-cell MOVING guests. Component fixture only, no Runtime edit.
var crowd: Array = []
var offsets := [0, 16, -16, 8]
for i: int in 4:
crowd.append({&"row": {&"key": "guest/os-p23-%03d" % (12+i),
&"center": Vector2(108+offsets[i], 118-4*(i%2)),
&"at": Vector2(84+offsets[i], 103-4*(i%2)), &"scale": 3.0,
&"mode": &"idle", &"frame": 0, &"flip": false,
&"state": GuestRuntime.State.MOVING, &"cell": Vector3i(1,1,0)},
&"bounds": Rect2(80,74,56,88), &"transit": false})
crowd.sort_custom(func(a: Dictionary, b: Dictionary) -> bool: return a[&"row"][&"center"].x < b[&"row"][&"center"].x)
# _life_pack uses the view's cell dimensions for the unchanged feet formula.
# The x-capacity assertion is independent of the current default world size.
expect(view._life_pack(crowd, 3).is_empty(), "four cores cannot fit 72px in 56px")
var saved_size := view.size
var saved_zoom := view.zoom_level
var dim: Vector2 = view._cell_dimensions()
view.zoom_level *= 64.0/dim.x
var fitted: Array = view._life_pack(crowd, 2)
expect(fitted.size() == 4, "all four R13 occupants fit at p=2")
for row: Dictionary in fitted:
expect(row[&"scale"] == 2.0 and row[&"cell"] == Vector3i(1,1,0), "fitting preserves cell and uses p=2")
var regroup: Array = crowd.slice(0, 2).duplicate(true)
for i: int in 2:
regroup[i][&"row"][&"center"] = Vector2(108, 118+26*i)
regroup[i][&"bounds"] = Rect2(80,74,20,130)
var regrouped: Array = view._life_fitted_groups(regroup)
expect(regrouped.size() == 2, "scale change splits vertical component")
for group: Array in regrouped:
expect(group.size() == 1 and group[0][&"row"][&"scale"] == 2.0, "regroup avoids stale p=1 fit")
var saturated: Array = []
for i: int in 10:
var member: Dictionary = crowd[0].duplicate(true)
member[&"row"][&"key"] = "guest/saturation-%02d" % i
member[&"row"][&"center"] = Vector2(108,118)
saturated.append(member)
var saturated_groups: Array = view._life_fitted_groups(saturated)
expect(saturated_groups.size() == 1, "saturation keeps one vertical component")
expect(view._life_pack(saturated_groups[0], 1).is_empty(), "ten cores cannot fit 60px in 56px")
expect(view._life_pack(saturated_groups[0].slice(0,9), 1).size() == 9, "nine cores fit without losing identities")
var aggregate_model := {&"guests": [], &"staff": [], &"actor_drawings": [], &"cabins": []}
var aggregate_rows: Array = []
for member: Dictionary in saturated:
var row: Dictionary = member[&"row"].duplicate(true)
row[&"riding"] = true
aggregate_rows.append(row)
aggregate_model[&"guests"].append({&"id": String(row[&"key"]).trim_prefix("guest/"), &"cell": Vector3i(1,1,0)})
aggregate_model[&"cabins"].append({&"rect": Rect2(76,70,64,96), &"passengers": aggregate_rows})
view._fit_life_actors(aggregate_model)
expect(aggregate_model[&"cabins"][0][&"passengers"].size() == 9, "aggregation draws all nine fitting members")
var aggregate: Dictionary = aggregate_model[&"actor_aggregations"][0]
expect(aggregate[&"members"].size() == 10 and aggregate[&"drawn_keys"].size() == 9, "aggregation retains every identity")
expect(aggregate[&"text"] == "+1" and aggregate[&"at"] == Vector2(80,74), "actual aggregation badge position and text")
view.zoom_level = saved_zoom
view.size = saved_size
var before: PackedByteArray = var_to_bytes(runtime.create_snapshot())
var tracks: PackedByteArray = var_to_bytes([view._actor_tracks, view._elevator_tracks])
var model := view._build_life_observation()
@@ -67,6 +122,10 @@ func run() -> void:
await process_frame
var report := view.get_life_observation_report()
expect(not report.is_empty(), "actual drawing published an observation")
expect(report.get(&"observation_serial", -1) == report.get(&"overlay_consumed_serial", -2), "LifeOverlay consumed this observation")
expect(report.get(&"overlay_passes", []) == [&"traffic", &"actors"], "traffic drawn before actors")
var indices: Array = report.get(&"overlay_child_indices", [])
expect(indices.size() == 3 and indices[0] < indices[1] and indices[1] < indices[2], "LifeOverlay above inactive art and below lens")
# The getter exposes the last actual draw and must not create another model.
var original: PackedByteArray = var_to_bytes(report)
if report.has(&"traffic"):