Commit Graph

3 Commits

Author SHA1 Message Date
swipelab
02d856275c P17.2: organic fall — per-column stagger (cascade pour)
render_fall now offsets each COLUMN's drop START by a small bounded delay
(fall_stagger_t) so a refilled/collapsed row pours in as a left-to-right cascade
instead of every gem snapping down in one flat lockstep row. Column col waits
FALL_STAGGER_MAX (0.30) * col/7 of the fall window, then falls over the remaining
1 - 0.30, with that local progress fed through ease_in_cubic so each column still
accelerates under gravity within its own window.

Bounded by construction: the last column lands EXACTLY at t=1 and every earlier
column strictly before it, so no gem is ever left mid-air at the segment end — the
seam to the next round / settled board stays invisible and move.final is untouched.

FALL_ANIM_DUR (0.22s) and the timeline helpers (phase/total/cascade_rounds_started)
are unchanged, so the per-round cascade-cue timing snapshots don't churn and live
per-round audio is unaffected. Render-only — no board.sx model change.

tests/easing.sx pins fall_stagger_t: f(0)=0, f(1)=1 across all columns (no gem
unlanded), per-column monotonicity, and the mid-fall cascade ordering (each later
column strictly behind the one before). tests/anim_plan.sx (final==model,
contiguity) stays green.

Golden goldens/p17_stagger.png: M3TE_FX=11 (depth-5 cascade, seed 1337) pinned at
M3TE_ANIM_TIME=1.91 — round 4 refills columns 2-7 by one cell each, so the top row
reads as a left-to-right staircase (vs the pre-stagger flat row in p17_fall.png).
2026-06-06 11:35:36 +03:00
swipelab
4d06097b08 P16.2: organic illegal swap — springy bounce-back (+ M3TE_BADSWAP hook)
render_swap's rejected-swap branch now drives the two gems with a P15.1
spring-based bounce-back (bad_swap_bounce): a quick lunge toward the
neighbour, then a damped spring home that overshoots rest by a bounded
amount and settles to exactly 0. f(0)=f(1)=0, so the move stays purely
visual — board byte-identical to pre-swap, no score/move spent.

- board_anim.sx: add bad_swap_bounce envelope (lunge via ease_out_cubic,
  settle via 1 - spring(u)); BADSWAP_LUNGE_T/AMP constants.
- board_view.sx: replace the linear ping-out illegal branch with the bounce.
- main.sx: add illegal_swaps (complement of legal_swaps, same row-major
  order) + the startup-only M3TE_BADSWAP=n capture hook; mirrors M3TE_FX.
- tests/easing.sx: append bounce-envelope assertions (endpoints, single
  lunge peak + location, damped settle); regenerate expected snapshot.
- README.md: document the M3TE_BADSWAP recipe + goldens/p16_badswap.png.

Gate green: ios-sim build links, 22 logic snapshots pass (anim_plan model
invariants unchanged; SWAP_ANIM_DUR untouched so cascade-cue snapshots do
not churn).
2026-06-06 11:01:45 +03:00
swipelab
1a8360ec1d P15.1: add extended easing toolkit + determinism snapshot (sx)
Pure, headless easing curves of t in [0,1] for the organic-animation pass
(swap/fall/combine juice), placed alongside the existing ease_out_cubic /
ease_in_quad in board_anim.sx: ease_in_cubic, ease_in_out_cubic, ease_out_back
(bounded overshoot, settles to exactly 1), spring (damped wobble to exactly 1),
and squash_envelope (signed squash-&-stretch landing shape). The math module has
no exp/pow, so the decaying curves use a (1-t)^n polynomial envelope that hits 0
at t==1, pinning f(1) precisely.

Additive only: no render code calls the new curves yet. tests/easing.sx locks,
per curve, the endpoints, overshoot/undershoot bounds, and monotonicity-where-
required (booleans only, so the snapshot is platform-stable), structured so P16.2
can append illegal-swap bounce-back assertions. Test count 21 -> 22.
2026-06-06 10:16:02 +03:00