"""A small friendly ghost for Tidewater (built live on stream 2026-10-10): round head, a sheet that flares to a flexible hem, dark oval eyes and an 'o' mouth, two stubby arms. +x is where it looks. ~0.6 m tall. -> ghost.json Claude Opus 5.5 (Tessel).""" import json from pathlib import Path SHEET = "#f4f6fb" prims = [] def add(name, shape, size, pos=None, rot=None, **kw): p = {"name": name, "shape": shape, "size": [round(v, 4) for v in size], "texture": "blank", "color": SHEET, **kw} if pos is not None: p["pos"] = [round(v, 4) for v in pos] p["rot"] = rot or [0, 0, 0] p["physics_shape"] = "none" prims.append(p) soft = dict(glow=0.05, alpha=0.92) add("Little ghost", "sphere", [0.3, 0.3, 0.3], **soft) # head (root) # body: a cone flaring down from the head, hollow underneath add("sheet", "cylinder", [0.42, 0.42, 0.38], [0, 0, -0.15], top_size=[0.6, 0.6], hollow=0.9, **soft) # hem: scallops round the bottom edge, the classic ghost sheet import math for i in range(8): a = 2 * math.pi * (i + 0.5) / 8 add(f"scallop {i}", "sphere", [0.12, 0.12, 0.1], [0.19 * math.cos(a), 0.19 * math.sin(a), -0.34], **soft) for s, side in ((1, "L"), (-1, "R")): add(f"eye {side}", "sphere", [0.035, 0.05, 0.075], [0.137, s * 0.05, 0.03], color="#1b1b24", shiny="low") add(f"arm {side}", "sphere", [0.08, 0.06, 0.16], [0.03, s * 0.2, -0.12], [s * -35, 0, 0], **soft) add("mouth", "sphere", [0.025, 0.04, 0.05], [0.142, 0, -0.04], color="#1b1b24") spec = {"name": "Little ghost", "desc": "A friendly ghost by Tessel the AI (Claude). Touch it.", "defaults": {"bump": "none"}, "prims": prims} Path(__file__).with_name("ghost.json").write_text(json.dumps(spec, indent=1)) print(len(prims), "prims")