{
"id": "055",
"prompt": "A ball that gets tired: it flies, bounces, and every floor hit steals energy (vy damped 7/8 and vx rubbed down by friction) until it nearly stops — then it gets kicked again with a fresh LCG-random speed so the show never ends. rustlite has no structs and locals die each frame, so keep x, y (in 1/16-px fixed point), vx, vy, an init latch and the LCG seed in state slots.",
"solution_rl": "fn iabs(v: i32) -> i32 {\n if v < 0 { 0 - v } else { v }\n}\n\nfn frame(t: i32) {\n let w: i32 = host::display::width();\n let h: i32 = host::display::height();\n if host::display::state_get(0) == 0 {\n host::display::state_set(0, 1);\n host::display::state_set(1, 20 * 16);\n host::display::state_set(2, 20 * 16);\n host::display::state_set(3, 50);\n host::display::state_set(4, 0);\n }\n let mut x: i32 = host::display::state_get(1);\n let mut y: i32 = host::display::state_get(2);\n let mut vx: i32 = host::display::state_get(3);\n let mut vy: i32 = host::display::state_get(4);\n vy = vy + 4;\n x = x + vx;\n y = y + vy;\n if x < 0 { x = 0; vx = 0 - vx; }\n if x > (w - 14) * 16 { x = (w - 14) * 16; vx = 0 - vx; }\n let floor: i32 = (h - 16) * 16;\n if y > floor {\n y = floor;\n vy = (0 - vy) * 7 / 8;\n vx = vx * 7 / 8;\n }\n if y == floor && iabs(vx) < 3 && iabs(vy) < 6 {\n let seed: i32 = host::display::state_get(5) * 1103515245 + 12345;\n host::display::state_set(5, seed);\n let mut kick: i32 = (seed >> 16) % 60;\n if kick < 0 { kick = 0 - kick; }\n vx = kick + 30;\n vy = 0 - 90;\n }\n host::display::state_set(1, x);\n host::display::state_set(2, y);\n host::display::state_set(3, vx);\n host::display::state_set(4, vy);\n host::display::clear(0x000000);\n host::display::fill_rect(0, h - 2, w, 2, 0x306030);\n host::display::fill_rect(x / 16, y / 16, 14, 14, 0xff8800);\n host::display::present();\n}\n",
"tags": [
"physics",
"state",
"prng",
"no-struct-boundary"
]
}