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).
12 lines
606 B
Plaintext
12 lines
606 B
Plaintext
== endpoints locked ==
|
|
ease_in true ease_in_out true back true spring true squash true existing true
|
|
== monotonic where required ==
|
|
ease_in true ease_in_out true ease_out_cubic true ease_in_quad true
|
|
== overshoot bounded + settles ==
|
|
back_overshoots true back_bounded true spring_overshoots true spring_bounded true spring_wobbles true
|
|
== squash envelope bounded ==
|
|
squash_moves true squash_two_sided true squash_bounded true
|
|
== illegal-swap bounce ==
|
|
bounce_ends true peak_amp true peak_loc true overshoots true overshoot_bounded true settles true
|
|
ok: easing toolkit endpoints locked + amplitudes bounded
|